Skip to content

Instantly share code, notes, and snippets.

@CodaFi

CodaFi/Exam.md Secret

Last active July 6, 2023 04:19
Show Gist options
  • Save CodaFi/d2fa0ad00cb226558f80aa49a3b82262 to your computer and use it in GitHub Desktop.
Save CodaFi/d2fa0ad00cb226558f80aa49a3b82262 to your computer and use it in GitHub Desktop.
A short quiz to expose some gaps in knowledge about Objective-C. Please don't use this to interview somebody.

Multiple Choice Questions:

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) Exceptions, Errors, and Handling

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) Objective-C Objects

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) ARC

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) Runtime Wrangling

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) Language Constructs

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 a nonatomic property does ensure integrity.
  • c) The synthesized body of a nonatomic property does not ensure integrity of the returned value, while an atomic property does ensure integrity.
  • d) The synthesized bodies of atomic properties are threadsafe, while the synthesized bodies of nonatomic 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 of MyProtocol.
  • b) It indicates the NSObject protocol is an ancestor of MyProtocol.
  • c) It indicates that only objects can conform to MyProtocol.
  • d) It indicates that only NSObject can conform to MyProtocol.

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 values YES and NO.
  • c) It may be dangerous because BOOL can take on more values than just YES and NO.
  • 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 to nil.
  • 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.

Free Form:

1) (Toll Free) Bridging

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"?

2) Auto Release Pools

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?

3) ARC In Depth

Should an IBOutlet property be declared weak or strong? Justify your response. Does your response also apply to IBOutletCollection?

4) Attributes

Why is the -CGColor property of NSColor and UIColor marked with NS_RETURNS_INNER_POINTER (__attribute((objc_returns_inner_pointer)))?

5) Blocks

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 ...

Challenge Questions:

Two-Step Initialization?

Give an example of a class where +alloc is required but not necessarily -init?

A Walk On The Wild Side

// 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);

Impish Delights

Describe a possible implementation of imp_implementationWithBlock. What considerations must be taken into account for write XOR execute memory protected systems like Darwin OSes?

@dsheikherev
Copy link

Where can we find the answers ? 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment