2012-04-26 48 views
45

Có sự khác biệt nào giữa việc sử dụng dấu gạch dưới và sử dụng từ khóa self trong Mục tiêu-C khi gọi số @property không?Sự khác biệt giữa _ và tự. trong Mục tiêu-C

khai tài sản:

@property (weak, nonatomic) NSString *myString; 

Calling @synthesize về tài sản:

@synthesize myString = _myString; 

Có một sự khác biệt nếu tôi muốn sử dụng nó trong mã của tôi? Khi nào? Trong getter/setter?

self.myString = @"test"; 
_myString = @"test"; 
+0

'self' là biểu tượng. '_' là một ký tự trong một số ký hiệu. 'myString' và' _myString' là hai biểu tượng khác nhau có liên quan, không phải do chính tả mà bởi vì chúng được đặt tên trong cùng một '@ synthezize'. –

+0

Hãy thử câu trả lời sau đây: http://stackoverflow.com/questions/5170631/what-does-synthesize-window-window-do – Peres

+2

Kiểm tra xem @ Jonathan trả lời cho câu hỏi này trước SO giúp http: // stackoverflow .com/questions/5466496/why-rename-synthesized-properties-in-ios-với-hàng đầu-gạch dưới – visakh7

Trả lời

68

self.myString = @"test"; tương đương với cách viết [self setMyString:@"test"];. Cả hai đều gọi một phương thức.

Bạn có thể đã tự viết phương pháp đó. Nó có thể giống như thế này:

- (void)setMyString:(NSString*)newString 
{ 
    _myString = newString; 
} 

Bởi vì bạn sử dụng @synthesize, bạn không cần phải thực sự bận tâm viết phương pháp đó, bạn có thể chỉ cho phép trình biên dịch để viết nó cho bạn. Vì vậy, khi nhìn vào phương pháp đó, có vẻ như việc gọi nó sẽ làm điều tương tự như chỉ gán một giá trị cho biến thể hiện, đúng không? Vâng, nó không đơn giản như vậy.

Thứ nhất, bạn có thể viết phương thức setter riêng của mình. Nếu bạn làm như vậy, phương pháp của bạn sẽ được gọi, và nó có thể làm tất cả các loại điều bổ sung cũng như thiết lập biến. Trong trường hợp đó, sử dụng self.myString = sẽ gọi phương thức của bạn, nhưng làm _myString = sẽ không, và do đó chức năng khác nhau sẽ được sử dụng.

Thứ hai, nếu bạn từng sử dụng Quan sát giá trị khóa, trình biên dịch thực hiện một số thủ thuật rất thông minh. Đằng sau hậu trường, nó phân lớp lớp của bạn và ghi đè phương thức setter của bạn (cho dù đó là cách bạn viết hoặc tạo ra bằng cách tổng hợp), để thực hiện các cuộc gọi đến willChangeValueForKey: cần thiết cho Key Value Observing để hoạt động. Bạn không cần phải biết cách làm việc này (mặc dù nó khá thú vị nếu bạn muốn đọc một số giờ đi ngủ!), Nhưng bạn cần biết rằng nếu bạn muốn Key Value Observing hoạt động tự động, bạn phải sử dụng các phương thức setter.

Thứ ba, gọi phương thức setter ngay cả khi bạn đang dựa vào tổng hợp để viết một cái cho bạn sự linh hoạt cho tương lai. Bạn có thể muốn làm điều gì đó thêm bất cứ khi nào giá trị được thay đổi và tại thời điểm bạn phát hiện bạn muốn làm điều đó, bạn có thể viết phương pháp setter theo cách thủ công - nếu bạn có thói quen luôn sử dụng self.myString = thì bạn sẽ không cần phải thay đổi phần còn lại của mã để bắt đầu gọi phương thức mới!

Thứ tư, điều tương tự cũng áp dụng cho các lớp con. Nếu ai đó đã phân lớp mã của bạn, nếu bạn sử dụng những người định cư thì họ có thể ghi đè lên chúng để điều chỉnh chức năng.

Bất cứ khi nào bạn truy cập trực tiếp biến mẫu, bạn rõ ràng không cung cấp cách để thêm chức năng để được nối vào lúc đó. Vì bạn hoặc ai đó có thể muốn móc trong các chức năng như vậy trong tương lai, nó trả tiền để sử dụng những người định cư tất cả các thời gian, trừ khi có một lý do chính đáng để không.

+0

Lưu ý rằng tôi không đề cập đến các tác động quản lý bộ nhớ. Nếu bạn đang sử dụng ARC, chúng ít liên quan hơn nhiều trong trường hợp này, vì vậy tôi bỏ qua chúng. –

+0

Giải thích tốt :) – iTag

+0

Bằng cách này, về câu đầu tiên ... Điều này đúng 99% thời gian, nhưng nếu bạn có một setter tùy chỉnh (được chỉ định với 'setter =' trong khai báo thuộc tính), thì hai biểu mẫu không chính xác tương đương. –

8

Bạn là chính xác - phiên bản đầu tiên (self.myString) gọi getter tổng hợp/setter và phiên bản thứ hai truy cập các biến thành viên tin trực tiếp.

Dường như bạn đang sử dụng ARC, vì vậy trong trường hợp đó, nó không tạo ra nhiều sự khác biệt. Tuy nhiên, nếu bạn không sử dụng ARC, nó có thể tạo sự khác biệt khi gán trực tiếp cho thành viên riêng tư sẽ không kích hoạt tính năng giữ lại/giải phóng hoặc sao chép/giải phóng logic được tạo cho bạn bằng cách sử dụng synthesize.

+0

Chúng là hai biểu tượng khác nhau. Người ta có thể là "aardvark" và "zebra" khác và vẫn có mối quan hệ biến-setter/getter. –

+0

@Hot Licks - Bạn đúng rằng tên không liên quan, nhưng khi tôi đọc câu hỏi, tôi nghĩ anh ấy tự hỏi sự khác biệt thực tế là gì giữa việc sử dụng thuộc tính tổng hợp so với chỉ sử dụng biến thành viên sao lưu nó. –

+0

@EricPetroelje - vâng, đó chính xác là những gì tôi đã hỏi. Cảm ơn! – Kuba

3

_ (gạch dưới) chỉ đơn giản là quy ước, như được giải thích trong this question.

Khi bạn không tiền tố quyền truy cập thuộc tính với self., bạn đang truy cập trực tiếp vào biến bên dưới, như trong c struct. Nói chung, bạn chỉ nên làm điều này trong các phương thức init của bạn và trong các trình truy cập thuộc tính tùy chỉnh. Điều này cho phép các nội dung như thuộc tính được tính toán và KVC hoạt động như dự định.

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