Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update sample code for 2 chapter #2

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 38 additions & 30 deletions chapter_2/item_10.txt
Original file line number Diff line number Diff line change
@@ -1,42 +1,50 @@
// Item 10

// C early binding
#import <stdio.h>

void printHello() {
printf("Hello, world!\n");
- (void)askUserAQuestion {
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"Question" message:@"What do you want to do?"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"Continue",
nil];
[alert show];
}
void printGoodbye() {
printf("Goodbye, world!\n");
}

void doTheThing(int type) {
if (type == 0) {
printHello();
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
[self doCancel];
} else {
printGoodbye();
[self doContinue];
}
return 0;
}

#import <objc/runtime.h>

// C late binding
#import <stdio.h>
static void *EOCMyAlertViewKey = "EOCMyAlertViewKey";

void printHello() {
printf("Hello, world!\n");
- (void)askUserAQuestion {
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"Question" message:@"What do you want to do?"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"Continue",
nil];
void (^block)(NSInteger) = ^(NSInteger buttonIndex){
if (buttonIndex == 0) {
[self doCancel];
} else {
[self doContinue];
}
};

objc_setAssociatedObject(alert,
EOCMyAlertViewKey,
block,
OBJC_ASSOCIATION_COPY);
[alert show];
}
void printGoodbye() {
printf("Goodbye, world!\n");
}

void doTheThing(int type) {
void (*fnc)();
if (type == 0) {
fnc = printHello;
} else {
fnc = printGoodbye;
}
fnc();
return 0;
}
- (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
void (^block)(NSInteger) = objc_getAssociatedObject(alertView, EOCMyAlertViewKey);
block(buttonIndex);
}
120 changes: 28 additions & 92 deletions chapter_2/item_11.txt
Original file line number Diff line number Diff line change
@@ -1,106 +1,42 @@
// Item 11

// `resolveInstanceMethod' example
id autoDictionaryGetter(id self, SEL _cmd);
void autoDictionarySetter(id self, SEL _cmd, id value);
// C early binding
#import <stdio.h>

+ (BOOL)resolveInstanceMethod:(SEL)selector {
NSString *selectorString = NSStringFromSelector(selector);
if (/* selector is from a @dynamic property */) {
if ([selectorString hasPrefix:@"set"]) {
class_addMethod(self, selector, (IMP)autoDictionarySetter, "v@:@");
} else {
class_addMethod(self, selector, (IMP)autoDictionaryGetter, "@@:");
}
return YES;
}
return [super resolveInstanceMethod:selector];
}


// Full "AutoDictionary" example
#import <Foundation/Foundation.h>

@interface AutoDictionary : NSObject
@property (nonatomic, strong) NSString *string;
@property (nonatomic, strong) NSNumber *number;
@property (nonatomic, strong) NSDate *date;
@property (nonatomic, strong) id opaqueObject;
@end

#import "AutoDictionary.h"
#import <objc/runtime.h>

id autoDictionaryGetter(id self, SEL _cmd) {
// Get the backing store from the object
AutoDictionary *typedSelf = (AutoDictionary*)self;
NSMutableDictionary *backingStore = typedSelf.backingStore;

// The key is simply the selector name
NSString *key = NSStringFromSelector(_cmd);

// Return the value
return [backingStore objectForKey:key];
void printHello() {
printf("Hello, world!\n");
}
void printGoodbye() {
printf("Goodbye, world!\n");
}

void autoDictionarySetter(id self, SEL _cmd, id value) {
// Get the backing store from the object
AutoDictionary *typedSelf = (AutoDictionary*)self;
NSMutableDictionary *backingStore = typedSelf.backingStore;

/** The selector will be for example, "setOpaqueObject:".
* We need to remove the "set", ":" and lowercase the first
* letter of the remainder.
*/
NSString *selectorString = NSStringFromSelector(_cmd);
NSMutableString *key = [selectorString mutableCopy];

// Remove the `:' at the end
[key deleteCharactersInRange:NSMakeRange(key.length - 1, 1)];

// Remove the `set' prefix
[key deleteCharactersInRange:NSMakeRange(0, 3)];

// Lowercase the first character
NSString *lowercaseFirstChar = [[key substringToIndex:1] lowercaseString];
[key replaceCharactersInRange:NSMakeRange(0, 1) withString:lowercaseFirstChar];

if (value) {
[backingStore setObject:value forKey:key];
void doTheThing(int type) {
if (type == 0) {
printHello();
} else {
[backingStore removeObjectForKey:key];
printGoodbye();
}
return 0;
}

@interface AutoDictionary ()
@property (nonatomic, strong) NSMutableDictionary *backingStore;
@end

@implementation AutoDictionary
@dynamic string, number, date, opaqueObject;
// C late binding
#import <stdio.h>

- (id)init {
if ((self = [super init])) {
_backingStore = [NSMutableDictionary new];
}
return self;
void printHello() {
printf("Hello, world!\n");
}

+ (BOOL)resolveInstanceMethod:(SEL)selector {
NSString *selectorString = NSStringFromSelector(selector);
if ([selectorString hasPrefix:@"set"]) {
class_addMethod(self, selector, (IMP)autoDictionarySetter, "v@:@");
void printGoodbye() {
printf("Goodbye, world!\n");
}

void doTheThing(int type) {
void (*fnc)();
if (type == 0) {
fnc = printHello;
} else {
class_addMethod(self, selector, (IMP)autoDictionaryGetter, "@@:");
fnc = printGoodbye;
}
return YES;
}

@end


// Using AutoDictionary
AutoDictionary *dict = [AutoDictionary new];
dict.date = [NSDate dateWithTimeIntervalSince1970:475372800];
NSLog(@"dict.date = %@", dict.date);
// Output: dict.date = 1985-01-24 00:00:00 +0000
fnc();
return 0;
}
125 changes: 94 additions & 31 deletions chapter_2/item_12.txt
Original file line number Diff line number Diff line change
@@ -1,44 +1,107 @@
// Item 12
// Item 11

// Exchanging methods
Method originalMethod =
class_getInstanceMethod([NSString class],
@selector(lowercaseString));
Method swappedMethod =
class_getInstanceMethod([NSString class],
@selector(uppercaseString));
method_exchangeImplementations(originalMethod, swappedMethod);
// `resolveInstanceMethod' example
id autoDictionaryGetter(id self, SEL _cmd);
void autoDictionarySetter(id self, SEL _cmd, id value);

+ (BOOL)resolveInstanceMethod:(SEL)selector {
NSString *selectorString = NSStringFromSelector(selector);
if (/* selector is from a @dynamic property */) {
if ([selectorString hasPrefix:@"set"]) {
class_addMethod(self, selector, (IMP)autoDictionarySetter, "v@:@");
} else {
class_addMethod(self, selector, (IMP)autoDictionaryGetter, "@@:");
}
return YES;
}

return [super resolveInstanceMethod:selector];
}

// Using the method exchanging of NSString
NSString *string = @"ThIs iS tHe StRiNg";

NSString *lowercaseString = [string lowercaseString];
NSLog(@"lowercaseString = %@", lowercaseString);
// Output: lowercaseString = THIS IS THE STRING
// Full "EOCAutoDictionary" example
#import <Foundation/Foundation.h>

NSString *uppercaseString = [string uppercaseString];
NSLog(@"uppercaseString = %@", uppercaseString);
// Output: uppercaseString = this is the string
@interface EOCAutoDictionary : NSObject
@property (nonatomic, strong) NSString *string;
@property (nonatomic, strong) NSNumber *number;
@property (nonatomic, strong) NSDate *date;
@property (nonatomic, strong) id opaqueObject;
@end

#import "EOCAutoDictionary.h"
#import <objc/runtime.h>

// Using a category and then swizzling methods
@interface NSString (MyAdditions)
- (NSString*)myLowercaseString;
@interface EOCAutoDictionary ()
@property (nonatomic, strong) NSMutableDictionary *backingStore;
@end

@implementation NSString (MyAdditions)
- (NSString*)myLowercaseString {
NSString *lowercase = [self myLowercaseString];
NSLog(@"Lowercasing string: %@ => %@", self, lowercase);
return lowercase;
@implementation EOCAutoDictionary
@dynamic string, number, date, opaqueObject;

- (id)init {
if ((self = [super init])) {
_backingStore = [NSMutableDictionary new];
}
return self;
}

+ (BOOL)resolveInstanceMethod:(SEL)selector {
NSString *selectorString = NSStringFromSelector(selector);
if ([selectorString hasPrefix:@"set"]) {
class_addMethod(self, selector, (IMP)autoDictionarySetter, "v@:@");
} else {
class_addMethod(self, selector, (IMP)autoDictionaryGetter, "@@:");
}
return YES;
}

@end

Method originalMethod = class_getInstanceMethod([NSString class], @selector(lowercaseString));
Method swappedMethod = class_getInstanceMethod([NSString class], @selector(myLowercaseString));
method_exchangeImplementations(originalMethod, swappedMethod);
id autoDictionaryGetter(id self, SEL _cmd) {
// Get the backing store from the object
EOCAutoDictionary *typedSelf = (EOCAutoDictionary*)self;
NSMutableDictionary *backingStore = typedSelf.backingStore;

// The key is simply the selector name
NSString *key = NSStringFromSelector(_cmd);

// Return the value
return [backingStore objectForKey:key];
}

void autoDictionarySetter(id self, SEL _cmd, id value) {
// Get the backing store from the object
EOCAutoDictionary *typedSelf = (EOCAutoDictionary*)self;
NSMutableDictionary *backingStore = typedSelf.backingStore;

/** The selector will be for example, "setOpaqueObject:".
* We need to remove the "set", ":" and lowercase the first
* letter of the remainder.
*/
NSString *selectorString = NSStringFromSelector(_cmd);
NSMutableString *key = [selectorString mutableCopy];

// Remove the `:' at the end
[key deleteCharactersInRange:NSMakeRange(key.length - 1, 1)];

// Remove the `set' prefix
[key deleteCharactersInRange:NSMakeRange(0, 3)];

// Lowercase the first character
NSString *lowercaseFirstChar = [[key substringToIndex:1] lowercaseString];
[key replaceCharactersInRange:NSMakeRange(0, 1) withString:lowercaseFirstChar];

if (value) {
[backingStore setObject:value forKey:key];
} else {
[backingStore removeObjectForKey:key];
}
}

// Using EOCAutoDictionary
EOCAutoDictionary *dict = [EOCAutoDictionary new];
dict.date = [NSDate dateWithTimeIntervalSince1970:475372800];
NSLog(@"dict.date = %@", dict.date);
// Output: dict.date = 1985-01-24 00:00:00 +0000

NSString *string = @"ThIs iS tHe StRiNg";
NSString *lowercaseString = [string lowercaseString];
// Output: Lowercasing string: ThIs iS tHe StRiNg => this is the string
Loading