<<

Building a (Core) Foundation Rob Napier A little background

• Mac OS X since 10.4 • iPhoneOS since release • Cisco Jabber, The Daily, RNCryptor • Focus on low-level • Today: Mac developer for...

KACE NAPIER KUMAR Bookstore Category COMPUTERS/PROGRAMMING/SOFTWARE DEVELOPMENT ROB NAPIER MUGUNTH KUMAR

BUILD AMAZING MOBILE APPS WITH THE iOS SDK 5 PROGRAMMING iOS iOS 5 Programming Pushing the Limits is your total guide to creating standout apps for the iPad, iPhone, and iPod Touch. Veteran mobile developers Rob Napier and Mugunth Kumar take you beyond the basics to cover advanced topics you won’t find in most other iOS development books. From the ins and outs of the Core Foundation API, to maximizing speed and performance with , to storyboarding your UI flow, they guide you step by step through all the knotty stuff you need to master to program fun, fully-functional, high-performance apps. Topics include: Interacting with the Objective-® Runtime Using advanced text layout with Introspecting objects and modifying classes Creating complex reusable table view layouts iOS 5 at runtime Using blocks to implement functional programming Controlling multitasking Creating high performance apps for any RESTful web service Running on multiple platforms Implementing superfast caching for regions with spotty Making optimal use of Security Services network connectivity PROGRAMMING Creating amazing animations Optimizing cash flow with In-App Purchases

Why settle for adequate mobile apps when you can create extraordinary ones? Get iOS 5 Programming Pushing the Limits and expand your development horizons. PUSHING THE LIMITS Visit www.wiley.com/go/ptl/ios5programming to download code files. PUSHING THEPUSHING LIMITS ROB NAPIER has been developing for iOS platforms since the first SDK release, working on products such as The Daily and Cisco Mobile. Advanced Application Development He is a major contributor to Stack Overflow and writes the Cocoaphony blog (cocoaphony.com). for Apple iPhone®, iPad®, and iPod Touch® MUGUNTH KUMAR is an independent iOS consultant working on a variety of iOS apps, including some for Goodyear and Mastercard. Two of his apps have reached the Top 5 apps in the Singapore and have been featured in various magazines and newspapers. He writes iOS tutorials on his blog, blog.mugunthkumar.com.

Cover design by Dan Jubb Price £29.99//US$44.99/CAN$53.99

Chapter 19 Core Foundation?

• Data structures for all those powerful frameworks with “Core” in their name. • The awesomeness of Objective-C. The speed of C. Where are we?*

UIKit

Foundation

Core Foundation

Core OS / Darwin

*Simplified, but close enough Who cares?

• You want to use those powerful frameworks, right? • Did I mention, it can do a lot of things Cocoa can’t? • And C is fast. Yes, very fast. The Path

• The real types • Memory management • Introspection • Strings • Collections • Toll-free • ARC The Path

• The real types • Memory management • Introspection • Strings • Collections • Toll-free Bridging • ARC Real Types

typedef void * CFTypeRef; typedef const struct __CFString * CFStringRef; typedef struct __CFString * CFMutableStringRef; The Path

• The real types • Memory management • Introspection • Strings • Collections • Toll-free Bridging • ARC Memory Management

• If you Create or Copy an object, you are an owner • If you do not Create or Copy an object, you are not an owner. • If you want to prevent the object from being destroyed, you must become an owner by calling CFRetain() • If you are an owner of an object, you must call CFRelease() when you are done with it CFRelease != -release

• CFRelease makes us cry • CFRelease(NULL) crashes • There are a dozen wrappers on CFRelease() that fix that • You will certainly make your own • And call them SAFE_RELEASE() like everyone else autorelease?

• There is no autorelease :( Allocators

• How you want your memory? CFCreateBlah(Allocator, param, param) • 99.9% of the time you want NULL • Sometimes you want kCFAllocatorMalloc for memory that was created with malloc() • Occasionally you want kCFAllocatorNull to do nothing • Everything else is incredibly obscure The Path

• The real types • Memory management • Introspection • Strings • Collections • Toll-free Bridging • ARC Introspection

•CFGetTypeID() <=> CFArrayGetTypeID() •CFCopyDescription() •CFShow() •CFShowStr() The Path

• The real types • Memory management • Introspection • Strings • Collections • Toll-free Bridging • ARC Strings

• Constants: CFSTR() CFStringRef foo = CFSTR(“foo”); •CFStringCreateWithCString() Convert CFStringRef to cstring

char * MYCFStringCopyUTF8String(CFStringRef aString) { if (aString == NULL) { return NULL; } CFIndex length = CFStringGetLength(aString); CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8); char *buffer = (char *)malloc(maxSize); if (CFStringGetCString(aString, buffer, maxSize, kCFStringEncodingUTF8)) { return buffer; } free(buffer); return NULL; } Convert non-const cstring to CStringRef

Consider the ownership: const char *cstr = “Hello”; char * = malloc(strlen(cstr) + 1); strcpy(bytes, cstr);

CFStringRef str = CFStringCreateWithCStringNoCopy(NULL, bytes, kCFStringEncodingUTF8, kCFAllocatorMalloc); CFShow(str); CFRelease(str); The Path

• The real types • Memory management • Introspection • Strings • Collections • Toll-free Bridging • ARC CFArray

CFStringRef strings[3] = { CFSTR(“One”), CFSTR(“Two”), CFSTR(“Three”) }; CFArrayRef array = CFArrayCreate(NULL, (void *)strings, 3, &kCFTypeArrayCallBacks); CFShow(array); CFRelease(array);

CFMutableArrayRef array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); CFDictionary

#define kCount 3 CFStringRef keys[kCount] = { CFSTR(“One”), CFSTR(“Two”), CFSTR(“Three”) }; CFStringRef values[kCount] = { CFSTR(“Foo”), CFSTR(“Bar”), CFSTR(“Baz”) }; CFDictionaryRef dict = CFDictionaryCreate(NULL, (void *)keys, (void *)values, kCount, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); Others

•CFTree •CFBinaryHeap •CFBitVector Callbacks

•retain •release •copyDescription •equal •hash Non-retaining CFArray

CFArrayCallBacks nrCallbacks = kCFTypeArrayCallBacks; nrCallbacks.retain = NULL; nrCallbacks.release = NULL; CFMutableArrayRef nrArray = CFArrayCreateMutable(NULL, 0, &nrCallbacks);

CFStringRef string = CFStringCreateWithCString(NULL, “Stuff”, kCFStringEncodingUTF8); CFArrayAppendValue(nrArray, string); CFRelease(nrArray); CFRelease(string); The Path

• The real types • Memory management • Introspection • Strings • Collections • Toll-free Bridging • ARC Toll-free Bridging

NSArray *nsArray = [NSArray arrayWithObject:@”Foo”]; printf(“%ld\n”, CFArrayGetCount((__bridge CFArrayRef)nsArray));

CFMutableArrayRef cfArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); CFArrayAppendValue(cfArray, CFSTR(“Foo”)); NSLog(@”%ld”, [(__bridge id)cfArray count]); CFRelease(cfArray); How does that even work?

ObjC: typedef struct objc_object { Class isa; } *id; CF: typedef struct __CFRuntimeBase { uintptr_t _cfisa ... } The CF Magic

CFIndex CFStringGetLength(CFStringRef str) { CF_OBJC_FUNCDISPATCH0(__kCFStringTypeID, CFIndex, str, “length”); __CFAssertIsString(str); return __CFStrLength(str) } The Path

• The real types • Memory management • Introspection • Strings • Collections • Toll-free Bridging • ARC Converting to ARC

- (NSString *)firstName { CFStringRef cfString = CFStringCreate...; return CFBridgingRelease(cfString); }

CFStringRef cfStr = CFBridgingRetain([nsString copy]); ... CFRelease(cfStr); Bringing It Home

• Core Foundation is your friend • 90% of Core Foundation is Foundation minus autorelease (and minus ARC) • Core Foundation, as a rule, is more flexible and faster than the ObjC equivalent • Go Forth and Core! http://iosptl.com