Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Understanding Objective-C Inside and Out

Jeff Kelley
September 27, 2013

Understanding Objective-C Inside and Out

How many times have you tried to debug something in Objective-C without really knowing *why* it works a certain way? Do you start sweating when Xcode throws linker errors your way, or when you have to mix ARC and non-ARC code? This talk will reveal how Objective-C works, what actually happens when your application is linked, and reveal what ARC is actually doing. Objective-C is a 30-year-old language, and it’s evolving faster than ever. We’ll look at the basics of the language, how properties and categories work, and cover advanced topics like creating classes at runtime, memory management and ARC, and tagged pointers. At the end of the talk, you’ll be able to diagnose issues with your app more quickly, dive into system components more readily, and have a better sense of why your code works.

Jeff Kelley

September 27, 2013
Tweet

More Decks by Jeff Kelley

Other Decks in Programming

Transcript

  1. Understanding Objective-
    C Inside and Out
    CocoaConf Columbus, September 27th, 2013
    Jeff Kelley
    @SlaunchaMan
    Saturday, September 28, 13

    View full-size slide

  2. Who?
    Saturday, September 28, 13

    View full-size slide

  3. Objective-C’s Beginning
    • Developed by Brad Cox and Tom Love in
    the early 1980s
    • Originally OOPC, or Object Oriented Pre-
    Compiler
    • Was originally a C precompiler!
    • Acquired by NeXT in 1995
    • Apple now owns Objective-C rights
    Saturday, September 28, 13

    View full-size slide

  4. Why Objective-C?
    • Compatibility with existing C code
    • Originally developed to work alongside
    telecom C code
    • Brings in the object-oriented nature of
    Smalltalk
    Saturday, September 28, 13

    View full-size slide

  5. Smalltalk
    | bigNumber |
    bigNumber := 42 factorial
    'helloWorld' indexOf: $o startingAt: 6
    Saturday, September 28, 13

    View full-size slide

  6. Early Objective-C
    Saturday, September 28, 13

    View full-size slide

  7. Early Objective-C
    • Tim Berners-Lee wrote the first web
    browser, WorldWideWeb, on a NeXT
    Cube in Objective-C in 1989/1990
    • Let’s look at some source code!
    Saturday, September 28, 13

    View full-size slide

  8. Early Objective-C
    - readPrintInfo
    /*
    * Sets the margin fields from the Application-wide PrintInfo.
    */
    {
    id pi;
    float conversion, dummy;
    NXCoord left, right, top, bottom;
    [super readPrintInfo];
    pi = [NXApp printInfo];
    [self convertOldFactor:&conversion newFactor:&dummy];
    [pi getMarginLeft:&left right:&right top:&top bottom:&bottom];
    [leftMargin setFloatValue:left * conversion];
    [rightMargin setFloatValue:right * conversion];
    [topMargin setFloatValue:top * conversion];
    [bottomMargin setFloatValue:bottom * conversion];
    return self;
    }
    Saturday, September 28, 13

    View full-size slide

  9. Why do we still use it?
    • C is powerful
    • C is fast
    • Apple owns it
    • See recently-developed features:
    properties, ARC, blocks, literals
    • What else would we use?
    Saturday, September 28, 13

    View full-size slide

  10. Cargo Cults
    Saturday, September 28, 13

    View full-size slide

  11. Today’s Agenda
    • Why do I get all these weird linker errors?
    • objc_msgSend() keeps crashing!
    • Why can’t I add an instance variable in a
    category?
    • How can Apple still be using Objective-C?
    Saturday, September 28, 13

    View full-size slide

  12. Weird Linker Errors
    • Can freeze a new Objective-C programmer
    in his or her tracks
    • Simple, but cryptic error messages
    • Cross-library troubles
    Saturday, September 28, 13

    View full-size slide

  13. Demo
    Saturday, September 28, 13

    View full-size slide

  14. What happens when
    you send a message?
    •objc_msgSend()
    • Hey, I see that in my crash logs all the
    time! They should work on that!
    • Found in
    • If you want to pass an argument, you need
    to cast it
    • Useful for calling private APIs
    Saturday, September 28, 13

    View full-size slide

  15. Calling Private API
    Let’s call -recursiveDescription on a view.
    NSString *recursiveDescription =
    objc_msgSend(self.window,
    @selector(recursiveDescription));
    Saturday, September 28, 13

    View full-size slide

  16. Calling Private API
    • OK, that was easy. But what if something
    takes an argument? Or returns a C
    primitive?
    • You get to cast objc_msgSend() to the
    appropriate function type
    Saturday, September 28, 13

    View full-size slide

  17. Casting objc_msgSend()
    NSArray *myArray = @[ @1, @2, @3 ];
    NSUInteger (*unsignedIntegerMessage)(id obj, SEL message) =
    (NSUInteger (*)(id, SEL))objc_msgSend;
    NSUInteger count =
    unsignedIntegerMessage(myArray, @selector(count));
    Saturday, September 28, 13

    View full-size slide

  18. Casting objc_msgSend()
    • Hey, that looks like block syntax!
    • C function pointer syntax was here first
    • Don’t do this with other functions—this
    one is expecting it
    • Lots of hand-written assembly code per
    platform in objc_msgSend()
    Saturday, September 28, 13

    View full-size slide

  19. objc_msgSend() Family
    • id objc_msgSend(id self, SEL op, ...);
    • id objc_msgSendSuper(id self, SEL op, ...);
    • long double objc_msgSend_fpret(id self, SEL op, ...);
    • void objc_msgSend_stret(id obj, SEL op, ...);
    Saturday, September 28, 13

    View full-size slide

  20. objc_msgSend() Family
    • 64-bit iOS:
    •objc_msgSend(id self, SEL op, ...);
    Saturday, September 28, 13

    View full-size slide

  21. So what does
    objc_msgSend() do?
    • Every Objective-C method compiles to a C
    implementation, or IMP
    • These are looked up by name (the
    selector) and cached for performance
    • “Objective-C is slow”
    • objc_msgSend() finds the IMP and calls it
    • So if the stack explodes, you see it
    Saturday, September 28, 13

    View full-size slide

  22. Why is this useful?
    • Implement two Objective-C methods with
    one underlying C function
    • Override - (IMP)methodForSelector:
    (SEL)aSelector;
    • Or graft existing C functionality to
    Objective-C
    • Method Swizzling
    Saturday, September 28, 13

    View full-size slide

  23. Method Swizzling
    • If you need to modify behavior of a class
    you don’t own (like UIView), you can
    replace a method implementation with one
    of your own
    • A combination of class_addMethod()
    and method_setImplementation()
    Saturday, September 28, 13

    View full-size slide

  24. Demo
    Saturday, September 28, 13

    View full-size slide

  25. Objects and Instance
    Variables
    • Why can’t I add an instance variable in a
    category?
    • Where am I supposed to add instance
    variables, anyway?
    Saturday, September 28, 13

    View full-size slide

  26. What is an Object?
    • From :
    typedef struct objc_object {
    Class isa;
    } *id;
    • It’s just a C struct!
    • Well, not recently.
    • You can do object->instanceVariable
    Saturday, September 28, 13

    View full-size slide

  27. Memory Layout
    • Objective-C objects are laid out like structs
    • First member is always the isa pointer
    • Points to class
    • So to know where an instance variable is,
    we need to know the entire hierarchy
    • Therefore, we can’t add anything in a
    category
    Saturday, September 28, 13

    View full-size slide

  28. Why do we always use
    pointers?
    • With a complex object hierarchy, hundreds
    of instance variables might be on one class
    • Can’t make all these objects on the stack
    • Would use too much memory
    • Would die with the stack
    • All objects are created on the heap, we use
    pointers to find them
    Saturday, September 28, 13

    View full-size slide

  29. Reference Counting
    • How do we know when to free the
    memory an object is using?
    • Despite how we talk about it, the system is
    not as complicated as you might think
    • Objects don’t really know about each
    other, they just store pointers to them
    • Retain/release used based on simple rules
    Saturday, September 28, 13

    View full-size slide

  30. ARC
    • ARC is a simple system of rules
    • Placing an object’s address in a pointer
    variable? Retain it.
    • A pointer variable containing an object’s
    address falls out of scope or is getting a new
    value? Release it.
    • The method starts with alloc, new, copy, or
    create? Autorelease it instead.
    Saturday, September 28, 13

    View full-size slide

  31. ARC
    • ARC adds an optimization layer on top of
    these simple rules to get really fast
    • objc_retain() faster than [object
    retain];
    Saturday, September 28, 13

    View full-size slide

  32. What if my category
    needs storage?
    • Objective-C is really good at looking up
    values in storage
    • Honed through the message dispatch
    system
    • Associated objects API allows arbitrary
    storage of object associations
    • objc_setAssociatedObject() and friends
    Saturday, September 28, 13

    View full-size slide

  33. Demo
    Saturday, September 28, 13

    View full-size slide

  34. Places to Add Instance
    Variables
    • The public header
    @interface MyClass : NSObject {
    id obj;
    }
    • Encourages direct instance variable access
    by others, should be avoided
    • Use a property instead
    Saturday, September 28, 13

    View full-size slide

  35. Places to Add Instance
    Variables
    • The implementation block
    @implementation MyClass {
    id obj;
    }
    • Limits access to implementation file
    • Property access is still safer, but with
    ARC this is reasonably safe
    Saturday, September 28, 13

    View full-size slide

  36. Places to Add Instance
    Variables
    • The class extension
    @interface MyClass() {
    id obj;
    }
    • If you’re also adding methods in the class
    extension, it’s only logical to place these
    here as well
    Saturday, September 28, 13

    View full-size slide

  37. Dynamic Classes
    • No, really, I need to modify the behavior of
    an object at runtime.
    • Apple already does this with KVO
    • So how do they do it?
    Saturday, September 28, 13

    View full-size slide

  38. KVO in Action
    • First, the API creates a subclass of your
    class at runtime:
    Class mySubclass =
    objc_allocateClassPair([NSObject
    class], "MySubclass", 0);
    Saturday, September 28, 13

    View full-size slide

  39. KVO in Action
    • Second, the API sets your object to this
    new class
    object_setClass(object,
    mySubclass);
    • DO NOT set the isa pointer directly
    •object->isa = mySubclass;
    Saturday, September 28, 13

    View full-size slide

  40. KVO in Action
    • Third, the API implements the method(s) it
    wants to override:
    - (void)setFoo:(id)foo
    {
    NSLog(@"About to set foo!");
    [super setFoo:foo];
    NSLog(@"Set foo!");
    }
    Saturday, September 28, 13

    View full-size slide

  41. KVO in Action
    • Finally, the API overrides -class to hide
    what it’s done
    • So -isMemberOfClass: still works for the
    original class
    Saturday, September 28, 13

    View full-size slide

  42. Why would I need to
    do this?
    • Here’s an actual, real-life example of
    dynamic subclassing: Kiwi mocks
    • In Kiwi, the BDD test framework, you can
    stub a method like this:
    •[viewController
    stub:@selector(view)
    andReturn:thisMockView];
    Saturday, September 28, 13

    View full-size slide

  43. Why would I need to
    do this?
    • In production applications, you won’t need
    to do this too often
    • But in testing, it’s invaluable
    Saturday, September 28, 13

    View full-size slide

  44. So How is Apple Still
    Using Objective-C?
    • As KVO illustrates, Objective-C is
    extremely capable of runtime hackery
    • As the sole owner, Apple is free to make
    insane improvements to the language
    • Tagged Pointers
    • The isa pointer in 64-bit iOS
    • Excellent tool development in LLVM/Clang
    Saturday, September 28, 13

    View full-size slide

  45. Tagged Pointers
    • A pointer to an object will, due to
    alignment, have some extra bits
    • The last bit is always 0… or is it?
    • Apple sets the last bit to 1 and uses the
    remaining bits to store integers
    • Looks and acts just like an NSNumber, but
    needs no additional storage
    Saturday, September 28, 13

    View full-size slide

  46. Tagged Pointers
    • Don’t try to set the isa pointer. Bad things
    will happen.
    • Best-case scenario: compiler error.
    • 64-bit iOS means we get tagged pointers
    • Performance/memory gains for free!
    Saturday, September 28, 13

    View full-size slide

  47. 64-Bit iOS isa Pointer
    http://www.sealiesoftware.com/blog/
    Saturday, September 28, 13

    View full-size slide

  48. LLVM
    Saturday, September 28, 13

    View full-size slide

  49. LLVM/Clang
    Optimizations
    • Link-Time Optimization
    • Applies compiler optimizations across
    source files, leading to huge potential
    gains
    • New optimization level -Ofast
    • Not suitable for scientific applications
    that need precise floating-point values
    Saturday, September 28, 13

    View full-size slide

  50. Where is Objective-C
    Going?
    • Recent Objective-C developments have
    made developing faster
    • Auto-synthesized property accessors
    • ARC
    • Packages
    • Object Literals
    Saturday, September 28, 13

    View full-size slide

  51. Where is Objective-C
    Going?
    • Recent Objective-C developments have
    reduced the cognitive load of the language
    • ARC
    • Packages
    • Properties
    Saturday, September 28, 13

    View full-size slide

  52. Where is Objective-C
    Going?
    • Future developments will likely continue
    down these paths
    • My suggestion: get rid of pointers
    • “What? Are you crazy?”
    • The compiler is smart enough to re-
    insert them where needed
    Saturday, September 28, 13

    View full-size slide

  53. Q&A
    Saturday, September 28, 13

    View full-size slide

  54. References
    • http://en.wikipedia.org/wiki/Objective-C
    • http://en.wikipedia.org/wiki/Tim_Berners-Lee
    • http://www.mikeash.com/pyblog/friday-qa-2013-09-27-
    arm64-and-you.html
    • http://www.sealiesoftware.com/blog/archive/2013/09/24/
    objc_explain_Non-pointer_isa.html
    • https://twitter.com/marcoarment/status/
    383083874676641792
    • http://llvm.org/docs/LinkTimeOptimization.html
    Saturday, September 28, 13

    View full-size slide