2009-03-27 36 views
103

Có cách nào để đúc các đối tượng trong mục tiêu-c giống như cách các đối tượng được đúc trong VB.NET không?Làm thế nào để đúc một đối tượng trong Objective-C

Ví dụ, tôi đang cố gắng để làm như sau:

// 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]; 

Tuy nhiên tôi nhận được một lỗi biên dịch vì 'danh sách' tài sản tồn tại trong lớp SelectionListViewController nhưng không phải trên FieldEditViewController mặc dù SelectionListViewController thừa hưởng từ FieldEditViewController.

Điều này có ý nghĩa, nhưng có cách nào để đưa myEditController vào một SelectionListViewController để tôi có thể truy cập thuộc tính 'danh sách' không?

Ví dụ trong VB.NET tôi sẽ làm:

CType(myEditController, SelectionListViewController).list = listOfItems 

Thanks for the help!

+0

Tìm kiếm "đúc" trên trang này: http://en.wikipedia.org/wiki/Objective-C –

Trả lời

186

Hãy nhớ rằng, Objective-C là một superset của C, vì vậy typecasting làm việc giống như trong C:

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

Hoặc "Ghi nhớ, mục tiêu-C hoạt động như Java, chỉ cần nhớ thêm dấu hoa thị vào các biến trỏ tới đối tượng Obj-C. " –

+1

Câu trả lời hay. Bạn có thể làm cho nó một chút rõ ràng hơn bằng cách phá vỡ các diễn viên và phân công thành hai dòng. –

+0

Typecasting trong Objective-C giống với C cũ hơn Java. Java ẩn hầu hết điều này khỏi người dùng, do đó các đối số rằng C vẫn nên được dạy chứ không phải là Java như một ngôn ngữ đầu tiên. – csmith

7
((SelectionListViewController *)myEditController).list 

Thêm ví dụ:

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

Nói chung điều này là chính xác; bạn không cần truyền id trong các biểu thức thông báo. Nhưng khi sử dụng cú pháp dấu chấm để truy cập và thiết lập các thuộc tính, bạn phải sử dụng một loại cụ thể, không chỉ là id, do đó trình biên dịch biết lời gọi phương thức nào thực sự tạo ra. (Nó có thể khác nhau đối với các thuộc tính có cùng tên.) –

4

Chắc chắn, cú pháp là chính xác giống như C - NewObj* pNew = (NewObj*)oldObj;

Trong trường hợp này, bạn có thể xem xét việc cung cấp danh sách này làm tham số các nhà xây dựng, một cái gì đó như:

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

    if (self) { 
    [self setList: anItemList]; 
    } 

    return self; 
} 

Sau đó sử dụng nó như thế này:

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

Đúc để đưa là cũng quan trọng như đúc để loại trừ cho một ++ lập trình viên C. Loại đúc không giống như với RTTI theo nghĩa là bạn có thể đúc một đối tượng cho bất kỳ loại nào và con trỏ kết quả sẽ không phải là số không.

5

Typecasting trong Objective-C là dễ dàng như:

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

Tuy nhiên, những gì sẽ xảy ra nếu đối tượng đầu tiên không phải là UIView và bạn cố gắng sử dụng nó:

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

Nó sẽ sụp đổ. Và thật dễ dàng để tìm thấy sự cố như vậy cho trường hợp này, nhưng nếu những dòng đó nằm trong các lớp khác nhau và dòng thứ ba chỉ được thực hiện một lần trong 100 trường hợp. Tôi đặt cược khách hàng của bạn tìm thấy vụ tai nạn này, không phải bạn! Một giải pháp hợp lý là để crash early, như thế này:

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

Những khẳng định không trông rất đẹp, vì vậy chúng tôi có thể cải thiện chúng bằng loại có ích này:

@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 

Đây là nhiều tốt hơn:

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

PSĐối với các loại bộ sưu tập an toàn Xcode 7 có một tốt hơn nhiều so với typecasting - generics

Các vấn đề liên quan