如何在 Objective-C 中转换对象?

问题描述 投票:0回答:5

有没有一种方法可以在 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
objective-c
5个回答
234
投票

请记住,Objective-C 是 C 的超集,因此类型转换的工作原理与 C 中的一样:

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

17
投票

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 比类型转换更好 - 
generics


12
投票
更多示例:

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



5
投票
NewObj* pNew = (NewObj*)oldObj;


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

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

然后像这样使用它:

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



0
投票

© www.soinside.com 2019 - 2024. All rights reserved.