Xử lý ứng dụngDidBecomeActive - Hồi Làm thế nào một bộ điều khiển xem có thể phản hồi để ứng dụng trở thành Hoạt động?


179

Tôi có UIApplicationDelegategiao thức trong lớp AppDelegate.m chính của mình, với applicationDidBecomeActivephương thức được định nghĩa.

Tôi muốn gọi một phương thức khi ứng dụng trở về từ nền, nhưng phương thức này nằm trong một trình điều khiển khung nhìn khác. Làm cách nào tôi có thể kiểm tra trình điều khiển xem nào hiện đang hiển thị trong applicationDidBecomeActivephương thức và sau đó thực hiện cuộc gọi đến một phương thức trong bộ điều khiển đó?

Câu trả lời:


304

Bất kỳ lớp nào trong ứng dụng của bạn đều có thể trở thành "người quan sát" cho các thông báo khác nhau trong ứng dụng. Khi bạn tạo (hoặc tải) trình điều khiển chế độ xem của mình, bạn sẽ muốn đăng ký nó với tư cách là người quan sát cho UIApplicationDidBecomeActiveNotificationvà chỉ định phương thức bạn muốn gọi khi thông báo đó được gửi đến ứng dụng của bạn.

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(someMethod:)
                                             name:UIApplicationDidBecomeActiveNotification object:nil];

Đừng quên dọn dẹp sau khi chính mình! Hãy nhớ loại bỏ bản thân bạn với tư cách là người quan sát khi tầm nhìn của bạn biến mất:

[[NSNotificationCenter defaultCenter] removeObserver:self 
                                                name:UIApplicationDidBecomeActiveNotification
                                              object:nil];

Thông tin thêm về Trung tâm thông báo .


Thông minh. Không nghĩ đến việc sử dụng NSNotificationCenter. Cảm ơn bạn!
Calvin

3
Chỉ là một lỗi đánh máy trong dòng mã đó (thiếu 'tên'): [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector (someMethod :) name: UIApplicationDidBecomeActiveNotification object: nil];
Johnus

3
Để thêm vào câu trả lời của Reed, phương thức được gọi (trong ví dụ này là someMethod) cần chấp nhận tham số NSNotification. Vì vậy, chữ ký phương thức cho someMethod sẽ là - (void) someMethod: (NSNotification *) thông báo {// Làm gì đó ở đây}
Aaron

2
@Aaron Có thể, nhưng nó không phải là một yêu cầu. Đó là cái nhìn sâu sắc, mặc dù. Cảm ơn!
Sậy Olsen

Tuyệt diệu! Thật là một cách tuyệt vời để vô hiệu hóa / tạo lại các phiên bản NSTimer mà người ta đã thực hiện, ngay trong bộ điều khiển xem / các đối tượng khác chịu trách nhiệm cho các NSTimers đó. Yêu nó!
idstar

68

Swift 3, 4 tương đương:

thêm người quan sát

NotificationCenter.default.addObserver(self,
    selector: #selector(applicationDidBecomeActive),
    name: .UIApplicationDidBecomeActive, // UIApplication.didBecomeActiveNotification for swift 4.2+
    object: nil)

loại bỏ người quan sát

NotificationCenter.default.removeObserver(self,
    name: .UIApplicationDidBecomeActive, // UIApplication.didBecomeActiveNotification for swift 4.2+
    object: nil)

gọi lại

@objc func applicationDidBecomeActive() {
    // handle event
}

2
Tôi gọi nó ở đâu?

1
@ user8169082, bạn thêm một người quan sát bất cứ nơi nào bạn cần để bắt đầu nhận thông báo. Bạn có thể thêm nó vào viewDidLoadhoặc viewWillAppear:animatedví dụ. Và bạn có thể xóa người quan sát khi bạn không còn cần thông báo hoặc khi phiên bản người quan sát của bạn sẽ được giải quyết theo phương thức
deinit

2
nhanh chóng 4.2 Tôi đang sử dụng: NotificationCenter.default.addObserver (tự như công cụ chọn: #selector (applicationDidBecomeActive (thông báo :)), và tên: UIApplication.didBecomeActiveNotification, đối tượng: nil)
Brian

16

Swift 2 tương đương :

let notificationCenter = NSNotificationCenter.defaultCenter()

// Add observer:
notificationCenter.addObserver(self,
  selector:Selector("applicationWillResignActiveNotification"),
  name:UIApplicationWillResignActiveNotification,
  object:nil)

// Remove observer:
notificationCenter.removeObserver(self,
  name:UIApplicationWillResignActiveNotification,
  object:nil)

// Remove all observer for all notifications:
notificationCenter.removeObserver(self)

// Callback:
func applicationWillResignActiveNotification() {
  // Handle application will resign notification event.
}

Nơi tốt nhất để đặt removeObservertrong Swift: deinitphương thức.
Enrico Susatyo

Nói chung, không nên truy cập vào bản thân trong deinit; tại thời điểm này, bản thân ở giữa được phân bổ đầy đủ và được giải quyết
Zorayr

1
Bạn sẽ gỡ bỏ máy chủ ở đâu?
Enrico Susatyo

2
@EnricoSusatyo bạn có thể bỏ qua điều đó, vì nó không chính xác. Ghi đè deinit là tốt: "Bởi vì một cá thể không được giải quyết cho đến sau khi trình khử khử của nó được gọi, một trình khử khử có thể truy cập tất cả các thuộc tính của cá thể mà nó được gọi và có thể sửa đổi hành vi của nó dựa trên các thuộc tính đó (chẳng hạn như tìm kiếm tên của một tập tin cần phải được đóng lại. " Gọi deinit không ổn
Dan Rosenstark

7

Swift 4.2

Thêm người quan sát-

NotificationCenter.default.addObserver(self, selector: #selector(handleEvent), name: UIApplication.didBecomeActiveNotification, object: nil)

Xóa người quan sát-

NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)

Xử lý sự kiện-

@objc func handleEvent() {
}

5

Với Swift 4, Apple khuyên thông qua cảnh báo trình biên dịch mới rằng chúng tôi tránh sử dụng #selectortrong kịch bản này. Sau đây là một cách an toàn hơn nhiều để thực hiện điều này:

Đầu tiên, tạo một var lười biếng có thể được sử dụng bởi thông báo:

lazy var didBecomeActive: (Notification) -> Void = { [weak self] _ in
    // Do stuff
} 

Nếu bạn yêu cầu thông báo thực tế được bao gồm, chỉ cần thay thế _bằng notification.

Tiếp theo, chúng tôi thiết lập thông báo để quan sát thấy ứng dụng sẽ hoạt động.

func setupObserver() {
    _ = NotificationCenter.default.addObserver(forName: .UIApplicationDidBecomeActive,
                                               object: nil,
                                               queue:.main,
                                               using: didBecomeActive)
}

Thay đổi lớn ở đây là thay vì gọi a #selector, bây giờ chúng ta gọi var được tạo ở trên. Điều này có thể loại bỏ các tình huống mà bạn gặp sự cố bộ chọn không hợp lệ.

Cuối cùng, chúng tôi loại bỏ người quan sát.

func removeObserver() {
    NotificationCenter.default.removeObserver(self, name: .UIApplicationDidBecomeActive, object: nil)
}

1
#selectorcó thể gọi một phương thức được khai báo là một @objcthuộc tính trong Swift 4.
AnBisw

1
Nó không chính xác để sử dụng removeObserver(selfbản thân không được chỉ định khi thêm người quan sát. let observer = NotificationCenter.default.addObserverSau đó, bạn nênremoveObserver(observer
Yan Kalbaska

Cảm ơn @CodeBender tôi chưa biết chức năng đó và cuối cùng nó cũng xóa @objc. Tuy nhiên, khi tôi dùng thử, tôi nhận được cảnh báo trong bảng điều khiển (Xcode 11.3.1 (11C504), Swift 13.3): Không thể kết thúc BackgroundTask: không có tác vụ nền nào tồn tại với mã định danh. Ngay cả khi tôi lưu người quan sát trong một biến là NSObjectProtocol.
Palme

Nevermind Tôi cũng nhận được cảnh báo nếu tôi sử dụng @objcbiến thể.
Palme

3

Swift 5

fileprivate  func addObservers() {
      NotificationCenter.default.addObserver(self,
                                             selector: #selector(applicationDidBecomeActive),
                                             name: UIApplication.didBecomeActiveNotification,
                                             object: nil)
    }

fileprivate  func removeObservers() {
        NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
    }

@objc fileprivate func applicationDidBecomeActive() {
// here do your work
    }

0

Cách kết hợp:

import Combine

var cancellables = Set<AnyCancellable>()
NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)
    .sink { notification in
            // do stuff
    }.store(in: &cancellables)
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.