【发布时间】:2018-02-03 21:48:30
【问题描述】:
假设我希望能够拦截对 UIViewController 子类的任何方法调用。
首先,我调整+(instancetype)alloc method 并检查当前实例isKindOfClass:[UIViewController class]。如果是,我继续用目标实例化我的代理。
///swizzled Alloc
+ (instancetype)monitoredAlloc {
id obj = [self monitoredAlloc];
if([obj isKindOfClass:[UIViewController class]]) {
id proxy = [PMGProxy proxyWithObject:obj];
return proxy;
}
return [self monitoredAlloc];
}
---------------------------------------
/// Proxy class
@implementation PMGProxy
+ (instancetype)proxyWithObject:(id)obj {
PMGProxy *proxy = [self alloc];
proxy.obj = obj;
return proxy;
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
[invocation setTarget:_obj];
[invocation invoke];
}
-(NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
return [self.obj methodSignatureForSelector:sel];
}
- (Class)class {
return [self.obj class];
}
问题是我崩溃了,所以我认为我的代理的实现是错误的......我做错了什么?
这里是个例外:
*** Terminating app due to uncaught exception 'NSGenericException', reason: 'This coder requires that replaced objects be returned from initWithCoder:'
【问题讨论】:
-
沿着这条路走下去就是疯狂。有时可能有点对调试有用,但对其他任何东西都没有用。即使在调试的上下文中,如果您尝试对系统提供的类进行这种恶作剧,您也会遇到大量问题。
-
我不是在这里问这是否有用,也不打算将此代码推送到苹果商店。它更多的是用于学习目的。
-
沿着这条路走下去仍然是疯狂。 :)。错误方法可能是 UIViewController 类层次结构的实现细节的后果(或者实际上是安全编码的后果)。问题在于,尽管鸭子类型在类中工作得非常好,但当您尝试在复杂的、预先存在的类层次结构中进行大规模替换时,它很快就会与实现细节和实现假设发生冲突。
-
您[可能]会在子类化和覆盖您想要/需要记录的所有方法中找到更多价值。或者使用 swizzling 来简洁的替换和登录具体方法。乏味,更多的努力,但更准确地专注于公共 API。
标签: ios objective-c uiviewcontroller nsproxy swizzle