z, ? | toggle help (this) |
space, → | next slide |
shift-space, ← | previous slide |
d | toggle debug mode |
## <ret> | go to slide # |
c, t | table of contents (vi) |
f | toggle footer |
r | reload slides |
n | toggle notes |
p | run preshow |
P | toggle pause |
Boris Bügling - @NeoNacho
Mention OBJC2_UNAVAILABLE and opaqueness of some types
typedef struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
} *id;
An object is a C-struct with a pointer to its class and the ivars.
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE;
const char *name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE;
struct objc_method_list **methodLists OBJC2_UNAVAILABLE;
struct objc_cache *cache OBJC2_UNAVAILABLE;
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
Classes are opaque in the new runtime, but we still can learn from the old stuff. Cache: hash table from selectors to code. Talk about meta-classes.
[self doWithThing:thing];
objc_msgSend(self, @selector(doWithThing:), thing);
Keywords: message, selector, message send, method -- reality is a bit more complex as there is objmsgSendstret for structs and objmsgSendfpret for floating point - no longer true for arm64!
struct objc_method {
SEL method_name OBJC2_UNAVAILABLE;
char *method_types OBJC2_UNAVAILABLE;
IMP method_imp OBJC2_UNAVAILABLE;
}
typedef struct objc_selector *SEL;
typedef id (*IMP)(id self, SEL _cmd ,...);
SEL is an opaque type but basically a C string, sel_registerName
+(BOOL)resolveInstanceMethod:(SEL)aSEL;
-(void)forwardInvocation:(NSInvocation*)anInvocation;
-(NSMethodSignature*)methodSignatureForSelector:(SEL)sel;
-(BOOL)respondsToSelector:(SEL)aSelector;
unsigned int methodCount;
Method* methods = class_copyMethodList([NSObject class],
&methodCount);
for (int i = 0; i < methodCount; i++) {
SEL selector = method_getName(methods[i]);
char returnType[255];
method_getReturnType(methods[i], returnType, 255);
NSLog(@"%s %@", returnType,
NSStringFromSelector(selector));
}
Mention type encodings / @encode
Debugging
Key-Value Observation
Subclassing a class which isn't available in every OS release
Can also be done using weak linking
This method almost does the right thing
so let's patch it.
// Implementation by Mike Ash
void Swizzle(Class c, SEL orig, SEL new) {
Method origMethod = class_getInstanceMethod(c, orig);
Method newMethod = class_getInstanceMethod(c, new);
if (class_addMethod(c, orig,
method_getImplementation(newMethod),
method_getTypeEncoding(newMethod))) {
class_replaceMethod(c, new,
method_getImplementation(origMethod),
method_getTypeEncoding(origMethod));
} else {
method_exchangeImplementations(origMethod, newMethod);
}
}
UITableView(Custom)
-(void)myLayoutSubviews {
// [...] Implementation [...]
[self myLayoutSubviews];
}
- (void)attentionClassDumpUser:(id)arg1
yesItsUsAgain:(id)arg2
althoughSwizzlingAndOverridingPrivateMethodsIsFun:(id)arg3
itWasntMuchFunWhenYourAppStoppedWorking:(id)arg4
pleaseRefrainFromDoingSoInTheFutureOkayThanksBye:(id)arg5;
(thanks to @steipete for discovering this)
Class class = NSClassFromString(
@"UITableViewCellEditControl");
SEL originalSelector = NSSelectorFromString
(@"_toggleRotateAnimationDidStop:finished:");
SEL newSelector =
@selector(toggleMinusButtonAnimationDidStop:finished:);
IMP imp = imp_implementationWithBlock(^(id target) {
[target performSelector:newSelector];
[self toggleMinusButtonImageForControlView:target];
});
Method m = class_getInstanceMethod(class, originalSelector);
if (!class_addMethod(class, newSelector,
imp, method_getTypeEncoding(m))) {
return;
}
Swizzle(class, originalSelector, newSelector);
void objc_setAssociatedObject(
id object,
void *key, id value,
objc_AssociationPolicy policy);
id objc_getAssociatedObject(id object, void *key);
AssociationPolicy is the storage class (copy, retain, assign)
Using a message as an argument to another message.
NSArray* strings = @[ @"foo", @"candy" ];
NSLog(@"%@", [[strings collect]
stringByAppendingString:@"bar"]);
( "foobar", "candybar" )
@implementation HOM
-(void)forwardInvocation:(NSInvocation*)anInvocation {
id result = [xxTarget performSelector:xxSelector
withObject:anInvocation];
[anInvocation setReturnValue:&result];
}
-methodSignatureForSelector:(SEL)aSelector {
return [[xxTarget objectAtIndex:0]
methodSignatureForSelector:aSelector];
}
-xxinitWithTarget:aTarget selector:(SEL)newSelector {
xxTarget = aTarget;
xxSelector = newSelector;
return self;
}
@implementation NSArray(hom)
-(NSArray*)collect:(NSInvocation*)anInvocation {
NSMutableArray *resultArray = [NSMutableArray array];
for (id obj in self ) {
id resultObject;
[anInvocation invokeWithTarget:obj];
[anInvocation getReturnValue:&resultObject];
[resultArray addObject:resultObject];
}
return resultArray;
}
-collect {
return [HOM homWithTarget:self
selector:@selector(collect:)];
}
Me: @NeoNacho on Twitter and ADN
This talk: http://vu0.org/funtime/
Objective-C runtime source http://opensource.apple.com/source/objc4/
Source: only for OS X, not for iOS.
Objective-C runtime reference http://developer.apple.com
Mike Ash's Blog: http://www.mikeash.com/pyblog/
Greg Parker's Blog: http://sealiesoftware.com/blog/