Skip to content

Commit

Permalink
Add KVO test cases and note
Browse files Browse the repository at this point in the history
  • Loading branch information
steipete committed May 3, 2014
1 parent 6366d53 commit 16d0649
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
<AdditionalOption
key = "NSZombieEnabled"
value = "YES"
isEnabled = "YES">
</AdditionalOption>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
Expand Down
6 changes: 3 additions & 3 deletions AspectsDemo/AspectsDemo/AspectsAppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ @implementation AspectsAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

[self.window aspect_hookSelector:@selector(makeKeyAndVisible) atPosition:AspectPositionBefore withBlock:^(id object, NSArray *arguments) {
NSLog(@"We're about to call -[UIWindow makeKeyAndVisible].");
}];
// [self.window aspect_hookSelector:@selector(makeKeyAndVisible) atPosition:AspectPositionBefore withBlock:^(id object, NSArray *arguments) {
// NSLog(@"We're about to call -[UIWindow makeKeyAndVisible].");
// }];

// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
Expand Down
55 changes: 55 additions & 0 deletions AspectsDemo/AspectsDemoTests/AspectsDemoTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#import "NSObject+Aspects.h"

@interface TestClass : NSObject
@property (nonatomic, copy) NSString *string;
@property (nonatomic, assign) BOOL kvoTestCalled;
- (void)testCall;
- (void)testCallAndExecuteBlock:(dispatch_block_t)block;
@end
Expand Down Expand Up @@ -164,4 +166,57 @@ - (void)testStructReturn {
XCTAssertTrue(CGRectEqualToRect(rect, rectHooked), @"Must be equal");
}

- (void)testKVOCoexistance {
TestClass *testClass = [TestClass new];

__block BOOL hookCalled = NO;
[testClass aspect_hookSelector:@selector(setString:) atPosition:AspectPositionAfter withBlock:^(id object, NSArray *arguments) {
NSLog(@"Aspect hook!");
hookCalled = YES;
}];
[testClass addObserver:self forKeyPath:NSStringFromSelector(@selector(string)) options:0 context:_cmd];

XCTAssertFalse(testClass.kvoTestCalled, @"KVO must be not set");
testClass.string = @"test";
XCTAssertTrue(hookCalled, @"Hook must be called");
XCTAssertTrue(testClass.kvoTestCalled, @"KVO must work");
[testClass removeObserver:self forKeyPath:NSStringFromSelector(@selector(string)) context:_cmd];
hookCalled = NO;
testClass.kvoTestCalled = NO;
testClass.string = @"test2";
XCTAssertTrue(hookCalled, @"Hook must be called");
XCTAssertFalse(testClass.kvoTestCalled, @"KVO must no longer work");
}

// TODO: Pre-registeded KVO is currently not working.
//- (void)testKVOCoexistanceWithPreregisteredKVO {
// TestClass *testClass = [TestClass new];
// XCTAssertFalse(testClass.kvoTestCalled, @"KVO must be not set");
// [testClass addObserver:self forKeyPath:NSStringFromSelector(@selector(string)) options:0 context:_cmd];
// testClass.string = @"test";
// XCTAssertTrue(testClass.kvoTestCalled, @"KVO must work");
//
// __block BOOL hookCalled = NO;
// [testClass aspect_hookSelector:@selector(setString:) atPosition:AspectPositionAfter withBlock:^(id object, NSArray *arguments) {
// NSLog(@"Aspect hook!");
// hookCalled = YES;
// }];
//
// XCTAssertFalse(testClass.kvoTestCalled, @"KVO must be not set");
// testClass.string = @"test";
// XCTAssertTrue(hookCalled, @"Hook must be called");
// XCTAssertTrue(testClass.kvoTestCalled, @"KVO must work");
// [testClass removeObserver:self forKeyPath:NSStringFromSelector(@selector(string)) context:_cmd];
// hookCalled = NO;
// testClass.kvoTestCalled = NO;
// testClass.string = @"test2";
// XCTAssertTrue(hookCalled, @"Hook must be called");
// XCTAssertFalse(testClass.kvoTestCalled, @"KVO must no longer work");
//}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
NSLog(@"KVO!");
((TestClass *)object).kvoTestCalled = YES;
}

@end
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,10 @@ You can also add the two files NSObject+Aspects.h/m. There are no further requir

Compatibility
-------------
You can freely mix Aspects with regular method swizzling or KVO.
You can freely mix Aspects with regular method swizzling.

KVO works if observers are created after your calls aspect_hookSelector: It most likely will crash the other way around.
Still looking for workarounds here - any help apprechiated.

Because of ugly implementation details on the ObjC runtime, methods that return unions that also contain structs might not work correctly unless this code runs on the arm64 runtime.

Expand Down

0 comments on commit 16d0649

Please sign in to comment.