У мене є контролер перегляду, який використовує NSTimer
для виконання якогось коду.
Який найкращий спосіб визначити, коли програма переходить у фоновий режим, щоб я міг призупинити таймер?
Відповіді:
Ви можете зацікавити будь-який клас, коли програма переходить у фоновий режим, отримувати сповіщення. Це хороша альтернатива поєднанню цих класів з AppDelegate.
При ініціалізації зазначених класів:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillTerminate:) name:UIApplicationWillTerminateNotification object:nil];
Відповідаючи на повідомлення
-(void)appWillResignActive:(NSNotification*)note
{
}
-(void)appWillTerminate:(NSNotification*)note
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillTerminateNotification object:nil];
}
У Swift 4.0
override func viewDidLoad() {
super.viewDidLoad()
let app = UIApplication.shared
//Register for the applicationWillResignActive anywhere in your app.
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.applicationWillResignActive(notification:)), name: NSNotification.Name.UIApplicationWillResignActive, object: app)
}
@objc func applicationWillResignActive(notification: NSNotification) {
}
Для тих, хто хоче зробити це в Swift:
На init
:
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(applicationWillResignActive), name: UIApplicationWillResignActiveNotification, object: nil)
На deinit
:
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIApplicationWillResignActiveNotification, object: nil)
Відповідаючи на повідомлення:
dynamic private func applicationWillResignActive() {
// Do things here
}
Apple заохочує нас уникати динамічної диспетчеризації та селекторів Objective-C, коли це можливо в Swift, але це все ще найзручніший спосіб зробити це.
У швидкій версії 4.1:
Я використовую версію закриття:
var observer: NSObjectProtocol!
// inside init or viewDidLoad:
observer = NotificationCenter.default.addObserver(forName: .UIApplicationWillResignActive, object: nil, queue: nil) { _ in
print("willResignActive")
}
deinit {
NotificationCenter.default.removeObserver(observer)
}
addObserver
Метод повертає непрозорий об'єкт , який повинен бути видалений в певний момент.
лише допоміжна примітка: Якщо ви реєструєте контролер A, щоб отримувати сповіщення про перехід у фоновий режим, будьте обережні, що він буде викликаний, навіть якщо ви (наприклад ..) натискаєте другий контролер B, і ви відображаєте B: Якщо ця поведінка неправильна , краще зареєструватися / скасувати реєстрацію в
didAppear / WillDisappear.
- (void)applicationWillResignActive:(UIApplication *)application
на делегаті вашого додатка. Ви також можете зареєструватися для отримання UIApplicationWillResignActiveNotification
сповіщення про інші об'єкти.
Однак вам не обов'язково робити паузу таймера. Якщо ви нічого не зробите, програма все одно перейде в режим сну і не виконуватиме жодного коду. Імовірно, ваш таймер спрацює, коли ви знову станете активним (якщо ви це зробите). Якщо вам потрібно зробити щось особливе, існують методи делегування та сповіщення "дійсно стали активними", на які ви також можете зареєструватися.
Свіфт 4:
init() {
NotificationCenter.default.addObserver(self,
selector: #selector(applicationWillResignActive),
name: NSNotification.Name.UIApplicationWillResignActive,
object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self,
name: NSNotification.Name.UIApplicationWillResignActive,
object: nil)
}
@objc private func applicationWillResignActive() {
self.header.blur.effect = nil
}
Це краще рішення із застосуванням закриття
Заявити спостерігачеві
var backgroundObserver: NSObjectProtocol?
Ініціалізуйте спостерігача в viewDidLoad
backgroundObserver = NotificationCenter.default.addObserver(forName: UIApplication.willResignActiveNotification, object: nil, queue: .main) { [weak self] notification in
// Do what you want to do when app would go to background/ resign active
}
Не забудьте видалити спостерігача з деінциту
deinit {
if let observer = backgroundObserver {
NotificationCenter.default.removeObserver(observer)
}
}
@selector
, тобто замінивши@selector(appWillResignActive)
на@selector(appWillResignActive:)
(і те саме для@selector(appWillTerminate:)
).