Ios 使用具有Objective-C消息转发功能的UIView时出现分段错误或堆栈跟踪
问题是:给定一个类,该类刚从NSObject继承,并包装了UIView实例。此类名为UIViewWrapper。我想将此UIViewWrapper与UIView的“addSubview”一起使用。UIViewWrapper应该像“普通”UIView类一样工作 我目前正在利用Objective-C的“消息转发”功能来尝试让事情正常进行。在“addSubview”中,会对UIViewWrapper的实例进行一些调用,直到某一点,这些消息都会正确地转发到UIView的已包装实例。但最终程序崩溃,要么是“分段错误:11”(内存问题),要么是堆栈跟踪(见下文) 我的问题是:这样做有可能吗?如果是,“消息转发”是最好的方式吗?如果是,我在这里遗漏了什么?如果没有,解决此类问题的更好方法是什么 代码(省略main.m和AppDelegate.h,因为它们只有它们的常规内容):Ios 使用具有Objective-C消息转发功能的UIView时出现分段错误或堆栈跟踪,ios,objective-c,unrecognized-selector,Ios,Objective C,Unrecognized Selector,问题是:给定一个类,该类刚从NSObject继承,并包装了UIView实例。此类名为UIViewWrapper。我想将此UIViewWrapper与UIView的“addSubview”一起使用。UIViewWrapper应该像“普通”UIView类一样工作 我目前正在利用Objective-C的“消息转发”功能来尝试让事情正常进行。在“addSubview”中,会对UIViewWrapper的实例进行一些调用,直到某一点,这些消息都会正确地转发到UIView的已包装实例。但最终程序崩溃,要么是
也许如果你能澄清你想解决的问题,我们可以帮你更多。我有一种感觉,没有必要为此寻找解决方案,选择一种不同的方法会更好。正如Objective-C中经常出现的情况一样,你最好坚持“可可方式”做事 基本上,现在您使用不正确类的对象作为参数调用
addSubview
方法。见图1。这就是坠机的原因
<我知道这是完全错误的,在java/C++中(以及任何其他类型的语言都有强类型检查),甚至不会编译。但是由于Objective-C和Cocoa是非常动态的,我很好奇这样的“奇怪”问题是否可以用语言或框架特性来解决。UIViewWrapper就像一个代理。调用方应该像处理UIView一样处理它的实例,即使它实际上不是。如果将一些NSLog语句放入forwardInvocation,可以看到一些转发做得很好,但在某一点上停止了工作。我想知道确切的原因是什么。
//AppDelegate.m
@implementation AppDelegate
- (BOOL) application : (UIApplication *) application didFinishLaunchingWithOptions : (NSDictionary *) launchOptions {
self.window = [[UIWindow alloc] initWithFrame : [[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
//a normal UIView -> works as expected
//UIView *theView = [[UIView alloc] initWithFrame : CGRectMake(50, 50, 50, 50)];
//[theView setBackgroundColor : [UIColor yellowColor]];
//the wrapped version -> fails when added to the rootView
UIViewWrapper *theView = [[UIViewWrapper alloc] init];
UIView *rootView = [[UIView alloc] init];
[rootView addSubview : theView];
UIViewController *rootViewController = [[UIViewController alloc] init];
[rootViewController setView : rootView];
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
//UIViewWrapper.h
#import <UIKit/UIKit.h>
@interface UIViewWrapper : NSObject
@end
//UIViewWrapper.m
@interface UIViewWrapper()
@property(nonatomic, strong) UIView *uiview;
@end
@implementation UIViewWrapper
- (NSMethodSignature *) methodSignatureForSelector : (SEL) selector {
return [UIView instanceMethodSignatureForSelector : selector];
}
-(void) forwardInvocation : (NSInvocation *) forwardedInvocation {
if (!self.uiview) {
self.uiview = [[UIView alloc] initWithFrame : CGRectMake(50, 50, 50, 50)];
[self.uiview setBackgroundColor : [UIColor redColor]];
}
[forwardedInvocation invokeWithTarget : self.uiview];
}
@end
Jan 27 13:55:09 Dirks-MacBook-Air Showcase[15741]: +[__NSBlockVariable__ superlayer]: unrecognized selector sent to class 0x2df82b4
Jan 27 13:55:09 Dirks-MacBook-Air Showcase[15741]: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[__NSBlockVariable__ superlayer]: unrecognized selector sent to class 0x2df82b4'
*** First throw call stack:
(
0 CoreFoundation 0x0253fa14 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x028a9e02 objc_exception_throw + 50
2 CoreFoundation 0x02548c03 +[NSObject(NSObject) doesNotRecognizeSelector:] + 275
3 CoreFoundation 0x024866bd ___forwarding___ + 1037
4 CoreFoundation 0x0248628e _CF_forwarding_prep_0 + 14
5 UIKit 0x00dce092 -[UIView(Internal) _addSubview:positioned:relativeTo:] + 1452
6 UIKit 0x00dbc8e4 -[UIView(Hierarchy) addSubview:] + 56
7 Showcase 0x001dcb4b -[AppDelegate application:didFinishLaunchingWithOptions:] + 343