Reputation: 11201
I'm trying to add a cover screen to app when app is pushed to background by user.
I have these two methods on AppDelegate to add/remove the cover view.
func showCover(){
let blackV = UIView(frame: UIApplication.shared.keyWindow?.bounds ?? .zero)
blackV.backgroundColor = .black
blackV.tag = kCoverTag
let imgV = UIImageView(image: UIImage(named: "Logo-White"))
imgV.center = blackV.center
blackV.addSubview(imgV)
UIApplication.shared.keyWindow?.addSubview(blackV)
}
func hideCover(){
if let blackV = UIApplication.shared.keyWindow?.subviews.filter({$0.tag == kCoverTag}).first{
blackV.removeFromSuperview()
}
}
The tag value is declared on AppDelegate:
let kCoverTag = 987
In the applicationWillResignActive
, I apply the cover
func applicationWillResignActive(_ application: UIApplication) {
showCover()
}
and in didBecomeActive, I remove the cover.
func applicationDidBecomeActive(_ application: UIApplication) {
hideCover()
}
This works fine when app is sent to background by pressing home button.
Right after the applicationDidBecomeActive
is called, when I print the subviews of keyWindow , I get the output as:
po UIApplication.shared.keyWindow?.subviews
▿ Optional<Array<UIView>>
▿ some : 2 elements
- 0 : <UITransitionView: 0x7f97bd82ffc0; frame = (0 0; 414 896); autoresize = W+H; layer = <CALayer: 0x6000028ecce0>>
- 1 : <UIView: 0x7f97bae27f20; frame = (0 0; 414 896); tag = 987; layer = <CALayer: 0x600002868400>>
This is good as it shows the cover view as one of the subview added to the key window.
Now, when the app is sent to background by calling UIApplication.shared.openURL
, the applicationWillResignActive is called as expected.
And when the user press the "Back to app button" , the app will be shown back to user.
Now,when I print the subviews of key window in the didBecomeActive
method right before calling hideCover()
method, it looks like it has only one subview.
po UIApplication.shared.keyWindow?.subviews
▿ Optional<Array<UIView>>
▿ some : 1 element
- 0 : <UITransitionView: 0x7f97bfc05510; frame = (0 0; 414 896); autoresize = W+H; layer = <CALayer: 0x6000029984c0>>
Since this shows only one view, the hideCover()
method couldn't find the subview and hence couldn't remove it. But in the app I could see the cover view .
I'm wondering why the keyWindow
subviews didn't show the added cover view.
I'm testing this in simulator.
Update:
I did two separate print calls
Right after adding the cover view:
print("resign active",UIApplication.shared.keyWindow?.subviews)
This show two subviews for keyWindow
and right before removing the cover view in didBecomeActive method:
print("did become active",UIApplication.shared.keyWindow?.subviews)
This show only ONE subview for keyWindow
Upvotes: 4
Views: 3472
Reputation: 7
I use this to cover my app
var secureView: UIView?
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
secureView = UIView()
secureView?.backgroundColor = UIColor.white
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
public func applicationDidBecomeActive(_ application: UIApplication) {
self.secureView?.removeFromSuperview()
}
public func applicationWillResignActive(_ application: UIApplication) {
if let window = UIApplication.shared.windows.first, let view = secureView {
view.frame = window.bounds
window.addSubview(view)
}
}
for someone want to add story board:
override
func applicationWillResignActive(_ application: UIApplication) {
showSplashScreen()
}
override
func applicationDidBecomeActive(_ application: UIApplication) {
removeSplashScreen()
}
func showSplashScreen() {
let launchScreen = UIStoryboard(name: "LaunchScreen", bundle: nil).instantiateInitialViewController()
guard let launchScreen = launchScreen,
let launchView = launchScreen.view else {
return
}
launchView.tag = 8888
launchView.frame = window.bounds
self.window?.addSubview(launchView)
self.window?.makeKeyAndVisible()
}
func removeSplashScreen() {
guard let window = UIApplication.shared.windows.last,
let view = window.viewWithTag(8888) else {
return
}
view.removeFromSuperview()
}
Upvotes: 1
Reputation: 299335
Don't use keyWindow
here. That's not the right tool. There can be other windows created by the system and may have input focus via makeKey()
. Present the view from the window.rootViewController
from your UIApplicationDelegate
. See QA1838: Preventing Sensitive Information From Appearing In The Task Switcher for Apple's recommended way to implement what you're trying to do. Also see Preparing Your UI to Run in the Background for additional guidance.
Upvotes: 6