有没有一种方法可以在 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 是 C 的超集,因此类型转换的工作原理与 C 中的一样:
myEditController = [[SelectionListViewController alloc] init];
((SelectionListViewController *)myEditController).list = listOfItems;
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
更多示例:
int i = (int)19.5f; // (precision is lost)
id someObject = [NSMutableArray new]; // you don't need to cast id explicitly
NewObj* pNew = (NewObj*)oldObj;
在这种情况下,您可能希望考虑将此列表作为参数提供给构造函数,例如:
// SelectionListViewController
-(id) initWith:(SomeListClass*)anItemList
{
self = [super init];
if ( self ) {
[self setList: anItemList];
}
return self;
}
然后像这样使用它:
myEditController = [[SelectionListViewController alloc] initWith: listOfItems];