2010-07-07 16 views
9

Tôi có bộ điều khiển điều hướng. Một trong các chế độ xem thêm các bản xem phụ tùy chỉnh trong số viewDidAppear:. Tôi nhận thấy rằng lần đầu tiên tôi điều hướng đến một thể hiện của bộ điều khiển chế độ xem này sau khi khởi chạy ứng dụng, viewDidAppear: gọi hai lần. Nếu tôi bật chế độ xem này khỏi ngăn xếp và điều hướng lại, viewDidAppear: chỉ gọi một lần cho mỗi lần xuất hiện. Tất cả các lần xuất hiện tiếp theo đều gọi viewDidAppear: một lần.viewDidAppear được gọi hai lần trên cùng một trường hợp, nhưng chỉ lần đầu tiên lớp này tải biểu mẫu NIB

Vấn đề đối với tôi là lần đầu tiên tôi nhận được quan điểm này, tôi kết thúc gấp đôi số lượng các bản xem trước. Tôi làm việc xung quanh vấn đề này bằng cách giới thiệu một biến cờ hoặc một số như vậy, nhưng tôi muốn hiểu những gì đang xảy ra và làm thế nào để tôi nhận được hai invocations trong những trường hợp này.

Trả lời

14

Bạn không bao giờ nên dựa vào số -viewWillAppear:/-viewDidAppear: được gọi là cân bằng hợp lý với các biến thể biến mất. Trong khi các bộ điều khiển xem hệ thống sẽ làm tốt nhất có thể để luôn luôn thực hiện đúng các cuộc gọi, tôi không biết liệu chúng có bảo đảm nó hay không, và chắc chắn khi sử dụng các bộ điều khiển xem tùy chỉnh, bạn có thể tìm thấy các tình huống có thể được gọi nhiều lần.

Trong ngắn hạn, các phương pháp -viewWillAppear:/-viewDidAppear: của bạn phải là idempotent, nghĩa là nếu -viewDidAppear: được gọi hai lần liên tiếp trên bộ điều khiển của bạn, nó sẽ hoạt động đúng. Nếu bạn muốn tải chế độ xem tùy chỉnh, bạn có thể muốn thực hiện điều đó trong -viewDidLoad thay thế và sau đó chỉ cần đặt trên màn hình (nếu chúng chưa có) trong -viewDidAppear:.

Bạn cũng có thể đặt điểm ngắt trong phương pháp -viewDidAppear: của mình để xem lý do tại sao nó được gọi hai lần vào lần đầu tiên hiển thị.

+0

Tôi có điểm ngắt trong 'viewDidAppear:'. Làm thế nào nó có thể trả lời câu hỏi tại sao? – iter

+0

Nhìn vào dấu vết ngăn xếp để tìm hiểu lý do tại sao hệ thống đang gọi phương thức này. Nếu backtrace là khác nhau cho cả hai cuộc gọi, bạn có thể sử dụng điều này để thử và tìm ra những gì đang xảy ra. Điều này có thể hoặc có thể không hữu ích mặc dù, tùy thuộc vào chính xác những gì được chứa trong backtrace. –

+0

Các ngăn xếp trông giống hệt nhau, do đó sự ngạc nhiên của tôi theo đề xuất của bạn. Giải pháp của tôi là cấu trúc lại mã để tôi có thể gọi mã trong 'viewDidAppear:' gián tiếp từ 'viewDidLoad:', và vì vậy tránh toàn bộ vấn đề. Tôi chấp nhận câu trả lời của bạn mặc dù lời kêu gọi kép vẫn là một bí ẩn đối với tôi. – iter

1

có thể bạn gọi viewDidAppear trong viewDidLoad (hoặc một số nội dung khác đang diễn ra ở đó), vì nó chỉ được gọi một lần trong khi tải chế độ xem từ bộ nhớ. Nó sẽ phù hợp, mà nó được gọi hai lần chỉ lần đầu tiên.

+0

Đó là suy nghĩ đầu tiên của tôi. Nhưng không, tôi không làm thế. Và nếu tôi đặt một điểm dừng để xem lệnh gọi 'viewDidAppear:', không có phương thức nào của riêng tôi xuất hiện trong nó. – iter

0

Bạn chắc chắn nên cung cấp thêm thông tin.

Đây có phải là bộ điều khiển chế độ xem gốc không?
Có thể bạn bắt đầu bộ điều khiển điều hướng với bộ điều khiển chế độ xem gốc này và sau đó đẩy nó vào bộ điều khiển điều hướng một lần nữa?

+0

Ý tưởng thú vị, nhưng không, tôi không đẩy nó hai lần. Tôi 'NSLog (@"% @ ", [[self navigationController] viewControllers]);' từ 'viewDidAppear' và xem một thể hiện của khung nhìn của tôi nằm ở phía trên cùng của khung nhìn gốc. – iter

+0

Có thể bạn có 2 bộ điều khiển điều hướng do nhầm lẫn? –

0

Một giải pháp khác có thể là nguyên nhân cơ bản của bạn: Đảm bảo bạn không trình bày bất kỳ bộ điều khiển chế độ xem mới nào trong phương thức viewWillAppear: của mình.

Tôi đã gọi:

[appDel.window.rootViewController presentViewController:login animated:YES completion:nil]; 

từ bên trong viewWillAppear và nhìn thấy nguồn gốc của tôi phương pháp VC của viewDidAppear: gọi hai lần liên tiếp với chồng cùng dấu vết như bạn đề cập.Và không có cuộc gọi trung gian để viewDidDisappear:

Moving presentViewController: đến nguồn gốc phương pháp viewDidAppear: VC xoá sổ các vấn đề hai cuộc gọi, và vì vậy bây giờ dòng chảy là:

  1. gốc viewDidAppear: gọi
    • Gọi presentViewController đây
  2. Gốc viewDidDisappear: được gọi là
  3. xem mới được trình bày và không còn mang lại cho tôi một lời cảnh báo về "unbalanced VC display"

cố định với sự giúp đỡ từ câu trả lời này: https://stackoverflow.com/a/13315360/1143123 trong khi cố gắng giải quyết "Unbalanced calls to begin/end appearance transitions for ..."

-1

nó là một vấn đề khó chịu, bạn nghĩ rằng nó chạy một lần nhưng sau đó tôi phát hiện ra điều này đang gây ra tình trạng lộn xộn ... Điều này áp dụng cho tất cả 3 (ViewDidAppear, ViewDidLoad và ViewWillAppear), tôi nhận được điều này khi tích hợp với một thiết bị đầu cuối thanh toán; một khi nó kết thúc gọi API, cửa sổ đang được nạp lại khi nó đã có trên màn hình và tất cả bộ nhớ của nó vẫn còn đó (không được giữ lại).

tôi giải quyết nó bằng cách làm như sau cho tất cả các thói quen đề cập ở trên, dưới đây là một ví dụ để một trong số họ:

BOOL viewDidLoadProcessed = false; 

-(void)viewDidLoad:(BOOL)animated 
{ 
    if (!viewDidLoadProcessed) 
    { 
     viewDidLoadProcessed = YES; 
     . 
     . 
     . 
     ... do stuff here... 
     . 
     . 
    } 
} 

Lặp lại ở trên cho tất cả hai người còn lại, điều này ngăn không cho nó chạy gấp đôi. Điều này không bao giờ xảy ra trước khi Steve Jobs qua đời !!!

Kind Regards Heider Sati

1

Nếu bạn có một dòng như thế này trong appdelegate bạn

window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 

chắc chắn rằng bạn không có một "Main tập tin nib tên cơ sở" bất động sản trong plist của bạn đặt thành "Window.xib" hoặc bất kỳ cửa sổ tùy chỉnh nào được đặt tên. Nếu bạn làm như vậy, hãy xóa hàng đó khỏi danh sách của bạn và đảm bảo rằng bạn giống như

yourRootVC = [[UIViewController alloc] init]; 
[window setRootViewController:yourRootVC]; 

trong AppDelegate sau khi khởi động cửa sổ của bạn. Trong hầu hết các trường hợp, bạn có thể xóa Window.xib một cách an toàn.

1

Thêm [super viewDidAppear:animated]; làm việc cho tôi:

//Called twice 
- (void)viewDidAppear:(BOOL)animated{ 

} 

//Called once 
- (void)viewDidAppear:(BOOL)animated{ 
    [super viewDidAppear:animated]; 
} 
+1

Khi ghi nhật ký này, siêu không dừng tải hai lần. –

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