2013-04-07 20 views
122

Tôi có Bộ điều khiển chế độ xem có giá trị là 0 (nhãn) và khi tôi mở Bộ điều khiển xem đó từ ViewController Tôi đã đặt viewDidAppear để đặt giá trị 20 trên nhãn. Nó hoạt động tốt nhưng khi tôi đóng ứng dụng của tôi và hơn một lần nữa tôi mở ứng dụng của tôi nhưng giá trị không thay đổi bởi vì viewDidLoad, viewDidAppearviewWillAppear không có gì được gọi. Làm thế nào tôi có thể gọi khi tôi mở ứng dụng của mình. Tôi có phải làm bất cứ điều gì từ applicationDidBecomeActive không?ViewDidAppear không được gọi khi mở ứng dụng từ nền

+0

Bạn có thể đăng thông báo cục bộ khi ứng dụng hoạt động và thêm bộ điều khiển chế độ xem làm người quan sát và cập nhật giá trị. –

Trả lời

257

Tò mò về trình tự chính xác của các sự kiện, tôi instrumented một ứng dụng như sau: (@Zohaib, bạn có thể sử dụng mã NSNotificationCenter dưới đây để trả lời câu hỏi của bạn).

// AppDelegate.m 

- (void)applicationWillEnterForeground:(UIApplication *)application 
{ 
    NSLog(@"app will enter foreground"); 
} 

- (void)applicationDidBecomeActive:(UIApplication *)application 
{ 
    NSLog(@"app did become active"); 
} 

// ViewController.m 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    NSLog(@"view did load"); 

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; 
} 

- (void)appDidBecomeActive:(NSNotification *)notification { 
    NSLog(@"did become active notification"); 
} 

- (void)appWillEnterForeground:(NSNotification *)notification { 
    NSLog(@"will enter foreground notification"); 
} 

- (void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 
    NSLog(@"view will appear"); 
} 

- (void)viewDidAppear:(BOOL)animated { 
    [super viewDidAppear:animated]; 
    NSLog(@"view did appear"); 
} 

Khi khởi chạy, đầu ra trông như thế này:

2013-04-07 09:31:06.505 myapp[15459:11303] view did load 
2013-04-07 09:31:06.507 myapp[15459:11303] view will appear 
2013-04-07 09:31:06.511 myapp[15459:11303] app did become active 
2013-04-07 09:31:06.512 myapp[15459:11303] did become active notification 
2013-04-07 09:31:06.517 myapp[15459:11303] view did appear 

Nhập nền sau đó nhập lại foreground:

2013-04-07 09:32:05.923 myapp[15459:11303] app will enter foreground 
2013-04-07 09:32:05.924 myapp[15459:11303] will enter foreground notification 
2013-04-07 09:32:05.925 myapp[15459:11303] app did become active 
2013-04-07 09:32:05.926 myapp[15459:11303] did become active notification 
+1

Danh, bạn đã ánh xạ UIApplicationWillEnterForegroundNotification tới appDidEnterForeground :. Đó không phải là một chút sai lầm? Thông báo "sẽ" và "đã làm". Điều đó có chủ ý không? – Lubiluk

+0

@Lubiluk - không cố ý. Tôi sẽ chỉnh sửa. Nắm bắt tốt. – danh

+2

Đây là một câu trả lời rất hữu ích. Tôi đã thực hiện một phiên bản Swift của nó [ở đây] (http://stackoverflow.com/a/34529572/3681880). – Suragch

2

Chỉ cần có bộ điều khiển chế độ xem của bạn đăng ký thông báo UIApplicationWillEnterForegroundNotification và phản ứng tương ứng.

+0

Tôi sẽ làm như thế nào? tôi đã gọi viewController của tôi trong applicationDidBecomeActive nhưng. nó chồng chéo viewController hoặc tiền phạt của nó để làm điều đó? – Zohaib

+2

Không gọi chế độ xem của bạnController trong ứng dụngDidBecomeActive (dù sao cũng sai vì nó được gọi nhiều lần). Đăng ký thông báo trong 'viewDidLoad' của bạn như @nsgulliver được đề xuất.'ViewDidAppear' của bạn cũng sẽ gọi' doYourStuff' để đặt nhãn của bạn với giá trị mong muốn. – andreagiavatto

111

Sử dụng Objective-C

Bạn nên đăng ký một UIApplicationWillEnterForegroundNotification trong ViewController của bạn 's viewDidLoad phương pháp và bất cứ khi nào ứng dụng trở lại từ nền bạn có thể làm bất cứ điều gì bạn muốn làm trong phương pháp đăng ký thông báo. ViewController 's viewWillAppear hoặc viewDidAppear sẽ không được gọi khi ứng dụng quay lại từ nền tới nền trước.

-(void)viewDidLoad{ 

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doYourStuff) 

    name:UIApplicationWillEnterForegroundNotification object:nil]; 
} 

-(void)doYourStuff{ 

    // do whatever you want to do when app comes back from background. 
} 

Đừng quên hủy đăng ký thông báo bạn đã đăng ký.

-(void)dealloc { 
    [[NSNotificationCenter defaultCenter] removeObserver:self]; 
} 

Note nếu bạn đăng ký của bạn viewController cho UIApplicationDidBecomeActiveNotification sau đó phương pháp của bạn sẽ được gọi mỗi khi ứng dụng của bạn trở nên linh hoạt, Nó không được khuyến khích đăng ký viewController cho thông báo này.

Sử dụng Swift

Để thêm người quan sát bạn có thể sử dụng đoạn mã sau

override func viewDidLoad() { 
    super.viewDidLoad() 

    NSNotificationCenter.defaultCenter().addObserver(self, selector:"doYourStuff", name: 
    UIApplicationWillEnterForegroundNotification, object: nil) 
} 

func doYourStuff(){ 
    // your code 
} 

Để loại bỏ quan sát bạn có thể sử dụng deinit chức năng nhanh chóng.

deinit { 
    NSNotificationCenter.defaultCenter().removeObserver(self) 
} 
+5

Mang một sự tương đồng đáng chú ý đến http://stackoverflow.com/a/15854893/341994 :) – matt

+4

Có, đó là :) đôi khi rất khó để tìm câu trả lời :) – nsgulliver

+0

@nsgulliver Tôi có phải tự hủy bỏ đăng ký thông báo không - (void) dealloc { [[NSNotificationCenter defaultCenter] removeObserver: self]; }. Ứng dụng sẽ làm điều đó cho tôi chứ? – ios

4

Tôi nghĩ rằng việc đăng ký cho UIApplicationWillEnterForegroundNotification là nguy hiểm như bạn có thể kết thúc với nhiều hơn một bộ điều khiển phản ứng với thông báo đó. Không có gì garanties rằng các bộ điều khiển vẫn còn nhìn thấy khi nhận được thông báo.

Dưới đây là những gì tôi làm: Tôi buộc gọi viewDidAppear trên bộ điều khiển hoạt động trực tiếp từ phương pháp đại biểu didBecomeActive của App:

Thêm mã dưới đây để - (void)applicationDidBecomeActive:(UIApplication *)application

UIViewController *activeController = window.rootViewController; 
if ([activeController isKindOfClass:[UINavigationController class]]) { 
    activeController = [(UINavigationController*)window.rootViewController topViewController]; 
} 
[activeController viewDidAppear:NO]; 
+5

Nó được đảm bảo nếu bộ điều khiển unregisters (vì nó nên) cho UIApplicationWillEnterForegroundNotification trong viewWillDisappear thay vì trong dealloc. Gọi viewDidAppear rõ ràng trông giống như một hack với tôi, nó phá vỡ ngữ nghĩa (xem cá nhân) và có thể gây nhầm lẫn cho mọi người (từ kinh nghiệm). – joakim

2

thử thêm này trong appdelegate applicationWillEnterForeground.

func applicationWillEnterForeground(_ application: UIApplication) {   
    // makes viewWillAppear run 
    self.window?.rootViewController?.beginAppearanceTransition(true, animated: false) 
    self.window?.rootViewController?.endAppearanceTransition() 
} 
0

Theo tài liệu của Apple:

(void)beginAppearanceTransition:(BOOL)isAppearing animated:(BOOL)animated; 

Mô tả:
Cho một bộ điều khiển con xuất hiện của nó là về để thay đổi. Nếu bạn đang triển khai bộ điều khiển vùng chứa tùy chỉnh, hãy sử dụng phương pháp này để cho trẻ biết rằng chế độ xem của nó sắp đến xuất hiện hoặc biến mất. Không gọi viewWillAppear:, viewWillDisappear:, viewDidAppear: hoặc viewDidDisappear: trực tiếp.

(void)endAppearanceTransition; 

Mô tả:

Cho một bộ điều khiển con xuất hiện của nó đã thay đổi. Nếu bạn đang triển khai bộ điều khiển vùng chứa tùy chỉnh, hãy sử dụng phương pháp này để cho trẻ biết rằng quá trình chuyển đổi chế độ xem đã hoàn tất.

Mẫu mã:

(void)applicationDidEnterBackground:(UIApplication *)application 
{ 

    [self.window.rootViewController beginAppearanceTransition: NO animated: NO]; // I commented this line 

    [self.window.rootViewController endAppearanceTransition]; // I commented this line 

} 

Câu hỏi: Làm thế nào tôi cố định?

Ans: Tôi đã tìm thấy dòng này trong ứng dụng. Dòng này làm cho ứng dụng của tôi không nhận được bất kỳ thông báo nào của ViewWillAppear. Khi tôi nhận xét những dòng này nó hoạt động tốt.

13

Swift 3.0 ++ phiên bản

Trong viewDidLoad của bạn, đăng ký tại trung tâm thông báo để nghe này mở từ hành động nền

NotificationCenter.default.addObserver(self, selector:#selector(doSomething), name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil) 

Sau đó, thêm chức năng này và thực hiện hành động cần thiết

func doSomething(){ 
    //... 
} 

Cuối cùng, thêm chức năng này để dọn dẹp người quan sát thông báo khi bộ điều khiển xem của bạn bị hủy.

deinit { 
    NotificationCenter.default.removeObserver(self) 
} 
+0

Giải pháp dễ dàng và thẳng tiến để xử lý thông báo bên trong VC +1 –

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