Unless otherwise noted, all questions assume a working installation of clang
running on a modern 64-bit Mac with Automatic Reference Counting enabled in a
modern runtime.
1.1 What is Cocoa’s policy around catching exceptions thrown by frameworks?
- a) Exceptions thrown by frameworks are fatal and should never be caught.
- b) Exceptions thrown by frameworks can be fatal, but should be caught to prevent the program from crashing.
- c) Exceptions thrown by frameworks are rarely fatal and can be caught and thrown liberally.
- d) Exceptions thrown by frameworks are never fatal and can even be used to properly structure code.
1.2 Can NSAssert be disabled in release builds.
- a) No, NSAssert cannot be disabled.
- b) NSAssert will be optimized away in release builds and is therefore disabled.
- c) NSAssert can be disabled by defining a condition at build time.
1.3 What will be the outcome of compiling and then executing the following program?
@import Foundation;
@interface CFIFruitList : NSObject
@property (nonatomic, copy) NSMutableArray<NSString *> *fruitNames;
@end
@implementation CFIFruitList
- (instancetype)init {
self = [super init];
if (self) {
NSMutableArray *favoriteFruits = [@[ @"Apple", @"Banana", @"Pear", @"Orange", @"Peach" ] mutableCopy];
self.fruitNames = favoriteFruits;
}
return self;
}
- (void)removeAName {
if (self.fruitNames.count == 0) return;
[self.fruitNames removeObjectAtIndex:self.fruitNames.count - 1];
}
@end
int main(int argc, char **argv) {
CFIFruitList *fruitList = [[CFIFruitList alloc] init];
[fruitList removeAName];
return EXIT_SUCCESS;
}
- a) This program will run without any errors.
- b) This program will fail to compile and so will not run.
- c) This program will crash at runtime.
1.4 For a method with the following signature:
- (BOOL)performOperationWithError:(NSError **)error;
Assuming a canonical invocation of this method, how is error
passed at runtime?
- a)
error
is passed by value because the pointer value is copied during the call. - b)
error
is passed by reference because it is a pointer value. - c)
error
is passed by writeback because it is__autoreleasing
.
2.1 Which of the following is the the proper declaration of a convenience initializer?
- a)
+ (instancetype)foo;
- b)
- (instancetype)foo;
- c)
+ (instancetype)initWithBar:(Bar*)bar;
- d)
- (instancetype)initWithBar:(Bar*)bar;
2.2 What occurs when messaging an object that is nil
?
- a) A runtime crash occurs.
- b) An exception is thrown.
- c) Nothing happens.
2.3 What occurs when sending a non-nil object a message for a selector it does not implement?
- a) The compiler enforces all message sends, so this is impossible.
- b) An exception is thrown.
- c) Nothing happens.
2.4 For a non-nil user-defined Objective-C object, foo
, what is the result of evaluating the expression *(__bridge void **)foo
?
- a) A crash occurs.
- b) The class metadata of the object is obtained.
- c) A pointer to the first instance variable of the object is obtained.
3.1 Does the following code cause a retain cycle? If so, why? If not, why not?
- a) Yes, it leaks
self
because the method call-doSomethingElse
causes the block to capture self. - b) Yes, it leaks
self
because of the call to NSParameterAssert. - c) No, ARC will automatically break any potential retain cycle here.
- d) No, it does not leak because a weak reference to self is captured by the block.
__weak id weakSelf = self;
self.someProperty = ^ (BOOL someFlag) {
id self = weakSelf;
NSParameterAssert(someFlag);
[self doSomethingElse];
};
3.2 What is the name of the rule whereby user-allocated CoreFoundation objects are the responsibility of the caller to release?
- a) "The
CFRelease
Rule" - b) "The Create Rule"
- c) "The
malloc
-free
Rule"
3.3 Which of the three bridging casts (__bridge
, __bridge_retained
, __bridge_transfer
)
releases its operand after the cast is performed?
- a)
__bridge
- b)
__bridge_retained
- c)
__bridge_transfer
3.4 Which of the three bridging casts (__bridge
, __bridge_retained
, __bridge_transfer
)
retains its operand after the cast is performed?
- a)
__bridge
- b)
__bridge_retained
- c)
__bridge_transfer
3.5 Which statement about Automatic Reference Counting is most correct?
- a) Automatic Reference Counting manages memory completely. All variables do not require any manual reference balancing.
- b) Automatic Reference Counting generally manages the memory of most types, but some manual reference balancing may be required.
- c) Automatic Reference Counting is a form of runtime garbage collection.
4.1 A selector (SEL
) is:
- a) A unique runtime-relevant name for an Objective-C method.
- b) The part of a method declaration after the return type.
- c) A unique pointer to a particular Objective-C method.
- d) A function pointer.
4.2 Where may the Objective-C runtime allocate blocks?
- a) Blocks are Objective-C objects and so are allocated on the heap.
- b) Blocks are Objective-C objects and so are allocated on the stack.
- c) Blocks are magical and never require any allocation.
- d) Blocks may appear on both the heap and the stack.
4.3 How may times will +initialize
be called by the runtime?
- a)
+initialize
will be called exactly once by the runtime. - b)
+initialize
can be called many times by the runtime. - c)
+initialize
will never be called by the runtime and must be invoked manually.
4.4 What is meant by a "Non-Fragile Runtime ABI"?
- a) A runtime that never changes between releases.
- b) The ability to add instance variables to a class without recompilation of subclasses.
- c) A runtime that doesn't ever break.
4.5 Observe the following code declared in a framework linked with and loaded by a program:
// MyFramework.h
@interface NSObject (NoExceptionMessaging)
- (void)doesNotRecognizeSelector:(SEL)aSelector;
@end
// MyFramework.m
@implementation NSObject (NoExceptionMessaging)
- (void)doesNotRecognizeSelector:(SEL)aSelector { }
@end
4.6 What is a possible behavior the program may encounter if it attempts to send an object a message with a selector it does not respond to:
- a) The program will crash.
- b) The receiving object will respond to the selector.
- c) The program will execute unhindered.
- d) All of the above.
4.7 What is the Runtime Type Encoding of the signature of an instance method that takes
no arguments and returns void
?
- a) "v@:"
- b) "" (the empty string)
- c) "v@*"
- d) "@@:"
5.1 In the context of methods in the init family, what is a difference, if any, between id
and instancetype
.
- a) There is no difference.
- b)
id
is more typesafe,instancetype
is not typesafe. - c)
instancetype
is more typesafe,id
is not typesafe.
5.2 Which is the most correct definition of a top-level constant of type NSString *
?
- a)
NSString * MyConstant = @"";
- b)
const NSString * MyConstant = @"";
- c)
NSString *const MyConstant = @"";
- d)
const NSString *const MyConstant = @"";
5.3 What is a difference, if any, between properties marked atomic
and those marked nonatomic
?
- a) There is no meaningful difference.
- b) The synthesized body of an
atomic
property does not ensure integrity of the returned value, while anonatomic
property does ensure integrity. - c) The synthesized body of a
nonatomic
property does not ensure integrity of the returned value, while anatomic
property does ensure integrity. - d) The synthesized bodies of
atomic
properties are threadsafe, while the synthesized bodies ofnonatomic
properties are not threadsafe.
5.4 True or False, @synthesize
is required for the proper declaration of object properties.
- a) True
- b) False
5.5 What is the role of NSObject
in the declaration of the protocol below?
@protocol MyProtocol <NSObject, NSCopying>
- (void)doTheThing;
@end
- a) It indicates the
NSObject
class is an ancestor ofMyProtocol
. - b) It indicates the
NSObject
protocol is an ancestor ofMyProtocol
. - c) It indicates that only objects can conform to
MyProtocol
. - d) It indicates that only
NSObject
can conform toMyProtocol
.
5.6 Why might an explicit comparison to YES
, as in the code below, be dangerous?
/// ... omitted for brevity
if ([@"abcdefghijklmnopqrstuvwxyz" containsString:@"abc"] == YES) { /**/ }
/// ... omitted for brevity
- a) It is not dangerous because the expression always returns
YES
and the implicit form should be used for clarity. - b) It is not dangerous because
BOOL
can only take on the valuesYES
andNO
. - c) It may be dangerous because
BOOL
can take on more values than justYES
andNO
. - d) It may be dangerous because
-containsString:
does not take string encoding into account during the comparison.
5.7 Why might an explicit comparison to nil
be necessary instead of a cast?
/// ... omitted for brevity
- (BOOL)doMagic:(Magic *)magic {
return (BOOL)magic;
}
/// ... omitted for brevity
- a) The explicit comparison is not necessary because
magic
is always non-null. - b) The explicit comparison is not necessary because
magic
will automatically be compared tonil
. - c) The explicit comparison is necessary because the cast may slice
magic
. - d) The explicit comparison is necessary because
magic
is an Objective-C object, not just a C pointer.
Briefly describe a possible implementation of a bridged CoreFoundation-to-Objective-C type. What considerations must be made to ensure the bridging is "toll-free"?
Why might wrapping a tight loop in an @autoreleasepool
make looping code more
performant? In general, which part of the loop should be wrapped, the inside of
the loop body or the entire loop itself?
Should an IBOutlet
property be declared weak
or
strong
? Justify your response. Does your response also apply to IBOutletCollection
?
Why is the -CGColor
property of NSColor
and UIColor
marked with
NS_RETURNS_INNER_POINTER
(__attribute((objc_returns_inner_pointer))
)?
Where does the &x
"live", the stack or the heap? Justify your answer.
/// Class details omitted ...
- (void)foo {
__block int x = 0;
int *pointerToX = &x;
int (^block)() = ^{
x += 1;
return x;
};
}
/// Class details omitted ...
Give an example of a class where +alloc
is required but not necessarily -init
?
// 1) What type do I have?
// 2) Implement me to return a value of the proper type. (Invoke the callback in the appropriate location.)
void (^callback(NSInteger, void (^fp)(NSInteger)))(NSInteger);
Describe a possible implementation of imp_implementationWithBlock
. What considerations must be taken into account for write XOR execute memory protected systems like Darwin OSes?
Where can we find the answers ? 🙂