ViewController responseToSelector: thông báo được gửi đến phiên bản đã được phân bổ (CRASH)


95

Ok, đây là thỏa thuận, tôi ghét đặt câu hỏi về việc gỡ lỗi và sự cố của tôi. Bởi vì tôi thường tự xử lý chúng, nhưng tôi không thể giải quyết vấn đề này, ngay cả khi đã xem nhiều câu hỏi .

Ok, đây là vấn đề, tôi thấy ứng dụng của mình ngẫu nhiên bật và tắt với dấu vết ngăn xếp này:

*** -[ViewController respondsToSelector:]: message sent to deallocated instance 0x1e5d2ef0

Nơi nào ViewControllercó thể thay đổi, đôi khi là nơi mã của tôi gặp sự cố, KHÔNG liên quan đến cụ thể đó ViewControllervà không sở hữu hoặc gọi nó.

Ngoài ra, để lấy dấu vết bảng điều khiển đó, tôi đã kích hoạt Zombies, nếu không tôi sẽ không nhận được bản in bảng điều khiển nào cả, tôi chỉ nhận được:, objc_msgSendmà tôi biết có nghĩa là tôi đang nhắn tin cho một thứ gì đó được phát hành. Nhưng tôi không thể tìm thấy đó là đâu ... Tôi thực sự bị mắc kẹt! Thông thường tôi luôn gỡ lỗi các sự cố của mình, vì vậy tôi thực sự bị mắc kẹt về điều này.

Một lần nữa, điều này xảy ra ở những nơi khác nhau vào những thời điểm khác nhau, bật và tắt. Và nơi nó bị rơi hầu như không liên quan đến ViewController. Và tôi thấy điều này rất khó hiểu.

Bạn có cần mã của tôi không? Tôi có rất nhiều tệp và vì nó bị rơi ở nhiều nơi khác nhau, việc phân phối mã của tôi sẽ rất lộn xộn!

Tôi đã cố gắng thêm các điểm ngắt biểu tượng nhưng không may mắn và Zombies không khả dụng trên ứng dụng Instruments dành cho iOS. Tôi không thể chạy ứng dụng của mình trên trình mô phỏng vì nó có các khung kiến ​​trúc không hỗ trợ cho nó.

Cảm ơn mọi người...


bạn đã xem câu hỏi này chưa: stackoverflow.com/questions/1585688/…
self.

Giả sử cách bạn chuyển đổi sang quan điểm của mình là nhất quán, có thể bạn có thể cho chúng tôi xem một hoặc hai ví dụ. Nếu bạn đang thực hiện lệnh gọi push / presentViewController tiêu chuẩn, bạn sẽ ổn, nhưng tôi thấy rất nhiều người ở đây làm những việc như cấp phát / init'ing một bộ điều khiển chế độ xem, nhưng sau đó không thực hiện đẩy / hiện tại mà chỉ thêm bộ điều khiển của xem như một lượt xem phụ. Chỉ là một ví dụ ngẫu nhiên. Nhưng chúng tôi không thể chẩn đoán điều này nếu không có một số mã. Hy vọng rằng một vài đoạn trích sẽ giúp chúng ta tìm ra những gì đang xảy ra, hãy cùng xem.
Rob

Làm thế nào về việc kích hoạt các điểm ngắt biểu tượng? Hãy thử thêm những thứ này: wiki.zemingo.com/index.php?title=Symbolic_Breakpoints
Stavash

@RobertRyan Tôi sử dụng presentModalViewController, tôi không thêm nó làm chế độ xem phụ
MCKapur

Trong trường hợp của tôi, bộ điều khiển chế độ xem con của tôi chứa một webView và VC con là đại biểu cho scrollView của webView. Tôi cần xóa thủ công tham chiếu đại biểu trong dealloc / viewWillDisappear, nếu không tôi gặp sự cố này. Hy vọng nó sẽ giúp một ai đó.
Dermot

Câu trả lời:


169

Sử dụng Công cụ để theo dõi các lỗi phiên bản được phân bổ theo thỏa thuận. Cấu hình ứng dụng của bạn ( Cmd ⌘+ I) và chọn mẫu Zombies . Sau khi ứng dụng của bạn đang chạy, hãy thử xử lý sự cố. Bạn sẽ nhận được một cái gì đó như thế:

nhập mô tả hình ảnh ở đây

Nhấp vào mũi tên bên cạnh địa chỉ trong cửa sổ bật lên để hiển thị đối tượng đã được gọi sau khi nó được phân bổ.

nhập mô tả hình ảnh ở đây

Bây giờ bạn sẽ thấy mọi cuộc gọi đã thay đổi số lượng giữ lại của đối tượng này. Điều này có thể là do việc gửi trực tiếp các thông báo giữ lại / giải phóng cũng như làm cạn kiệt các vùng tự động phát hành hoặc chèn vào các NSArrays.

Cột RefCt hiển thị số tiền giữ lại sau khi hành động được gọi và Người gọi có trách nhiệm hiển thị tên lớp và phương thức mà nó được thực hiện. Khi bạn nhấp đúp vào bất kỳ bản giữ lại / phát hành nào, các công cụ sẽ hiển thị cho bạn dòng mã nơi điều này được thực hiện (Nếu điều này không hoạt động, bạn có thể kiểm tra cuộc gọi bằng cách chọn nó và chọn đối tác của nó trong ngăn Chi tiết Mở rộng ):

nhập mô tả hình ảnh ở đây

Điều này sẽ cho phép bạn kiểm tra tất cả vòng đời của đối tượng KeepCount và có thể bạn sẽ tìm ra vấn đề của mình ngay lập tức. Tất cả bạn phải làm là tìm người mất tích giữ lại cho mới nhất phát hành .


3
Vấn đề có thể không phải là mới nhất release, cụ thể. Vấn đề là bất kỳ sự không cân bằng nàorelease . Tôi cũng có thể chỉ đơn giản là thất bại với retainmột cái gì đó mà bạn đang lưu ý đến và tham khảo sau này.
Ken Thomases

1
Ngoài ra, tôi không có một công cụ Zombie mẫu, mà có thể là do tôi đang sử dụng Xcode Beta 4.5, tôi sẽ chuyển sang 4.4 trong thời gian này
MCKapur

2
Ồ, Zombies chỉ được cung cấp trong trình mô phỏng iOS. Tôi không thể chạy trong iOS mô phỏng, một số trong các khuôn khổ và các thư viện của tôi sử dụng không hỗ trợ kiến trúc
MCKapur

Chỉ là một lưu ý nhỏ. Đây là từ tính năng mới trong xcode 5. "Mẫu công cụ Zombies đã được cải tiến trong Xcode 5 và hiện hỗ trợ sử dụng trên các thiết bị. Sử dụng Zombies trên thiết bị yêu cầu iOS 7." Lưu ý này mang đến cho bạn bởi tôi và 2 giờ của thời gian quý báu của tôi ...
nickfox

2
Điều đó có nghĩa là gì nếu Ứng dụng của chúng tôi ngừng gặp sự cố và ngừng đưa ra lỗi "thông báo được gửi đến phiên bản được phân bổ" khi chúng tôi kết nối công cụ này với nó? (Cứ như thể "căn bệnh" biến mất khi bệnh nhân được làm "xét nghiệm chẩn đoán".)
Praxiteles

59

đã gặp vấn đề tương tự. Trong trường hợp của tôi, một viewController cần để nhận các sự kiện navigationController, vì vậy nó đang đăng ký làm đại biểu điều khiển điều hướng:

 self.navigationController.delegate = self;

Sự cố xảy ra khi bộ điều khiển đó đã được phân bổ nhưng vẫn là đại biểu cho bộ điều khiển chế độ xem. Việc thêm mã này vào dealloc không có tác dụng:

-(void) dealloc
{
    if (self.navigationController.delegate == self)
    {
        self.navigationController.delegate = nil;
    }

bởi vì tại thời điểm mà dealloc được gọi, bộ điều khiển chế độ xem đã bị xóa khỏi hệ thống phân cấp chế độ xem, vì vậy self.navigationController là nil, vì vậy việc so sánh được đảm bảo sẽ thất bại! :-(

Giải pháp là thêm mã này để phát hiện VC rời khỏi hệ thống phân cấp chế độ xem ngay trước khi nó thực sự làm như vậy. Nó sử dụng một phương pháp được giới thiệu trong iOS 5 để xác định khi nào chế độ xem đang được bật lên và không được đẩy

-(void) viewWillDisappear:(BOOL) animated
{  
   [super viewWillDisappear:animated];
   if ([self isMovingFromParentViewController])
   {
      if (self.navigationController.delegate == self)
      {
           self.navigationController.delegate = nil;
      }
   }
}

Không còn sự cố!


Tôi cũng vậy, cảm ơn - chỉ cần 4 giờ tìm kiếm để tìm thấy bài đăng này.
daidai

Cảm ơn bạn đã đăng bài, có cùng một vấn đề ^^
Tyron

Làm thế nào để mọi người tìm ra giải pháp cho một vấn đề khó chịu như vậy? Bỏ mũ ra !!
ViruMax

4

Đối với bất kỳ ai không thể giải quyết nó, đây là một số kỹ thuật khác:

https://stackoverflow.com/a/12264647/539149

https://stackoverflow.com/a/5698635/539149

https://stackoverflow.com/a/9359792/539149

https://stackoverflow.com/a/15270549/539149

https://stackoverflow.com/a/12098735/539149

Bạn có thể chạy Công cụ trong Xcode 5 bằng cách nhấp vào cửa sổ bật lên của dự án-> Chỉnh sửa sơ đồ ... Hồ sơ -> Công cụ và chọn Phân bổ hoặc Rò rỉ, sau đó lập hồ sơ ứng dụng của bạn, sau đó dừng Công cụ, nhấp vào nút thông tin trong Phân bổ và "Bật phát hiện NSZombie" .

Tuy nhiên, đối với các tin nhắn đến trực tiếp từ com.apple.main-thread, điều này có thể sẽ không tiết lộ bất cứ điều gì.

Tôi đã đập đầu vào điều này trong hơn hai giờ và câu trả lời hóa ra là một sự phát hành quá mức, tôi đã phát hiện ra bằng cách bình luận về một bản sao dự án của mình bằng vũ lực cho đến khi tôi tìm ra thủ phạm:

[viewController release];
viewController = NULL;

Vấn đề là bản phát hành không đặt biến thành NULL.

Điều đó có nghĩa là việc đặt nó thành NULL các cuộc gọi sẽ giải phóng một lần nữa, giảm số lượng lại và giải phóng bộ nhớ ngay lập tức cho đến khi các biến tham chiếu viewController kết thúc với nó.

Vì vậy, hãy bật ARC hoặc đảm bảo rằng dự án của bạn luôn sử dụng bản phát hành hoặc NULL nhưng không sử dụng cả hai. Sở thích của tôi là sử dụng NULL vì khi đó không có cơ hội tham chiếu đến một thây ma nhưng nó làm cho việc tìm kiếm nơi các đối tượng được thả khó khăn hơn.


4

Tôi đã gặp vấn đề tương tự trong iOS ngày hôm qua. Tôi đã tạo IAP trong chế độ xem phụ "Giới thiệu" về ứng dụng và tôi đã thêm Trình quan sát giao dịch trong "Giới thiệu" viewDidLoad. Khi tôi mua hàng lần đầu tiên, không có vấn đề gì, nhưng sau khi tôi quay lại cửa sổ chính và nhập về chế độ xem phụ để mua hàng lần nữa, sự cố "thông báo được gửi đến phiên bản deallocated" đã xảy ra và ứng dụng bị lỗi.

- (void)viewDidLoad
{
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];                                           object:nil];
}

Sau khi tôi loại bỏ Trình quan sát giao dịch trong dealloc, vấn đề đã được giải quyết.

- (void)dealloc
{
    // Even though we are using ARC, we still need to manually stop observing any
    // NSNotificationCenter notifications.  Otherwise we could get "zombie" crashes when
    // NSNotificationCenter tries to notify us after our -dealloc finished.

    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}

Nó đã khắc phục sự cố thời gian chạy của tôi ... Tôi đã nhận được zombieđối tượng để mua hàng trong ứng dụng. Sau nhiều giờ đào bới, tôi đã tìm thấy cái này .... MỘT NGƯỜI CÁM ƠN LỚN.
Mahendra

4

Tôi đã gặp một vấn đề rất tương tự và tôi đã phát hiện ra đó là do bộ điều khiển điều hướng được thiết lập.

Bên dưới đã giải quyết vấn đề của tôi,

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if (self.navigationController.delegate != self) {
        self.navigationController.delegate = self;
    }
}

-(void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];

    if (self.navigationController.delegate == self) {
        self.navigationController.delegate = nil;
    }
}

Cảm ơn!! cùng một vấn đề ở đây.
pegpeg

2

Gặp sự cố tương tự trong OS X.

Để giải quyết điều này không đủ - (void)deallocphương pháp như @SoftwareEvolved đã nói. Nhưng tiếc - (void)viewWillDisappearlà chỉ có trên phiên bản 10.10 trở lên.

Tôi đã giới thiệu phương thức tùy chỉnh trong lớp con NSViewController của mình, nơi đặt tất cả các tham chiếu nguy hiểm cho zombie thành nil. Trong trường hợp của tôi, đó là NSTableViewthuộc tính ( delegatedataSource).

- (void)shutdown
{
  self.tableView.delegate = nil;
  self.tableView.dataSource = nil;
}

Đó là tất cả. Mỗi lần tôi sắp xóa chế độ xem khỏi chế độ xem siêu cao cần gọi phương thức này.


2

Tôi đã gặp vấn đề tương tự. Rất khó để tìm đại biểu nào gây ra sự cố, vì nó không chỉ ra bất kỳ dòng hoặc câu lệnh mã nào Vì vậy, tôi đã thử một số cách, Có thể nó sẽ hữu ích cho bạn.

  1. Mở tệp xib và từ chủ sở hữu tệp, Chọn "hiển thị trình kiểm tra kết nối" bên phải. Các đại biểu được liệt kê, đặt chúng thành nil bị nghi ngờ.
  2. (Tương tự như trường hợp của tôi) Đối tượng thuộc tính như Textfield có thể tạo ra vấn đề, Vì vậy, hãy đặt các đại biểu của nó thành nil.
-(void) viewWillDisappear:(BOOL) animated{

[super viewWillDisappear:animated];

if ([self isMovingFromParentViewController]){

self.countryTextField.delegate = nil;

self.stateTextField.delegate = nil;

}

}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.