Skip to content

Instantly share code, notes, and snippets.

@joemasilotti
Last active September 2, 2015 18:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joemasilotti/d7086033fa1e82aadd2e to your computer and use it in GitHub Desktop.
Save joemasilotti/d7086033fa1e82aadd2e to your computer and use it in GitHub Desktop.
WKUserContentController Swizzling (breaks in Xcode 7)
#import <WebKit/WebKit.h>
@interface WKUserContentController (Spec)
- (NSDictionary *)userScriptHandlers;
@end
#import <objc/runtime.h>
#import "WKUserContentController+Spec.h"
#import "NSObject+MethodRedirection.h"
static char kUserScriptHandlersKey;
@interface WKUserContentController (SpecPrivate)
- (void)stubbedAddScriptMessageHandler:(id<WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;
- (void)originalAddScriptMessageHandler:(id<WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;
- (void)stubbedRemoveScriptMessageHandlerForName:(NSString *)name;
- (void)originalRemoveScriptMessageHandlerForName:(NSString *)name;
@end
@implementation WKUserContentController (Spec)
+ (void)initialize {
[WKUserContentController redirectSelector:@selector(addScriptMessageHandler:name:)
to:@selector(stubbedAddScriptMessageHandler:name:)
andRenameItTo:@selector(originalAddScriptMessageHandler:name:)];
[WKUserContentController redirectSelector:@selector(removeScriptMessageHandlerForName:)
to:@selector(stubbedRemoveScriptMessageHandlerForName:)
andRenameItTo:@selector(originalRemoveScriptMessageHandlerForName:)];
}
- (instancetype)init {
if (self = [super init]) {
objc_setAssociatedObject(self, &kUserScriptHandlersKey, [NSMutableDictionary dictionary], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return self;
}
- (NSDictionary *)userScriptHandlers {
return [self mutableUserScriptHandlers];
}
- (NSMutableDictionary *)mutableUserScriptHandlers {
return objc_getAssociatedObject(self, &kUserScriptHandlersKey);
}
- (void)stubbedAddScriptMessageHandler:(id<WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name {
[self mutableUserScriptHandlers][name] = scriptMessageHandler;
}
- (void)stubbedRemoveScriptMessageHandlerForName:(NSString *)name {
[[self mutableUserScriptHandlers] removeObjectForKey:name];
}
@end
#import <Cedar-iOS.h>
#import "WKUserContentController+Spec.h"
using namespace Cedar::Matchers;
using namespace Cedar::Doubles;
SPEC_BEGIN(WKUserContentController_SpecSpec)
describe(@"WKUserContentController_Spec", ^{
__block WKUserContentController *subject;
beforeEach(^{
subject = [[WKUserContentController alloc] init];
});
describe(@"-userScriptHandlers", ^{
context(@"before any handlers are added", ^{
it(@"should return an empty dictionary", ^{
[subject userScriptHandlers] should equal(@{ });
});
});
context(@"adding two handlers", ^{
__block id<WKScriptMessageHandler> handler1, handler2;
beforeEach(^{
handler1 = nice_fake_for(@protocol(WKScriptMessageHandler));
handler2 = nice_fake_for(@protocol(WKScriptMessageHandler));
[subject addScriptMessageHandler:handler1 name:@"name1"];
[subject addScriptMessageHandler:handler2 name:@"name2"];
});
it(@"should return the handlers keyed by name", ^{
[subject userScriptHandlers] should equal(@{ @"name1": handler1,
@"name2": handler2 });
});
context(@"then removing one", ^{
beforeEach(^{
[subject removeScriptMessageHandlerForName:@"name1"];
});
it(@"should return the remaining handler", ^{
[subject userScriptHandlers] should equal(@{ @"name2": handler2 });
});
});
});
});
});
SPEC_END
#import <WebKit/WebKit.h>
#import <Cedar-iOS.h>
using namespace Cedar::Matchers;
using namespace Cedar::Doubles;
SPEC_BEGIN(WKWebViewSpec)
describe(@"WKWebView", ^{
__block WKWebView *subject;
beforeEach(^{
subject = [[WKWebView alloc] init];
});
it(@"should create a web view", ^{
subject should_not be_nil; // this causes the crash
});
});
SPEC_END
@joemasilotti
Copy link
Author

  • Everything passes with Xcode 6.X and iOS 8.X.
  • WKWebViewSpec.mm:17 raises an exception with Xcode 7 and iOS 9.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment