2011-10-20 27 views
29

trong khi mã hóa trong iOS 4.3 trước đây, tôi tìm thấy trong khi thêm chế độ xem của trình điều khiển chế độ xem khác với [superview addSubView:controller.view], trường hợp bộ điều khiển sẽ không nhận được thông báo -viewWillAppear/viewDidAppear. một số luồng trong ngăn xếp tràn. Sau đó, tôi tự gọi -viewWillAppear/-viewDidAppear nếu cần.iOS: hành vi addSubview khác nhau giữa iOS 4.3 và 5.0

nhưng, sau khi nâng cấp lên iOS 5.0, một số hành vi nguy hiểm UIView đã xảy ra. Cuối cùng tôi thấy rằng trong iOS 5, [superview addSubView:controller.view], sẽ gửi một thông báo -viewWillAppear/-viewDidAppear đến cá thể bộ điều khiển tự động, cộng với các cuộc gọi thủ công của tôi, có hai thông báo trùng lặp mỗi khi bộ điều khiển hành động hành vi của nó.

và tôi cũng tìm thấy một vấn đề tương tự: iOS 5 : -viewWillAppear is not called after dismissing the modal in iPad

Bây giờ, vấn đề là, sau khi tìm kiếm tài liệu táo, tôi đã không tìm thấy bất kỳ doc rõ ràng cho diff về những vấn đề này. Tôi thậm chí còn tự hỏi liệu đây có phải là hành vi vòng đời xem được đảm bảo trong iOS 5.0 hay không.

Có ai khắc phục sự cố tương tự hoặc tìm một số nguyên tắc về sự khác biệt này không. vì tôi muốn chạy ứng dụng của mình cả trong 4.x & 5.x iOS.

+1

Như bạn đã phát hiện ra, chỉ có khoảng 10% trong những thay đổi giữa iOS 4 và iOS 5 được ghi nhận một cách rõ ràng. –

Trả lời

28

Trong iOS 4, bạn phải gọi thủ công -viewWillAppear, -viewWillDisappear, v.v. khi thêm hoặc xóa chế độ xem khỏi cấu trúc phân cấp chế độ xem của bạn. Chúng được gọi tự động trong iOS 5 nếu chế độ xem đang được thêm hoặc bị xóa khỏi hệ thống phân cấp cửa sổ. May mắn thay, iOS 5 có một phương pháp trong UIViewController mà bạn có thể ghi đè lên để trở lại hành vi đó trở về làm thế nào nó làm việc với iOS 4. Chỉ cần thêm video này vào UIViewController của bạn:

-(BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers { 
    return NO; 
} 

Đây có lẽ là giải pháp dễ nhất miễn là bạn đang hỗ trợ cả iOS 4 và iOS 5. Khi bạn thả hỗ trợ cho iOS 4, bạn có thể xem xét sửa đổi mã của mình để sử dụng phương pháp mới hơn khi hoán đổi chế độ xem.

Chỉnh sửa ngày 05 Tháng 2 2012

Rõ ràng chức năng này đòi hỏi người điều khiển xem đứa trẻ được bổ sung vào bộ điều khiển giao diện chính bằng cách sử dụng phương pháp addChildViewController:. Phương pháp này không tồn tại trong iOS4, vì vậy bạn cần phải làm điều gì đó như thế này:

if ([self respondsToSelector:@selector(addChildViewController:)]) { 
    [self addChildViewController:childViewController]; 
    } 

Nhờ mọi người sửa lại cho tôi về vấn đề này.

+0

Cảm ơn rất nhiều bạn !!!! –

+0

Cảm ơn, đã khắc phục sự cố trên ios4 nhưng trên ios5 viewWillAppear được gọi hai lần (một từ lệnh gọi thủ công mà tôi đưa vào) không chắc chắn tại sao. – richy

+1

Richy .. Thật lạ khi phương thức này bị bỏ qua trong iOS4 và chỉ được gọi trong iOS5. Bạn có thể muốn kiểm tra lại kết quả của mình. – chris

0

Bằng phương pháp này u biết mà os u sử dụng và đặt điều kiện nếu là ít hơn 5.0 hoặc một khác

[[UIDevice currentDevice] systemVersion]

+0

Tôi biết cách này làm một số trợ giúp. Và tôi muốn biết thêm về sự khác biệt như thế này. – KrzyCube

9

Điều này có thể không phải là một câu trả lời những gì bạn muốn, nhưng Tôi đã có cùng một loại vấn đề.

Trong trường hợp của mình, khi tôi thêm chế độ xem của trình điều khiển chế độ xem vào chế độ xem của trình điều khiển chế độ xem khác dưới dạng chế độ xem phụ, chế độ xem phụ đã được nhận viewWillAppear chỉ trong iOS 5.0 chứ không phải iOS 4.X.

Vì vậy, tôi đã thêm một điều kiện khó chịu.

[self.view addSubview:self.viewController.view]; 
if ([[[UIDevice currentDevice] systemVersion] compare:@"5.0"] == NSOrderedAscending) { 
    [self.viewController viewWillAppear:animated]; 
} 

Từ iOS 5.0, Apple provides a way to implement custom container view controllers like UINavigationController or UITabController. Tôi nghĩ thay đổi này ảnh hưởng đến khi viewWillAppear được gọi.

Sự cố này có thể được giải quyết nếu chúng tôi sử dụng -[UIViewController addChildViewController:].

+0

Tôi không nghĩ rằng nó có bất cứ điều gì để làm với phiên bản hệ điều hành. API vẫn giữ nguyên. Có các quy tắc cố định là khi viewWillApear/Disappear sẽ được gọi. http://stackoverflow.com/questions/131062/iphone-viewwillappear-not-firing – zakishaheen

+0

cảm ơn rất nhiều sự giúp đỡ của bạn! :) –

2

Đó là hành vi iOS5:
chế độ xemLàm mới, xemDidAppear, ... được thực thi tự động sau addSubView: cho iOS5.
Vì vậy, đối với iOS5, không cần phải thực hiện thủ công các phương pháp đó khi cần thiết cho iOS < 5.0.

Việc sửa chữa có thể là:

if ([[UIDevice currentDevice].systemVersion doubleValue] < 5.0) { 
...execute viewWillAppear or other 
} 
0

view{Will,Did}Appear, view{Will,Did}Disappear là chức năng trên Xem Controller và không xem. Các chức năng này được gọi bởi bộ điều khiển chế độ xem được cung cấp SDK được cho là quản lý các bộ điều khiển chế độ xem khác, ví dụ: UITabBarController, UINavigationBarController.

Nếu bạn tự quản lý các trình điều khiển phụ, bạn phải gọi những điều này một cách rõ ràng (và theo thứ tự đúng - mặc dù bạn nên có lý do chính đáng để thực hiện việc này). Một chế độ xem không nhận được các cuộc gọi này khi loại bỏ một chế độ xem đơn giản chỉ đơn giản là vì không có ai để gọi nó.Đóng gói bộ điều khiển chế độ xem gốc trong một UINavigationController (và ẩn thanh điều hướng nếu bạn muốn) và sau đó mở một bộ điều khiển chế độ xem phương thức. Sau khi loại bỏ, hoặc bật, số viewWillAppear sẽ được gọi.

5

Câu trả lời ở trên hơi không đầy đủ. Giả sử bạn có 2 bộ điều khiển xem, ControllerA và ControllerB.

ControllerA.view đã được thêm vào cửa sổ (nó là phụ huynh) và bạn muốn thêm ControllerB.view dưới dạng chế độ xem con của ControllerA.

Nếu bạn không thêm ControllerB làm con của ControllerA trước, thì tự độngForwardAppearanceAndRotationMethodsToChildViewControllers sẽ bị bỏ qua và bạn vẫn sẽ được gọi bởi iOS5, có nghĩa là bạn sẽ gọi callback của trình điều khiển xem hai lần.

Ví dụ trong ControllerA:

- (BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers { 
    return NO; 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    self.controllerB = [[ControllerB alloc] initWithNibName:@"ControllerB" bundle:nil]; 

    [self.view addSubview:self.controllerB.view]; 
} 

- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 
    [self.controllerB viewWillAppear:animated]; 
} 

Trong ControllerB NSLogging trong viewWillAppear:

- (void)viewWillAppear:(BOOL)animated 
{ 
    NSLog("@ControllerB will appear"); 
} 

này sẽ dẫn đến iOS5 chỉ hiển thị rằng NSLog nhắn hai lần. tức là Bạn đang tự độngForwardAppearanceAndRotationMethodsToChildViewControllers đã bị bỏ qua.

Để khắc phục điều này, bạn cần thêm controllerB làm con của bộ điều khiển a.

Quay trở lại lớp ControllerA của:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    self.controllerB = [[ControllerB alloc] initWithNibName:@"ControllerB" bundle:nil]; 
    if ([self respondsToSelector:@selector(addChildViewController:)]) 
     [self addChildViewController:self.controllerB]; 

    [self.view addSubview:self.controllerB.view]; 
} 

này bây giờ sẽ làm việc như mong đợi trong cả iOS4 và iOS5 mà không cần đến việc hack khủng khiếp của việc kiểm tra chuỗi phiên bản iOS, nhưng thay vào đó kiểm tra trên nếu chức năng chúng tôi sau có sẵn.

Hy vọng điều này sẽ hữu ích.

0

Sau khi xem xét tất cả các bằng chứng, tôi nghĩ điều tốt nhất cần làm là KHÔNG sử dụng viewDidAppear vv cho các lượt xem bị ảnh hưởng bởi lỗi ios 4/ios 5 này.Thay vào đó hãy tạo một lớp tùy chỉnh (như viewDidAppearCustom) và tự gọi nó. bằng cách này bạn có thể đảm bảo rằng táo sẽ không thay đổi sdk một lần nữa và mess bạn lên. Có một blog tuyệt vời bao gồm vấn đề này ở đây:

http://gamesfromwithin.com/view-controller-notification-changes-on-ios5

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