2008-11-23 38 views
5

Tôi có một phương pháp init mà phải mất một (id) lập luận:Tại sao tôi cần truyền tự id?


    -(id) initWithObject:(id) obj; 

Tôi đang cố gắng để gọi nó như thế này:


    [[MyClass alloc] initWithObject:self]; 

Nhưng XCode được phàn nàn về tranh luận là một "biệt Loại mục tiêu-C "(thường chỉ ra một loại không phù hợp hoặc mức độ lỗi gián tiếp).

Nếu tôi tự chuyển mình thành (id) cảnh báo sẽ biến mất. Trong cả hai trường hợp, mã chạy như mong đợi. Điều thú vị là, trên dòng tiếp theo, tôi sẽ tự chuyển sang phương thức khác cũng có id và hoạt động tốt.

Tôi tự hỏi liệu tôi có thiếu điều gì đó tinh tế - hay nó là một đặc tính của trình biên dịch?

Tôi không hoàn toàn thoải mái khi chỉ truyền cho đến khi tôi chắc chắn về lý do tại sao cần thiết.

[Chỉnh sửa]

Tôi đã được yêu cầu cung cấp thêm mã. Không chắc có nhiều thứ khác có liên quan. Đây là mã thực tế của tôi mà thực hiện cuộc gọi. Lưu ý rằng chính nó, trong một phương thức init. Đó là lời kêu gọi initWithSource đó là đưa ra các cảnh báo:


-(id) initWithFrame:(CGRect) frame 
{ 
    self = [super initWithFrame: frame]; 
    if(self) 
    { 
     delegate = nil; 
     touchDelegate = [[TBCTouchDelegate alloc] initWithSource:self]; 
     [touchDelegate.viewWasTappedEvent addTarget: self action:@selector(viewWasTapped:)]; 
    } 
    return self; 
} 

Và đây là phương pháp init được gọi là:


-(id) initWithSource:(id) sourceObject 
{ 
    self = [super init]; 
    if (self != nil) 
    { 
     // Uninteresting initialisation snipped 
    } 
    return self; 
} 
+0

Bạn có thể muốn đăng thêm mã tại đây; không có gì nhảy ra ngoài, nhưng chỉ có hai dòng để làm việc với, thật khó để nói. –

+0

Đồng ý với Ben, nhưng một điều cần xem xét, là phương thức initWithObject được khai báo? –

+0

Cảm ơn bạn đã tìm kiếm. Tôi đã thêm một chút mã trên, cho những gì nó có giá trị. @ Jason: Có, initWithSource (tên phương thức thực tế của tôi) được khai báo trong tiêu đề và chắc chắn khớp với tiêu đề. – philsquared

Trả lời

7

Thông thường điều này có nghĩa là có nhiều tên initWithSource: phương pháp trên lớp khác nhau với các loại lập luận mâu thuẫn nhau. Hãy nhớ rằng, nếu một biến được gõ là id trình biên dịch không biết lớp đó là gì. Vì vậy, nếu bạn gọi initWithSource: trên một đối tượng được nhập id và nhiều lớp có phương thức initWithSource:, trình biên dịch về cơ bản chỉ chọn một trong hai. Nếu nó chọn "sai" một, tốt, bạn nhận được một "loại Objective-C loại" lỗi.

Vậy tại sao điều này lại xảy ra với bạn? Tôi không chắc chắn 100%, nhưng hãy nhớ rằng +[TBCTouchDelegate alloc] trả về một id. Như vậy chaining các alloc/init gọi là tương đương với điều này:

id o = [TBCTouchDelegate alloc]; 
touchDelegate = [o initWithSource:self]; 

Do đó, bạn đang gọi initWithSource: trên một biến -typed id. Nếu có phương pháp initWithSource: xung đột, bạn có thể gặp lỗi trình biên dịch này.

Có phương pháp xung đột nào không? Tôi đã kiểm tra hệ thống, và chỉ có một mâu thuẫn là trong NSAppleScript:

- (id)initWithSource:(NSString *)source; 

Bây giờ NSAppleScript phần của Quỹ, nhưng tôi nhận thấy đây là mã iPhone. Vì vậy, có lẽ bạn chỉ nhận được lỗi này khi biên dịch cho trình giả lập chứ không phải thiết bị?

Trong mọi trường hợp, nếu đây là vấn đề của bạn, bạn có thể nhận được xung quanh nó bằng cách tách alloc/init vào hai dòng khác nhau:

touchDelegate = [TBCTouchDelegate alloc]; 
touchDelegate = [touchDelegate initWithSource:self]; 

Bây giờ, bạn đang gọi điện thoại initWithSource: trên một biến đầy đủ, đánh máy (thay vì id -typed), do đó trình biên dịch không còn phải đoán cái nào cần chọn. Hoặc bạn có thể cast sự trở lại từ +alloc:

touchDelegate = [(TBCTouchDelegate *)[TBCTouchDelegate alloc] initWithSource:self]; 

giải pháp khác là đổi tên initWithSource: để tránh những xung đột và có lẽ làm cho nó mô tả nhiều hơn. Bạn không nói những gì lớp học hiện đang được đặt tên và những gì các "nguồn" là cho, vì vậy tôi không thể ném ra bất kỳ khả năng.

+0

Tôi đã thử sao chép mã của bạn vào dự án của riêng tôi và nhấn đúp vào initWithSource. Mặc dù nó là một dự án iPhone, nó thực sự là cố gắng để tham khảo NSApplescript, theo đề nghị của Dave. –

+0

Cảm ơn Dave - đã có mặt tại chỗ - và giải thích rõ ràng! May mắn thay, từ "nguồn" là khá tùy ý, vì vậy tôi đã có thể thay đổi nó khá dễ dàng. TouchDelegate là proxy để chạm vào các sự kiện và "nguồn" là đối tượng mà proxy đang proxy. Tôi đã gọi nó là TouchSource ngay bây giờ. – philsquared

+0

Cảm ơn bạn đã xác nhận thêm, Ben, và dành thời gian để giúp đỡ. – philsquared

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