Ios 使用具有Objective-C消息转发功能的UIView时出现分段错误或堆栈跟踪

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的已包装实例。但最终程序崩溃,要么是

问题是:给定一个类,该类刚从NSObject继承,并包装了UIView实例。此类名为UIViewWrapper。我想将此UIViewWrapper与UIView的“addSubview”一起使用。UIViewWrapper应该像“普通”UIView类一样工作

我目前正在利用Objective-C的“消息转发”功能来尝试让事情正常进行。在“addSubview”中,会对UIViewWrapper的实例进行一些调用,直到某一点,这些消息都会正确地转发到UIView的已包装实例。但最终程序崩溃,要么是“分段错误:11”(内存问题),要么是堆栈跟踪(见下文)

我的问题是:这样做有可能吗?如果是,“消息转发”是最好的方式吗?如果是,我在这里遗漏了什么?如果没有,解决此类问题的更好方法是什么

代码(省略main.m和AppDelegate.h,因为它们只有它们的常规内容):


也许如果你能澄清你想解决的问题,我们可以帮你更多。我有一种感觉,没有必要为此寻找解决方案,选择一种不同的方法会更好。正如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