如何在Objective-C中投射一个对象

有没有一种方法在Objective-C中投射对象,就像在VB.NET中投射对象的方式一样?

例如,我正在尝试执行以下操作:

// create the view controller for the selected item FieldEditViewController *myEditController; switch (selectedItemTypeID) { case 3: myEditController = [[SelectionListViewController alloc] init]; myEditController.list = listOfItems; break; case 4: // set myEditController to a diff view controller break; } // load the view [self.navigationController pushViewController:myEditController animated:YES]; [myEditController release]; 

不过,我得到一个编译器错误,因为'List'属性存在于SelectionListViewController类中,但不在FieldEditViewController上,即使SelectionListViewControllerinheritance自FieldEditViewController。

这是有道理的,但有没有办法将myEditController投射到一个SelectionListViewController,所以我可以访问“列表”属性?

例如在VB.NET中,我会这样做:

 CType(myEditController, SelectionListViewController).list = listOfItems 

谢谢您的帮助!

请记住,Objective-C是C的一个超集,所以types转换就像在C:

 myEditController = [[SelectionListViewController alloc] init]; ((SelectionListViewController *)myEditController).list = listOfItems; 
 ((SelectionListViewController *)myEditController).list 

更多例子:

 int i = (int)19.5f; // (precision is lost) id someObject = [NSMutableArray new]; // you don't need to cast id explicitly 

在Objective-C中进行types转换很简单:

 NSArray *threeViews = @[[UIView new], [UIView new], [UIView new]]; UIView *firstView = (UIView *)threeViews[0]; 

但是,如果第一个对象不是UIView而您尝试使用它,会发生什么情况:

 NSArray *threeViews = @[[NSNumber new], [UIView new], [UIView new]]; UIView *firstView = (UIView *)threeViews[0]; CGRect firstViewFrame = firstView.frame; // CRASH! 

它会崩溃。 在这种情况下很容易find这样的崩溃,但是如果这些行在不同的类中,并且第三行在100个情况下仅被执行一次会怎样。 我敢打赌,你的客户发现这个崩溃,不是你! 一个合理的解决办法是尽早崩溃 ,如下所示:

 UIView *firstView = (UIView *)threeViews[0]; NSAssert([firstView isKindOfClass:[UIView class]], @"firstView is not UIView"); 

这些断言看起来不太好,所以我们可以用这个方便的类别来改进它们:

 @interface NSObject (TypecastWithAssertion) + (instancetype)typecastWithAssertion:(id)object; @end @implementation NSObject (TypecastWithAssertion) + (instancetype)typecastWithAssertion:(id)object { if (object != nil) NSAssert([object isKindOfClass:[self class]], @"Object %@ is not kind of class %@", object, NSStringFromClass([self class])); return object; } @end 

这好多了:

 UIView *firstView = [UIView typecastWithAssertion:[threeViews[0]]; 

PS对于集合types安全性Xcode 7比types转换 – generics要好得多

当然,语法是完全一样的C – NewObj* pNew = (NewObj*)oldObj;

在这种情况下,您可能希望考虑将此列表作为参数提供给构造函数,如下所示:

 // SelectionListViewController -(id) initWith:(SomeListClass*)anItemList { self = [super init]; if ( self ) { [self setList: anItemList]; } return self; } 

然后像这样使用它:

 myEditController = [[SelectionListViewController alloc] initWith: listOfItems]; 

为包含而投入与为C ++程序员排除投射一样重要。 types转换与RTTI不同,因为您可以将对象转换为任何types,并且生成的指针不会为零。