如何在 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 中,即使 SelectionListViewController 继承自 FieldEditViewController。

这是有道理的,但是有没有一种方法可以将 myEditController 强制转换为 SelectionListViewController,这样我就可以访问“ list”属性了?

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

CType(myEditController, SelectionListViewController).list = listOfItems

谢谢你的帮助!

185111 次浏览

记住,Objective-C 是 C 的一个超集,所以类型转换的工作方式和 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

当然,语法与 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 + + 程序员来说,为包含进行强制转换与为排除进行强制转换同样重要。类型强制转换与 RTTI 的不同之处在于,您可以将对象强制转换为任何类型,并且生成的指针不为空。

在 Objective-C 中进行类型转换很容易:

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!

它会崩溃的。在这种情况下很容易发现这样的崩溃,但是如果这些行在不同的类中,而第三行在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]];

对于集合类型安全 Xcode 7比类型转换 非专利药有更好的性能