如何在 Objective-C 中转换对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/690748/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to cast an object in Objective-C
提问by Billy
Is there a way to cast objects in objective-c much like the way objects are cast in VB.NET?
有没有办法像在 VB.NET 中投射对象一样在 Objective-c 中投射对象?
For example, I am trying to do the following:
例如,我正在尝试执行以下操作:
// 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];
However I am getting a compiler error since the 'list' property exists in the SelectionListViewController class but not on the FieldEditViewController even though SelectionListViewController inherits from FieldEditViewController.
但是,我收到一个编译器错误,因为“list”属性存在于 SelectionListViewController 类中,但不存在于 FieldEditViewController 中,即使 SelectionListViewController 继承自 FieldEditViewController。
This makes sense, but is there a way to cast myEditController to a SelectionListViewController so I can access the 'list' property?
这是有道理的,但是有没有办法将 myEditController 转换为 SelectionListViewController 以便我可以访问“列表”属性?
For example in VB.NET I would do:
例如在 VB.NET 中我会这样做:
CType(myEditController, SelectionListViewController).list = listOfItems
Thanks for the help!
谢谢您的帮助!
回答by Jim Puls
Remember, Objective-C is a superset of C, so typecasting works as it does in C:
请记住,Objective-C 是 C 的超集,因此类型转换的工作方式与在 C 中一样:
myEditController = [[SelectionListViewController alloc] init];
((SelectionListViewController *)myEditController).list = listOfItems;
回答by Sijmen Mulder
((SelectionListViewController *)myEditController).list
More examples:
更多例子:
int i = (int)19.5f; // (precision is lost)
id someObject = [NSMutableArray new]; // you don't need to cast id explicitly
回答by Alexander Vasenin
Typecasting in Objective-C is easy as:
Objective-C 中的类型转换很简单,因为:
NSArray *threeViews = @[[UIView new], [UIView new], [UIView new]];
UIView *firstView = (UIView *)threeViews[0];
However, what happens if first object is not UIViewand you try to use it:
但是,如果第一个对象不是UIView并且您尝试使用它会发生什么:
NSArray *threeViews = @[[NSNumber new], [UIView new], [UIView new]];
UIView *firstView = (UIView *)threeViews[0];
CGRect firstViewFrame = firstView.frame; // CRASH!
It will crash. And it's easy to find such crash for this case, but what if those lines are in different classes and the third line is executed only once in 100 cases. I bet your customers find this crash, not you! A plausible solution is to crash early, like this:
它会崩溃。在这种情况下很容易找到这样的崩溃,但是如果这些行在不同的类中并且第三行在 100 种情况下只执行一次怎么办。我敢打赌,您的客户会发现这次崩溃,而不是您!一个合理的解决方案是早点崩溃,像这样:
UIView *firstView = (UIView *)threeViews[0];
NSAssert([firstView isKindOfClass:[UIView class]], @"firstView is not UIView");
Those assertions doesn't look very nice, so we could improve them with this handy category:
这些断言看起来不太好,所以我们可以用这个方便的类别来改进它们:
@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
This is muchbetter:
这要好得多:
UIView *firstView = [UIView typecastWithAssertion:[threeViews[0]];
P.S. For collections type safety Xcode 7 have a much better than typecasting - generics
PS 对于集合类型安全,Xcode 7 比类型转换要好得多 -泛型
回答by Andrew Grant
Sure, the syntax is exactly the same as C - NewObj* pNew = (NewObj*)oldObj;
当然,语法和 C 完全一样—— NewObj* pNew = (NewObj*)oldObj;
In this situation you may wish to consider supplying this list as a parameter to the constructor, something like:
在这种情况下,您可能希望考虑将此列表作为参数提供给构造函数,例如:
// SelectionListViewController
-(id) initWith:(SomeListClass*)anItemList
{
self = [super init];
if ( self ) {
[self setList: anItemList];
}
return self;
}
Then use it like this:
然后像这样使用它:
myEditController = [[SelectionListViewController alloc] initWith: listOfItems];
回答by stephen
Casting for inclusion is just as important as casting for exclusion for a C++ programmer. Type casting is not the same as with RTTI in the sense that you can cast an object to any type and the resulting pointer will not be nil.
对于 C++ 程序员来说,包含的转换与排除的转换同样重要。类型转换与 RTTI 不同,因为您可以将对象转换为任何类型并且结果指针不会为 nil。

