Menangani applicationDidBecomeActive - "Bagaimana pengontrol tampilan dapat merespons aplikasi menjadi Aktif?"

179

Saya memiliki UIApplicationDelegateprotokol di kelas AppDelegate.m utama saya, dengan applicationDidBecomeActivemetode yang ditentukan.

Saya ingin memanggil metode ketika aplikasi kembali dari latar belakang, tetapi metode ini di controller tampilan lain. Bagaimana saya bisa memeriksa controller tampilan mana yang saat ini ditampilkan dalam applicationDidBecomeActivemetode dan kemudian membuat panggilan ke metode dalam controller itu?

Calvin
sumber

Jawaban:

304

Kelas apa pun dalam aplikasi Anda dapat menjadi "pengamat" untuk berbagai notifikasi dalam aplikasi. Saat Anda membuat (atau memuat) pengontrol tampilan Anda, Anda ingin mendaftarkannya sebagai pengamat untuk UIApplicationDidBecomeActiveNotificationdan menentukan metode mana yang ingin Anda panggil saat pemberitahuan itu dikirimkan ke aplikasi Anda.

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

Jangan lupa membersihkan dirimu sendiri! Ingatlah untuk menghapus diri Anda sebagai pengamat ketika pandangan Anda hilang:

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

Informasi lebih lanjut tentang Pusat Pemberitahuan .

Reed Olsen
sumber
Luar biasa. Tidak terpikir untuk menggunakan NSNotificationCenter. Terima kasih!
Calvin
3
Hanya salah ketik pada baris kode tersebut (hilang 'nama'): [[NSNotificationCenter defaultCenter] addObserver: selektor diri: @selektor (someMethod :) nama: UIApplicationDidBecomeActiveNotification objek: nil];
Johnus
3
Untuk menambahkan jawaban Reed, metode yang dipanggil (dalam contoh ini adalah metode tertentu) harus menerima parameter NSNotification. Jadi tanda tangan metode untuk someMethod adalah - (batal) someMethod: (NSNotification *) notification {// Do Something Here}
Aaron
2
@ Harun Itu bisa, tapi itu bukan keharusan. Tapi itu wawasan yang bagus. Terima kasih!
Reed Olsen
Fantastis! Betapa cara yang bagus untuk membatalkan / membuat ulang instance NSTimer yang telah digunakan seseorang, tepat di view controllers / objek lain yang bertanggung jawab untuk NSTimer tersebut. Suka!
idStar
68

Swift 3, 4 Setara:

menambahkan pengamat

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

menghapus pengamat

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

panggilan balik

@objc func applicationDidBecomeActive() {
    // handle event
}
igrek
sumber
2
dimana saya menyebutnya?
1
@ user8169082, Anda menambahkan pengamat di mana pun Anda harus mulai menerima notifikasi. Anda bisa menambahkannya viewDidLoadatau viewWillAppear:animatedmisalnya. Dan Anda dapat menghapus pengamat saat Anda tidak lagi membutuhkan pemberitahuan, atau ketika pengamat Anda akan dibatalkan alokasi dalam metode
deinit
2
swift 4.2 Saya menggunakan: NotificationCenter.default.addObserver (diri, pemilih: #selector (applicationDidBecomeActive (notifikasi :)), nama: UIApplication.didBecomeActiveNotification, objek: nil)
Brian
16

Swift 2 Setara :

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.
}
Zorayr
sumber
Tempat terbaik untuk memasukkan metode removeObserverSwift:. deinit
Enrico Susatyo
Secara umum, mengakses diri sendiri tidak disarankan; pada titik ini, diri berada di antara sedang dialokasikan penuh dan sedang dialokasikan
Zorayr
1
Di mana Anda akan menghapus Server?
Enrico Susatyo
2
@EnricoSusatyo Anda dapat mengabaikan itu, karena itu tidak benar. Mengesampingkan deinit baik-baik saja: "Karena sebuah instance tidak dapat dialokasikan kembali sampai setelah deinitializer dipanggil, deinitializer dapat mengakses semua properti dari instance yang dipanggil dan dapat memodifikasi perilakunya berdasarkan pada properti tersebut (seperti mencari nama suatu file yang perlu ditutup). " Menelepon deinit tidak apa
Dan Rosenstark
7

Cepat 4.2

Tambahkan pengamat-

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

Hapus pengamat-

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

Menangani Event-

@objc func handleEvent() {
}
Abhishek Jain
sumber
5

Dengan Swift 4, Apple menyarankan melalui peringatan kompiler baru yang kami hindari penggunaannya #selectordalam skenario ini. Berikut ini adalah cara yang jauh lebih aman untuk mencapai ini:

Pertama, buat lazy var yang bisa digunakan dengan notifikasi:

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

Jika Anda mengharuskan pemberitahuan aktual dimasukkan, ganti saja _dengan notification.

Selanjutnya, kami mengatur pemberitahuan untuk mengamati agar aplikasi menjadi aktif.

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

Perubahan besar di sini adalah bahwa alih-alih memanggil #selector, kita sekarang memanggil var yang dibuat di atas. Ini dapat menghilangkan situasi di mana Anda mendapatkan crash pemilih yang tidak valid.

Akhirnya, kami menghapus pengamat.

func removeObserver() {
    NotificationCenter.default.removeObserver(self, name: .UIApplicationDidBecomeActive, object: nil)
}
CodeBender
sumber
1
#selectordapat memanggil metode yang dinyatakan sebagai @objcatribut dalam Swift 4.
AnBisw
1
itu salah untuk digunakan removeObserver(selfkarena diri tidak ditugaskan ketika menambahkan pengamat. Anda harus let observer = NotificationCenter.default.addObserverkemudianremoveObserver(observer
Yan Kalbaska
Terima kasih @ CodeBender saya belum tahu fungsi itu dan itu (akhirnya) menghapus @objc. Namun ketika saya mencobanya saya mendapatkan peringatan di konsol (Xcode 11.3.1 (11C504), Swift 13.3): Tidak dapat mengakhiri BackgroundTask: tidak ada tugas latar belakang yang ada dengan pengidentifikasi. Bahkan jika saya menyimpan pengamat dalam variabel sebagai NSObjectProtocol.
Palme
Nevermind saya juga mendapatkan peringatan jika saya menggunakan @objcvarian.
Palme
3

Cepat 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
    }
Gurjinder Singh
sumber
0

Cara kombinasikan:

import Combine

var cancellables = Set<AnyCancellable>()
NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)
    .sink { notification in
            // do stuff
    }.store(in: &cancellables)
ollie
sumber