Objective-C Interview Questions and Answers
Practice Objective-C interview questions and answers organized by difficulty, with revealable explanations and related topics.
Entry questions
1 questions- Question 1Entry
Name four important data types found in Objective-C
- Objective-C
Reveal answerHide answer
Four data types that you’ll definitely want your developer to be aware of are as follows: NSString : Represents a string. CGfloat : Represents a floating point value. NSInteger : Represents an integer. BOOL : Represents a boolean.
Junior questions
7 questions- Question 1Junior
What are Objective-C Categories?
- Objective-C
Reveal answerHide answer
Categories provide the ability to add functionality to an object without subclassing or changing the actual object. A handy tool, they are often used to add methods to existing classes, such as NSString or your own custom objects. A category can be declared for any class, even if you don't have the original implementation source code. Any methods that you declare in a category will be available to all instances of the original class, as well as any subclasses of the original class. At runtime, there's no difference between a method added by a category and one that is implemented by the original class. Consider a category to the Cocoa class NSString : #import <Foundation/Foundation.h>
@interface NSString(MyAdditions) +(NSString *)getCopyRightString; @end @implementation NSString(MyAdditions) +(NSString *)getCopyRightString { return @"Copyright TutorialsPoint.com 2013"; } @end int main(int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSString *copyrightString = [NSString getCopyRightString]; NSLog(@"Accessing Category: %@",copyrightString); [pool drain]; return 0; } - Question 2Junior
How to convert an NSArray to a string in Objective-C?
- Objective-C
Reveal answerHide answer
NSString * result = [[array valueForKey:@"description"] componentsJoinedByString:@""]; - Question 3Junior
What are Objective-C Categories?
- Objective-C
Reveal answerHide answer
Categories provide the ability to add functionality to an object without subclassing or changing the actual object. A handy tool, they are often used to add methods to existing classes, such as NSString or your own custom objects. A category can be declared for any class, even if you don't have the original implementation source code. Any methods that you declare in a category will be available to all instances of the original class, as well as any subclasses of the original class. At runtime, there's no difference between a method added by a category and one that is implemented by the original class. Consider a category to the Cocoa class NSString : #import <Foundation/Foundation.h>
@interface NSString(MyAdditions) +(NSString *)getCopyRightString; @end @implementation NSString(MyAdditions) +(NSString *)getCopyRightString { return @"Copyright TutorialsPoint.com 2013"; } @end int main(int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSString *copyrightString = [NSString getCopyRightString]; NSLog(@"Accessing Category: %@",copyrightString); [pool drain]; return 0; } - Question 4Junior
What is a protocol, and how do you define your own and when is it used?
- Objective-C
Reveal answerHide answer
A protocol is similar to an interface from Java. It defines a list of required and optional methods that a class must/can implement if it adopts the protocol. Any class can implement a protocol and other classes can then send messages to that class based on the protocol methods without it knowing the type of the class. @protocol MyCustomDataSource
- (NSUInteger)numberOfRecords; - (NSDictionary *)recordAtIndex:(NSUInteger)index; @optional - (NSString *)titleForRecordAtIndex:(NSUInteger)index; @endA common use case is providing a DataSource for UITableView or UICollectionView .
- Question 6Junior
Explain types of protocol in Objective-C
- Objective-C
Reveal answerHide answer
A formal protocol declares a list of methods that client classes are expected to implement. Formal protocols have their own declaration, adoption, and type-checking syntax. You can designate methods whose implementation is required or optional with the @required and @optional keywords. Subclasses inherit formal protocols adopted by their ancestors. A formal protocol can also adopt other protocols. Formal protocols are an extension to the Objective-C language. An informal protocol is a category on NSObject , which implicitly makes almost all objects adopters of the protocol. (A category is a language feature that enables you to add methods to a class without subclassing it.) Implementation of the methods in an informal protocol is optional. Before invoking a method, the calling object checks to see whether the target object implements it. Until optional protocol methods were introduced in Objective-C 2.0, informal protocols were essential to the way Foundation and AppKit classes implemented delegation.
- Question 7Junior
What is the difference between copy and retain ?
- Objective-C
Reveal answerHide answer
In a general setting, retaining an object will increase its retain count by one. This will help keep the object in memory and prevent it from being blown away. What this means is that if you only hold a retained version of it, you share that copy with whomever passed it to you. Copying an object, however you do it, should create another object with duplicate values. Think of this as a clone. You do NOT share the clone with whomever passed it to you.
- Question 8Junior
What are blocks and how are they used?
- Objective-C
Reveal answerHide answer
Blocks are a way of defining a single task or unit of behavior without having to write an entire Objective-C class. Under the covers Blocks are still Objective C objects. They are a language level feature that allow programming techniques like lambdas and closures to be supported in Objective-C. Creating a block is done using the ^ {
} syntax: myBlock = ^{ NSLog(@"This is a block"); }It can be invoked like so:
myBlock();It is essentially a function pointer which also has a signature that can be used to enforce type safety at compile and runtime. For example you can pass a block with a specific signature to a method like so:
- (void)callMyBlock:(void (^)(void))callbackBlock;If you wanted the block to be given some data you can change the signature to include them:
- (void)callMyBlock:(void (^)(double, double))block { ... block(3.0, 2.0); }
Mid questions
14 questions- Question 1Mid
When to use NSArray vs NSSet ?
- Objective-C
Reveal answerHide answer
NSArray is faster than NSSet for simply holding and iterating. As little as 50% faster for constructing and as much as 500% faster for iterating. So if you only need to iterate contents, don't use an NSSet . Of course, if you need to test for inclusion, work hard to avoid NSArray . The reason is that a set uses hash values to find items (like a dictionary) while an array has to iterate over its entire contents to find a particular object. Even if you need both iteration and inclusion testing, you should probably still choose an NSSet . If you need to keep your collection ordered and also test for inclusion, then you should consider keeping two collections (an NSArray and an NSSet ), each containing the same objects.
- Question 2Mid
What's the difference between the atomic and nonatomic attributes?
- Objective-C
Reveal answerHide answer
Problem
What do atomic and nonatomic mean in property declarations?
@property(nonatomic, retain) UITextField *userName; @property(atomic, retain) UITextField *userName; @property(retain) UITextField *userName;What is the operational difference between these three?
Solution
Atomic is the default behavior will ensure the present process is completed by the CPU, before another process accesses the variable is not fast, as it ensures the process is completed entirely thread safe ues if the instance variable is gonna be accessed in a multithreaded environment. Non-Atomic is NOT the default behavior faster (for synthesized code, that is, for variables created using @property and @synthesize) not thread-safe may result in unexpected behavior, when two different process access the same variable at the same time use if the instance variable is not gonna be changed by multiple threads you can use it. It improves the performance. Suppose there is an atomic string property called "name", and if you call [self setName:@"A"] from thread A, call [self setName:@"B"] from thread B, and call [self name] from thread C, then all operations on different threads will be performed serially which means if one thread is executing a setter or getter, then other threads will wait. If the property "name" was nonatomic, then all threads in above example - A,B, C and D will execute simultaneously producing any unpredictable result. In case of atomic, either one of A, B or C will execute first, but D can still execute in parallel.
- Question 2Mid
What is the difference between NSDictionary and NSMutableDictionary ?
- Objective-C
Reveal answerHide answer
The key difference: NSMutableDictionary can be modified in place, NSDictionary cannot. This is true for all the other NSMutable* classes in Cocoa. NSMutableDictionary is a subclass of NSDictionary , so everything you can do with NSDictionary you can do with both. However, NSMutableDictionary also adds complementary methods to modify things in place, such as the method setObject:forKey: .
- Question 3Mid
How can I reverse a NSArray in Objective-C?
- Objective-C
Reveal answerHide answer
For reversing a mutable array, you can add the following category to your code:
@implementation NSMutableArray (Reverse) - (void)reverse { if ([self count] <= 1) return; NSUInteger i = 0; NSUInteger j = [self count] - 1; while (i < j) { [self exchangeObjectAtIndex:i withObjectAtIndex:j]; i++; j--; } } @endYou can also take advantage of the built-in reverseObjectEnumerator method on NSArray , and the allObjects method of NSEnumerator :
NSArray* reversedArray = [[startArray reverseObjectEnumerator] allObjects]; - Question 4Mid
What is Key-Value-Coding and Key-Value-Observing in Objective-C?
- Objective-C
Reveal answerHide answer
Key-Value-Coding (KVC) means accessing a property or value using a string.
id someValue = [myObject valueForKeyPath:@"foo.bar.baz"];Which could be the same as:
id someValue = [[[myObject foo] bar] baz]; Key-Value-Observing (KVO) allows you to observe changes to a property or value. To observe a property using KVO you would identify to property with a string; i.e., using KVC. Therefore, theobservable object must be KVC compliant. [myObject addObserver:self forKeyPath:@"foo.bar.baz" options:0 context:NULL];
- Question 5Mid
What mechanisms does iOS provide to support multi- threading?
- iOS Objective-C
Reveal answerHide answer
NSThread creates a new low-level thread which can be started by calling the start method. NSThread* myThread = [[NSThread alloc] initWithTarget:self
selector:@selector(myThreadMainMethod:) object:nil]; [myThread start];NSOperationQueue allows a pool of threads to be created and used to execute NSOperation s in parallel. NSOperation s can also be run on the main thread by asking NSOperationQueue for the mainQueue .
NSOperationQueue* myQueue = [[NSOperationQueue alloc] init]; [myQueue addOperation:anOperation]; [myQueue addOperationWithBlock:^{ /* Do something. */ }];GCD or Grand Central Dispatch is a modern feature of Objective-C that provides a rich set of methods and API's to use in order to support common multi-threading tasks. GCD provides a way to queue tasks for dispatch on either the main thread, a concurrent queue (tasks are run in parallel) or a serial queue (tasks are run in FIFO order). dispatch_queue_t myQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(myQueue, ^{ printf("Do some work here.\n"); }); - Question 9Mid
What are some limitations and problems you can face withcategories?
- Objective-C
Reveal answerHide answer
Advantages: You can extend any class, even those, for which you do not have the source. Look, for example, into the UI extensions added by Apple to the NSString class for rendering, getting the metrics, etc. Since you have access to all instance variables, categories provide you with a nice way to structure your code across compilation units using logical grouping instead of the “it must all be in one phyiscal place” approach taken, for example, by Java. Disadvantages: You cannot safely override methods already defined by the class itself or another category.
- Question 11Mid
What mechanisms does iOS provide to support multi- threading?
- iOS Objective-C
Reveal answerHide answer
NSThread creates a new low-level thread which can be started by calling the start method.
NSThread* myThread = [[NSThread alloc] initWithTarget:self
selector:@selector(myThreadMainMethod:) object:nil]; [myThread start];NSOperationQueue allows a pool of threads to be created and used to execute NSOperation s in parallel. NSOperation s can also be run on the main thread by asking NSOperationQueue for the mainQueue .
NSOperationQueue* myQueue = [[NSOperationQueue alloc] init]; [myQueue addOperation:anOperation]; [myQueue addOperationWithBlock:^{ /* Do something. */ }];GCD or Grand Central Dispatch is a modern feature of Objective-C that provides a rich set of methods and API's to use in order to support common multi-threading tasks. GCD provides a way to queue tasks for dispatch on either the main thread, a concurrent queue (tasks are run in parallel) or a serial queue (tasks are run in FIFO order). dispatch_queue_t myQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(myQueue, ^{ printf("Do some work here.\n"); }); - Question 13Mid
When would you use Categories over Inheritance and vice versa?
- Objective-C
Reveal answerHide answer
If you are adding functions, but not data, use a category. An example of this is adding functions to NSMutableData which allow you to remove X bytes from a section of the data, or remove all BUT X bytes from the data. It doesn't make sense to create an entire sub-class simply to add these two functions, nor does it makes sense to write functions that aren't attached to a class (a plain C function). This allows you to attach the functionality to the class without creating a new, uneeded relationship, and doesn't change any part of existing functionality. If you need to add/change data and add functionality to manipulate that data, or change functionality to represent a sub-type of object in your controller model, then you sub-class. For example, NSMutableData is a sub-class because it still uses NSData accessors, however, it changes the data representation internally so it can also manipulate the data. In this case a sub-class makes sense because it is no longer NSData , it is a /mutable/ NSData object (new keyword added to describe the object).
- Question 14Mid
What is the difference between inheritance and Categories in Objective-C?
- Objective-C
Reveal answerHide answer
Sometimes, Inheritance just seems like more trouble than it is worth. It is correctly used when you want to add something to an existing class that is a change in the behaviour of that class. With a Category, you just want the existing object to do a little more. As already given, if you just want to have a string class that handles compression, you don't need to subclass the string class, you just create a category that handles the compression. That way, you don't need to change the type of the string classes that you already use. Categories are a nice way to add functionality while at the same time conforming to an object oriented principle to prefer composition over inheritance.
- Question 15Mid
What is Key-Value-Coding and Key-Value-Observing in Objective-C?
- Objective-C
Reveal answerHide answer
Key-Value-Coding (KVC) means accessing a property or value using a string.
id someValue = [myObject valueForKeyPath:@"foo.bar.baz"];Which could be the same as:
id someValue = [[[myObject foo] bar] baz]; Key-Value-Observing (KVO) allows you to observe changes to a property or value. To observe a property using KVO you would identify to property with a string; i.e., using KVC. Therefore, theobservable object must be KVC compliant. [myObject addObserver:self forKeyPath:@"foo.bar.baz" options:0 context:NULL];
- Question 17Mid
What is difference between these three classes [NSManagedObject, NSManagedObjectContext, NSManagedObjectModel] of CoreData?
- Objective-C
Reveal answerHide answer
In database terms:
NSManagedObject = a row NSManagedObjectContext = a transaction NSManagedObjectModel = a schemaOf course, Core Data isn't a database.
- Question 18Mid
What is the purpose of managed object context NSManagedObjectContext in Objective-C and how does it work?
- Objective-C
Reveal answerHide answer
You can think of a managed object context as an intelligent scratch pad. When you fetch objects from a persistent store, you bring temporary copies onto the scratch pad where they form an object graph (or a collection of object graphs). You can then modify those objects however you like. Unless you actually save those changes, however, the persistent store remains unaltered.
- Question 19Mid
How can I reverse a NSArray in Objective-C?
- Objective-C
Reveal answerHide answer
For reversing a mutable array, you can add the following category to your code:
@implementation NSMutableArray (Reverse) - (void)reverse { if ([self count] <= 1) return; NSUInteger i = 0; NSUInteger j = [self count] - 1; while (i < j) { [self exchangeObjectAtIndex:i withObjectAtIndex:j]; i++; j--; } } @endYou can also take advantage of the built-in reverseObjectEnumerator method on NSArray , and the allObjects method of NSEnumerator :
NSArray* reversedArray = [[startArray reverseObjectEnumerator] allObjects];
Expert questions
11 questions- Question 1Expert
What sending a message to nil means and how is it actually useful?
- Objective-C
Reveal answerHide answer
One thing you should be clear on is that in Objective-C, you don't call a method on an object, you send a message to an object. The runtime will find the method and call it. A message sent to a nil object is perfectly acceptable in Objective-C, it's treated as a no-op. There is no way to flag it as an error because it's not an error, in fact it can be a very useful feature of the language. From the docs: In Objective-C, it is valid to send a message to nil—it simply has no effect at runtime. There are several patterns in Cocoa that take advantage of this fact. The value returned from a message to nil may also be valid: If the method returns an object, then a message sent to nil returns 0 ( nil ), for example: Person
*motherInLaw = [[aPerson spouse] mother]; If aPerson ’s spouse is nil , then mother is sent to nil and themethod returns nil . If the method returns any pointer type, any integer scalar of size less than or equal to sizeof(void*) , a float , a double , a long double , or a long long , then a message sent to nil returns 0 . If the method returns a struct , as defined by the Mac OS X ABI Function Call Guide to be returned in registers, then a message sent to nil returns 0.0 for every field in the data structure. Other struct data types will not be filled with zeros. If the method returns anything other than the aforementioned value types the return value of a message sent to nil is undefined .
- Question 2Expert
What is Dynamic Dispatch and how does it work in Objective- C?
- Objective-C
Reveal answerHide answer
Method Dispatch is the mechanism that helps to decide which operation should be executed, or more specifically, which method implementation should be used. By default, Objective-C supports Dynamic dispatch. For every call to a method, in case of dynamic dispatch, our compiler will have to look inside what we call awitness table (virtual table or dispatch table in other languages) for checking the implementation of that particular method. The compiler needs to determine whether you referring to the superclasses’ implementation or are you referring to the implementation of the subclass. And since memory to all the objects is allocated at runtime, the compiler can only perform that check at runtime. Objective-C messages are dispatched using the runtime's objc_msgSend() function. Shown in the Apple docs, the function takes at least 2 arguments:
- The receiving object
- The selector of the message
- [A variable list of arguments to the message being sent.]
Instances of a class have an isa pointer, which is a pointer to their class object. The selectors of methods in each object are stored in a "table" in the class object, and the objc_msgSend() function follows the isa pointer to the class object, to the find this table, and checks whether the method is in the table for the class. If it cannot find it, it looks for the method in the table of the class's superclass. If not found, it continues up the object tree, until it either finds the method or gets to the root object ( NSObject ). At this point, an exception is thrown. To speed the messaging process, the runtime system caches the selectors and addresses of methods as they are used. There’s a separate cache for each class, and it can contain selectors for inherited methods as well as for methods defined in the class. Before searching the dispatch tables, the messaging routine first checks the cache of the receiving object’s class (on the theory that a method that was used once may likely be used again). If the method selector is in the cache, messaging is only slightly slower than a function call. Once a program has been running long enough to “warm up” its caches, almost all the messages it sends find a cached method. Caches grow dynamically to accommodate new messages as the program runs.
- Question 3Expert
What's the difference between marking a method as @objc vs dynamic , when would you do one vs the other?
- Objective-C Swift
Reveal answerHide answer
A function/variable declared as @objc is accessible from Objective-C, but Swift will continue to access it directly via static or virtual dispatch. This means if the function/variable is swizzled via the Objective-C framework, like what happens when using Key-Value Observing or the various Objective-C APIs to modify classes, calling the method from Swift and Objective-C will produce different results. Using dynamic tells Swift to always refer to Objective-C dynamic dispatch. This is required for things like Key- Value Observing to work correctly. When the Swift function is called, it refers to the Objective-C runtime to dynamically dispatch the call.
- Question 6Expert
Explain the use case when ARC won't help you to release memory (but GC will)?
- Objective-C iOS Swift
Reveal answerHide answer
As an example, if you have a class named node, and node has an NSArray of children, and a single reference to its parent that "just works" with GC. With ARC (and manual reference counting as well) you have a problem. Any given node will be referenced from its children and also from its parent. Like:
A -> [B1, B2, B3] B1 -> A, B2 -> A, B3 -> A All is fine while you are using A (say via a local variable).When you are done with it (and B1/B2/B3), a GC system will eventually decide to look at everything it can find starting from the stack and CPU registers. It will never find A,B1,B2,B3 so it will finalize them and recycle the memory into other objects. When you use ARC or MRC, and finish with A it have a refcount of 3 (B1, B2, and B3 all reference it), and B1/B2/B3 will all have a reference count of 1 (A's NSArray holds one reference to each). So all of those objects remain live even though nothing can ever use them. The common solution is to decide one of those references needs to be weak (not contribute to the reference count). That will work for some usage patterns, for example if you reference B1/B2/B3 only via A. However in other patterns it fails. For example if you will sometimes hold onto B1, and expect to climb back up via the parent pointer and find A. With a weak reference if you only hold onto B1, A can (and normally will) evaporate, and take B2, and B3 with it. You can also say ARC puts a bigger priority on performance (or maybe predictability) while GC puts a bigger priority on being a generic solution. As a result GC has less predictable CPU/memory demands, and a lower
performance (normally) than ARC, but can handle any usage pattern. ARC will work much better for many many common usage patterns, but for a few (valid!) usage patterns it will fall over and die. - Question 7Expert
Why and in which conditions should we use @autoreleasepool ?
- Objective-C iOS
Reveal answerHide answer
When you can ensure a specific thread is never making use of autoreleased objects, that thread wouldn't need an autorelease pool. Avoiding the autoreleasepool is a bad advice, the coin has two sides. Using autorelease'd objects carries a certain amount of overhead (although insignificant in most scenarios) that should be avoided when possible. Especially in cases where there are multiple exits to a method, or an exception can be encountered, autoreleasing helps avoiding memory leaks and makes code cleaner. Be aware though, that this means nothing on that thread can use autorelease, including any frameworks you may call. There are situations where this is the case, such as in a classic producer/consumer scenario. You have a producer that creates objects, dispatches them to the main threads runloop, and can register them in the main threads autoreleasepool consequently. In general, I would not recommend creating a thread where significant work is carried out (besides a simple, long running computation) without an autoreleasepool.
- Question 13Expert
Explain method swizzling. When you would use it?
- Objective-C
Reveal answerHide answer
Objective-C handles method dispatch at runtime. This allows the implementation for a selector (i.e., method) to be changed as a program executes. Method swizzling is the act of swapping the implementations of two selectors as a program runs. This dynamic program modification is similar to monkey patching, a concept supported by other dynamic languages. For example we swizzle the viewDidAppear method with another method that calls viewDidAppear and then print a log. Consider: #import #import "UIViewController+Logging.h"
@implementation UIViewController (Logging) + (void)load { static dispatch_once_t once_token; dispatch_once(&once_token, ^{ SEL viewWillAppearSelector = @selector(viewDidAppear:); SEL viewWillAppearLoggerSelector = @selector(logged_viewDidAppear:); Method originalMethod = class_getInstanceMethod(self, viewWillAppearSelector); Method extendedMethod = class_getInstanceMethod(self, viewWillAppearLoggerSelector); method_exchangeImplementations(originalMethod, extendedMethod); }); } - (void) logged_viewDidAppear:(BOOL)animated { [self logged_viewDidAppear:animated]; NSLog(@"logged view did appear for %@", [self class]); } @end - Question 14Expert
What are limitations of NSDictionary ?
- Objective-C
Reveal answerHide answer
NSDictionary provides a key-to-object mapping. In essence, NSDictionary stores the "objects" in locations indexed by the "keys". Since the objects are stored at specific locations, NSDictionary requires that the key's value doesn't change (otherwise the object would suddenly be at the wrong location for its key). To ensure this requirement is maintained, NSDictionary always copies the keys to its own private location. This key copying behavior is fundamental to how NSDictionary works but is also a limitation: you can only use an Objective-C object as a key in an NSDictionary if it supports the NSCopying protocol. Further, the key should be small and efficient enough that copying is does not burden CPU or memory. This means that NSDictionary is really only suited to "value"-type objects as keys (eg. small strings and numbers). It is not ideal for modelling mappings from fully fledged objects to other objects.
- Question 15Expert
What was wrong with the NSEnumerator technique and why NSFastEnumeration was introduced?
- Objective-C
Reveal answerHide answer
Back in old days, we had to use NSEnumerator to iterate through a collection:
NSEnumerator *enumerator = [strings objectEnumerator]; NSString *thing; while ((thing = [enumerator nextObject])) { NSLog (@"woo. %@", thing); } There really isn’t anything wrong with NSEnumerator . It’s just clumsy. You need to make an object (which requires a dynamic memory allocation). You then have to ask the enumerator nicely for each object (which requires an objective-C message send for each one). That’s a fair amount of overhead, especially if you’re iterating over small collections.NSFastEnumeration lets classes, both Apple’s and ours, figure out what’s the optimal way to iterate its contents. You can often avoid memory allocation as well as a message send for every single object in the collection. Plus it’s fewer lines of code and fewer additional local variables.
NSArray *strings = [NSArray arrayWithObjects: @"greeble", @"bork", @"hoover", nil]; for (NSString *thing in strings) { NSLog (@"Woo! %@", thing); } - Question 16Expert
Why and in which conditions should we use @autoreleasepool ?
- Objective-C iOS
Reveal answerHide answer
When you can ensure a specific thread is never making use of autoreleased objects, that thread wouldn't need an autorelease pool. Avoiding the autoreleasepool is a bad advice, the coin has two sides. Using autorelease'd objects carries a certain amount of overhead (although insignificant in most scenarios) that should be avoided when possible. Especially in cases where there are multiple exits to a method, or an exception can be encountered, autoreleasing helps avoiding memory leaks and makes code cleaner. Be aware though, that this means nothing on that thread can use autorelease, including any frameworks you may call. There are situations where this is the case, such as in a classic producer/consumer scenario. You have a producer that creates objects, dispatches them to the main threads runloop, and can register them in the main threads autoreleasepool consequently. In general, I would not recommend creating a thread where significant work is carried out (besides a simple, long running computation) without an autoreleasepool.
- Question 17Expert
Which is the best of GCD, NSThread or NSOperationQueue ?
- Objective-C iOS
Reveal answerHide answer
- Use NSThread (or even the pthreads API) when you want or need to have_ direct control over the threads you create_, e.g. you need fine-grained control over thread priorities or are interfacing with some other subsystem that vends/consumes thread objects directly and you need to stay on the same page with it. Such instances are rare, but they do occur, particularly in real-time applications.
- Use GCD when your task lends itself well to simple parallelization, e.g. you just want to toss some work "into the background" with very little additional work, you have some data structures that you merely wish to serialize access to (and serial queues are great for doing that in a lockless fashion), you have some for loops that would lend themselves well to parallelization with dispatch_apply(), you have some data sources / timers that GCD's sources API will enable you to deal with easily in the background, etc etc. GCD is quite powerful and you can use it for a lot more than this, but these are all relative 'no brainer' scenarios where you don't want to get caught up in the initialization and setup tasks so much as simply "do basic stuff in parallel".
- Use NSOperation when you're already up at the Cocoa API layer (vs writing in straight C to the POSIX APIs) and have more complex operations you want to parallelize. NSOperation allows for subclassing, arbitrarily complex dependency graphs, cancellation and a supports a number of other higher-level semantics that may be useful to you. NSOperation actually uses GCD under the covers so it's every bit as multi-core, multi-thread capable as GCD, though it also brings the Foundation framework along for the ride so if you're hacking at the POSIX layer, you probably want to use option #2.
- Question 20Expert
Explain the use case when ARC won't help you to release memory (but GC will)?
- Objective-C iOS Swift
Reveal answerHide answer
As an example, if you have a class named node, and node has an NSArray of children, and a single reference to its parent that "just works" with GC. With ARC (and manual reference counting as well) you have a problem. Any given node will be referenced from its children and also from its parent. Like:
A -> [B1, B2, B3] B1 -> A, B2 -> A, B3 -> A All is fine while you are using A (say via a local variable).When you are done with it (and B1/B2/B3), a GC system will eventually decide to look at everything it can find starting from the stack and CPU registers. It will never find A,B1,B2,B3 so it will finalize them and recycle the
memory into other objects. When you use ARC or MRC, and finish with A it have a refcount of 3 (B1, B2, and B3 all reference it), and B1/B2/B3 will all have a reference count of 1 (A's NSArray holds one reference to each). So all of those objects remain live even though nothing can ever use them. The common solution is to decide one of those references needs to be weak (not contribute to the reference count). That will work for some usage patterns, for example if you reference B1/B2/B3 only via A. However in other patterns it fails. For example if you will sometimes hold onto B1, and expect to climb back up via the parent pointer and find A. With a weak reference if you only hold onto B1, A can (and normally will) evaporate, and take B2, and B3 with it. You can also say ARC puts a bigger priority on performance (or maybe predictability) while GC puts a bigger priority on being a generic solution. As a result GC has less predictable CPU/memory demands, and a lower
performance (normally) than ARC, but can handle any usage pattern. ARC will work much better for many many common usage patterns, but for a few (valid!) usage patterns it will fall over and die.
Senior questions
10 questions- Question 3Senior
What happens when you invoke a method on a nil pointer?
- Objective-C
Reveal answerHide answer
One thing you should be clear on is that in Objective-C, you don't call a method on an object, you send a message to an object. The runtime will find the method and call it. A message sent to a nil object is perfectly acceptable in Objective-C, it's treated as a no-op. There is no way to flag it as an error because it's not an error, in fact it can be a very useful feature of the language. There's a lot of code that depends on this behavior. Messages to nil with return type | return
---------------------------------|--------Integers up to 64 bits | 0 Floating-point up to long double | 0.0 Pointers | nil
Structs | {0} Any _Complex type | {0, 0} - Question 4Senior
Explain the difference between interfaces, delegates, andprotocols in Objective-C
- Objective-C
Reveal answerHide answer
The point of a delegate is to be notified when another object does something. For example one of your objects wants to know that a window is being closed, so you register it as the window's delegate and implement the windowWillClose: method. It will be called by NSWindow appropriately. So the delegate methods are usually defined in another class. Up to a certain point, it lets you extend the functionality of a class without subclassing it. A protocol is not like a Java interface, a protocol is an adapter that allows two classes to works together. Basically it says, if you want class A to send you messages about its state and actions these are the methods it will call on its delegate that you must implement. Its not like an interface because an interface says if you want to subclass this class you must implement these methods, the protocol says if you want to interact with this class you must implement these methods, so its somewhat different. The @interface is the class declaration, where the member variables and methods are listed. It's located in the .h , that you import if you need to use the class. The code for methods sits in the @implementation in the .m file. In Java it's different, the .java file serves both purposes.
- Question 5Senior
What's the difference between using a delegate andnotification?
- iOS Objective-C
Reveal answerHide answer
Both are used for sending values and messages to interested parties. A Delegate is for one-to-one communication and is a pattern promoted by Apple. In delegation the class raising events will have a property for the delegate and will typically expect it to implement some protocol . The delegating class can then call the delegates protocol methods. Notification allows a class to broadcast events across the entire application to any interested parties. The broadcasting class doesn't need to know anything about the listeners for this event, therefore notification is very useful in helping to decouple components in an application.
[NSNotificationCenter defaultCenter] postNotificationName:@"TestNotification" object:self]; - Question 6Senior
What are the reasons for using NSOperationQueue over GCD and vice versa?
- Objective-C iOS
Reveal answerHide answer
GCD is a low-level C-based API. NSOperation and NSOperationQueue are Objective-C classes. NSOperationQueue is objective C wrapper over GCD . If you are using NSOperation, then you are implicitly using Grand Central Dispatch.
GCD advantage over NSOperation : i. implementation For GCD implementation is very light-weight NSOperationQueue is complex and heavy-weight NSOperation advantages over GCD: i. Control On Operation you can Pause, Cancel, Resume an NSOperation ii. Dependencies you can set up a dependency between two NSOperations operation will not started until all of its dependencies return true for finished. iii. State of Operation can monitor the state of an operation or operation queue. ready ,executing or finished iv. Max Number of Operation you can specify the maximum number of queued operations that can run simultaneously When to Go for GCD or NSOperation When you want more control over queue (all above mentioned) use NSOperation For simple cases where you want less overhead (you just want to do some work "into the background" with very little additional work) use GCD
- Question 7Senior
What is @autoreleasepool ?
- Objective-C iOS
Reveal answerHide answer
The concept of an autorelease pool is simple, whenever an object instance is marked as autoreleased (for example NSString* str = [[[NSString alloc] initWithString:@"hello"] autorelease]; ), it will have a retain count of +1 at that moment in time, but at the end of the run loop, the pool is drained, and any object marked autorelease then has its retain count decremented. It's a way of keeping an object around while you prepare whatever will retain it for itself. With ARC, whilst the autorelease keyword isn't used by the developer, the underlying system that manages ARC inserts that for you. (Remember: All ARC is doing is inserting retain , release and autorelease calls for you at the appropriate times). Because of this, the existing AutoreleasePool concept needs to stay around.
- Question 8Senior
How to create an abstract class in Objective-C?
- Objective-C
Reveal answerHide answer
There is no way to create an abstract class in Objective-C. There is no compile-time enforcement that prevents instantiation of an abstract class, however. In fact, there is nothing to stop a user from providing implementations of abstract methods via a category (i.e. at runtime). You can force a user to at least override certain methods by raising an exception in those methods implementation in your abstract class: You can mock an abstract class - by making the methods/ selectors call doesNotRecognizeSelector: and thereforeraise an exception making the class unusable.
For example:
- (id)someMethod:(SomeObject*)blah { [self doesNotRecognizeSelector:_cmd]; return nil; } You can also do this for init. Instead of trying to create an abstract base class, consider using a protocol (similar to a Java interface). This allows you to define a set of methods, and then accept all objects that conform to theprotocol and implement the methods.
- Question 9Senior
What is the difference between ARC (automatic reference counting) and GC (garbage collection)?
- Objective-C iOS Swift
Reveal answerHide answer
ARC rely on a compile time "referenced" objects which make it efficient in a low-power mode environments (Mobile devices). ARC injects a code into the executable to be executed "automatically" on unused objects depending on their reference count. Advantages: Real-time, deterministic destruction of objects as they become unused. No background processing. Disadvantages: ARC cannot handle retain cycles automatically. GC rely on a runtime based "reachable" objects which make it efficient in a multi-threaded environment. GC works in the runtime as it will detect the unused object graphs (will eliminate retain-cycles) and remove them on an indeterminate time intervals Advantages: GC can clean up entire object graphs, including retain cycles. GC proceed in the background, so less memory management work is done as part of the regular application flow. Disadvantages: Because GC happens in the background, the exact time frame for object releases is undetermined. When a GC happens, other threads in the application may be temporarily put on hold.
- Question 10Senior
What is the difference between NSMapTable vs NSDictionary ?
- Objective-C
Reveal answerHide answer
NSMapTable is a general-purpose analogue of NSDictionary . Contrasted with the behavior of NSDictionary / NSMutableDictionary , NSMapTable has the following characteristics: NSDictionary / NSMutableDictionary copies keys, and
holds strong references to values ( NSDictionaryrequires that the key's value doesn't change otherwise the object would suddenly be at the wrong location
for its key).NSMapTable is mutable, without an immutable counterpart. NSMapTable can hold keys and values with weak references, in such a way that entries are removed when either the key or value is deallocated. NSMapTable can copy its values on input. NSMapTable can contain arbitrary pointers, and use pointer identity for equality and hashing checks. NSMapTable (as the name implies) is more suited to mapping in a general sense. Depending on how it is constructed, NSMapTable can handle the "key-to-object" style mapping of an NSDictionary but it can also handle "object-to-object" mappings — also known as an "associative array" or simply a "map".
- Question 11Senior
What are the differences between implementing a @property with @dynamic or @synthesize ?
- Objective-C
Reveal answerHide answer
@synthesize will generate getter and setter methods for your property. @dynamic just tells the compiler that the getter and setter methods are implemented not by the class itself but somewhere else (like the superclass or will be provided at runtime). Uses for @dynamic are e.g. with subclasses of NSManagedObject (CoreData) or when you want to create an outlet for a property defined by a superclass that was not defined as an outlet. @dynamic also can be used to delegate the responsibility of implementing the accessors. If you implement the accessors yourself within the class then you normally do not use @dynamic . @dynamic also lets you create accessors for varaibles not defined in your class interface and through introspection. Super class:
@property (nonatomic, retain) NSButton *someButton; ... @synthesize someButton; Subclass: @property (nonatomic, retain) IBOutlet NSButton *someButton; ... @dynamic someButton; - Question 12Senior
Why delegate is never retained?
- Objective-C
Reveal answerHide answer
The reason that you avoid retaining delegates is that you need to avoid a retain cycle. Objective-C works with reference counts to keep the memory clean. This does mean that it can't detect cyclic relationships. Example: Object A owns object B. Object B is retained by object A. Object B has a delegate that is object A. Object A is retained by object B. Object C owns object A. Object A is retained by object C.
Object A now has a retainCount of 2, and object B has a retainCount of 1 Object C gets freed, and releases object A Object A and B now have a retainCount of 1, because they own eachother. The system will not free them, because the retainCount is still 1 (still owned by another object) Memory leak!