6

Tôi có một phương pháp thỉnh thoảng gặp sự cố.Có phải "tự" yếu trong một phương thức trong ARC không?

-(void)foo{ 
    [self doSomething]; 
    [self.delegate didFinish]; 
    [self doSomethingElse]; 
} 

-doĐiều gì đó hoạt động chính xác, sau đó tôi gọi cho đại biểu -didFinish. Trong vòng -didFinish, tham chiếu đến đối tượng này có thể được đặt thành 0, phát hành nó dưới ARC. Khi phương thức bị treo, nó làm như vậy trên -doSomethingElse. Giả định của tôi là bản thân sẽ mạnh mẽ trong một phương pháp, cho phép hàm hoàn thành. Là tự yếu hay mạnh? Có tài liệu về điều này không? Điều gì sẽ là lý do cho nó được mạnh mẽ hay yếu?

Sửa

Sau khi được lấy cảm hứng từ một số các câu trả lời dưới đây, tôi đã làm một số điều tra. Nguyên nhân thực sự của vụ tai nạn trong trường hợp của tôi là NSNotificationCenter không giữ lại người quan sát trong mọi trường hợp. Mike Weller chỉ ra bên dưới rằng những người gọi phương thức nên giữ lại đối tượng trong khi nó đang được gọi để ngăn chặn trường hợp mà tôi đã mô tả ở trên, tuy nhiên có vẻ như NSNotificationCenter bỏ qua vấn đề này và luôn duy trì một tham chiếu yếu cho người quan sát. Nói cách khác:

-(void)setupNotification{ 
    //observer is weakly referenced when added to NSNotificationCenter 
    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(handleNotification:) 
               name:SomeNotification object:nil]; 
} 

//handle the notification 
-(void)handleNotification:(id)notification{ 
    //owner has reference so this is fine 
    [self doSomething]; 
    //call back to the owner/delegate, owner sets reference to nil 
    [self.delegate didFinish]; 
    //object has been dealloc'ed, crash 
    [self doSomethingElse]; 
} 
+2

Nếu nó là 'weak' sau đó 'self' nên trở thành' nil', và gửi tin nhắn cho' nil' sẽ không sụp đổ. Vì vậy, tôi sẽ đoán, không. – kennytm

+0

Bạn đã sử dụng 'NSLog' để xem có gì với' self.delegate'? – Desdenova

+0

Bạn nên đăng một số mã khác và theo dõi ngăn xếp của bạn, cũng bất kỳ ngoại lệ hoặc lỗi nào đang xảy ra. Đại biểu được tuyên bố như thế nào? –

Trả lời

9

self sẽ mạnh mẽ trong một phương pháp, cho phép chức năng hoàn thành. Là tự yếu hay mạnh?

self không mạnh và yếu trong ARC. Giả định rằng người gọi giữ một tham chiếu và self không an toàn không được giải quyết.

Cũng đúng là self có thể là -dealloc được chỉnh sửa theo phương pháp riêng của mình trong ARC và được coi là "Hành vi không xác định (hoặc ít nguy hiểm nhất)" cho chương trình của bạn.

Lý do nào khiến nó mạnh hoặc yếu?

Không được tiết lộ cho Hiệu suất - để tránh những gì (trong phần lớn các trường hợp) một số tham chiếu không cần thiết inc/dec. Ngay cả khi họ đã làm tất cả những hoạt động đếm số lượng bổ sung, chương trình của bạn vẫn sẽ dễ bị những vấn đề như vậy trong các chương trình đa luồng hoặc trong sự hiện diện của một điều kiện chủng tộc (cũng UB).Vì vậy, đây là một trong những trường hợp cạnh cực đoan mà họ (đúng) xác định họ không cần phải tự bảo vệ mình.

Có tài liệu nào về điều này không?

Of course! :)

+0

"và nó được coi là" Hành vi không xác định (hoặc ít nhất là nguy hiểm) "cho chương trình của bạn để làm điều này." Bạn đang nói, nếu những điều xấu xảy ra trong chương trình của bạn, thì đó là hành vi không xác định. Tất nhiên, nhưng điều đó không hữu ích. Làm thế nào để các lập trình viên biết rằng điều này có thể xảy ra? – newacct

+0

@newacct là trích dẫn từ các tài liệu được liên kết. mục đích của tuyên bố là rõ ràng (mặc dù tôi đã bỏ qua bit "ít nguy hiểm nhất"). điều này không xảy ra tình cờ. nó sẽ * dường như * tình cờ cho đến khi vấn đề được xác định. mục đích của tuyên bố là: khi/nếu chương trình của bạn cho phép điều này xảy ra, coi đó là hành vi không xác định. hành vi không xác định có một định nghĩa rất cụ thể trong C lang. do đó, câu lệnh sẽ chỉ định mức độ nghiêm trọng của lỗi này (nếu gặp phải). một lập trình viên hiểu chương trình của họ có thể xác định nó trong quá trình phát triển. tai nạn và zombie cũng sẽ giúp ích. – justin

+0

Một đối tượng được deallocated khi nó không còn có bất kỳ tài liệu tham khảo mạnh mẽ. Vấn đề là, bất kỳ cuộc gọi phương thức nào cũng có khả năng gây ra tham chiếu mạnh cuối cùng cho đối tượng hiện tại cần xóa. Vì vậy, theo định nghĩa đó, bất kỳ phương pháp nào có chứa một cuộc gọi phương thức là hành vi không xác định (trừ khi được chứng minh bằng cách khác)? Điều đó sẽ làm cho "hành vi được định nghĩa" khá vô nghĩa. – newacct

4

self không phải là yếu cũng không mạnh. Nếu bạn có thể truy cập self thì bạn đang ở trong phạm vi của một cuộc gọi phương thức và cuộc gọi phương thức đó đang được thực hiện bởi ai đó thông qua tham chiếu mà họ phải sở hữu. self được ngụ ý là tham chiếu hợp lệ miễn là nó nằm trong phạm vi và ngụ ý rằng bất kỳ quyền quản lý bộ nhớ hoặc quyền sở hữu nào được xử lý bởi người gọi.

Khi gọi phương thức qua tham chiếu yếu, ARC sẽ giữ lại đối tượng trong suốt thời gian gọi phương thức đó (xem this answer). Với cảnh báo trình biên dịch nghiêm ngặt được bật, bạn sẽ thực sự bị buộc phải tạo tham chiếu mạnh trước khi gửi bất kỳ phương thức nào đến tham chiếu đó. Vì vậy, theo định nghĩa, nếu một phương pháp đang được gọi trên một đối tượng, người gọi phải đã có quyền sở hữu và không có gì cần phải được thực hiện.

Tất nhiên, có thể kết thúc các phương thức gọi trên đối tượng được phân phối lại nhưng đó là kết quả của mã người gọi bị lỗi.

+0

"và cuộc gọi phương thức đó được thực hiện bởi ai đó thông qua tham chiếu mà họ phải sở hữu. Tự được ngụ ý là tham chiếu hợp lệ miễn là phạm vi và được ngụ ý rằng bất kỳ quyền quản lý bộ nhớ hoặc quyền sở hữu nào được xử lý bởi người gọi." Tuy nhiên, một cái gì đó bạn làm trong phương pháp này vô tình có thể phá vỡ mối quan hệ sở hữu ban đầu. Không thể đảm bảo nói chung rằng 'self' sẽ vẫn trỏ đến một đối tượng hợp lệ ở giữa phương thức. – newacct

+0

"Vì vậy, theo định nghĩa, nếu một phương pháp đang được gọi trên một đối tượng, người gọi phải đã có quyền sở hữu và không có gì cần phải được thực hiện." Không cần thiết. Nó chỉ đảm bảo rằng người nhận là hợp lệ tại thời điểm cuộc gọi bắt đầu; không có đảm bảo rằng nó vẫn còn giá trị trong suốt thời gian của cuộc gọi. – newacct

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