Swift - keep the same background when switching between views [duplicate] - ios

I want to be able to add a background image to my ios app that applies for all views and not having to add this image to every single view. Is it possible to add an image to UIWindow or something?
Now, when I do a transition, the background of the new view also "transitions" over my previous view even though its the same background. I want to be able to only se the content transition, and not the background, which is the same.

You should be able to achieve this by:
subclassing UIWindow and overriding drawRect to draw your image; details about subclassing UIWindow here
and then by using UIAppearance to control the background colour for the rest of the views in your app (you should set it to clearColor); details about this here, though I think you'll need to subclass the views used by your controllers in order to cope with the note in the accepted answer
A basic implementation could look like this:
class WallpaperWindow: UIWindow {
var wallpaper: UIImage? = UIImage(named: "wallpaper") {
didSet {
// refresh if the image changed
setNeedsDisplay()
}
}
init() {
super.init(frame: UIScreen.mainScreen().bounds)
//clear the background color of all table views, so we can see the background
UITableView.appearance().backgroundColor = UIColor.clearColor()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func drawRect(rect: CGRect) {
// draw the wallper if set, otherwise default behaviour
if let wallpaper = wallpaper {
wallpaper.drawInRect(self.bounds);
} else {
super.drawRect(rect)
}
}
}
And in AppDelegate:
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow? = WallpaperWindow()

Related

UIVisualEffectView stack overflow accessing contentView

I'm developing an iOS app (the original code is not mine). The code below works fine in iOS 9/10 but on iOS 11 it enters an infinite loop of calling
addSubview.
import UIKit
class BlurView: UIVisualEffectView {
var isRounded: Bool
init(style: UIBlurEffectStyle, isRounded: Bool = true) {
self.isRounded = isRounded
super.init(effect: UIBlurEffect(style: style))
setupInterface()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func addSubview(_ view: UIView) {
guard view !== contentView else {
super.addSubview(view)
return
}
contentView.addSubview(view)
}
}
If I substitute the effect parameter in the line super.init(effect: UIBlurEffect(style: style)) for nil it works fine (of course, without the blur).
Additional information: inside the addSubView I can't access the contentView property, which seems to be the one that creates the stack overflow problem. On the init it looks like it's internally used, and that's where it breaks.
The questions are:
Why does this work on iOS 9/10 and not iOS 11?
How can I make this work on iOS 11?

How can I add the same background image to all views in my ios app using swift?

I want to be able to add a background image to my ios app that applies for all views and not having to add this image to every single view. Is it possible to add an image to UIWindow or something?
Now, when I do a transition, the background of the new view also "transitions" over my previous view even though its the same background. I want to be able to only se the content transition, and not the background, which is the same.
You should be able to achieve this by:
subclassing UIWindow and overriding drawRect to draw your image; details about subclassing UIWindow here
and then by using UIAppearance to control the background colour for the rest of the views in your app (you should set it to clearColor); details about this here, though I think you'll need to subclass the views used by your controllers in order to cope with the note in the accepted answer
A basic implementation could look like this:
class WallpaperWindow: UIWindow {
var wallpaper: UIImage? = UIImage(named: "wallpaper") {
didSet {
// refresh if the image changed
setNeedsDisplay()
}
}
init() {
super.init(frame: UIScreen.mainScreen().bounds)
//clear the background color of all table views, so we can see the background
UITableView.appearance().backgroundColor = UIColor.clearColor()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func drawRect(rect: CGRect) {
// draw the wallper if set, otherwise default behaviour
if let wallpaper = wallpaper {
wallpaper.drawInRect(self.bounds);
} else {
super.drawRect(rect)
}
}
}
And in AppDelegate:
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow? = WallpaperWindow()

How to let user customize LaunchScreen [duplicate]

Xcode allows to create launch screen in .xib files via Interface Builder. Is it possible to execute some code with the xib, just like in usual view controllers? It would be great if we can set different text/images/etc while app launching.
No, it's not possible.
When launch screen is being displayed your app will be in loading state.
Even the - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions will not be completely executed while the launch screen is displayed.
So it's clear that, you don't have any access to your app and so at this point you can't execute any code.
I was trying to do the same thing here. :)
I really liked some of the apps, in which they do a little dynamic greeting text and image each time the app is launched, such as "You look good today!", "Today is Friday, a wonderful day", etc, which is very cute.
I did some search, below is how to do it:
(My code is XCode 7, with a launchscreen.xib file)
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var customizedLaunchScreenView: UIView?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
application.statusBarHidden = true
// customized launch screen
if let window = self.window {
self.customizedLaunchScreenView = UIView(frame: window.bounds)
self.customizedLaunchScreenView?.backgroundColor = UIColor.greenColor()
self.window?.makeKeyAndVisible()
self.window?.addSubview(self.customizedLaunchScreenView!)
self.window?.bringSubviewToFront(self.customizedLaunchScreenView!)
UIView.animateWithDuration(1, delay: 2, options: .CurveEaseOut,
animations: { () -> Void in
self.customizedLaunchScreenView?.alpha = 0 },
completion: { _ in
self.customizedLaunchScreenView?.removeFromSuperview() })
}
return true
}
// other stuff ...
}
Just do what ever you wanted to show, text, images, animations, etc. inside the customizedLaunchScreenView here.
At the end of the launching, just fade out this customized UIView using alpha value change, then remove it completely.
How cool is that? I absolutely love it!
Hope it helps.
I was also trying to achieve this. I tried the following, it gives a delay of couple of seconds but works for me.
Create and set a launch screen in project settings.
Create a view controller with custom class (SplashViewController) and set it your starting view controller in storyboard.
Add a container view in it and set it to full screen.
Set embedded segue to a Storyboard Reference.
Select Storyboard Reference and set launch screen in StoryBoard property from Attribute inspector.
Do whatever you want in SplashViewController (play animation or session check etc) and perform segue when done.
Hope it helps!
Language: Swift 4
Hello, here's a solution for using xib for launch screen.
Adding new class named LaunchView to your project, then u'll have a new file LaunchView.swift in project.
Go to LauchImage.xib to set class to LaunchView (which it's your new class).
Adding some code, & reading some information show at the LaunchView.swift. Here's is my code for displaying version of app at launch screen.
class LaunchView: UIView {
lazy var versionLabel: UILabel = {
let label = Factory.label(style: LabelStyle.custom(font: .regular, size: 10, color: .other(ColorUtility.versionGray)), mutiLine: false, textAlignment: .center)
label.text = "ver \(Constants.appVersion)"
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
nibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
nibSetup()
}
private func nibSetup() {
addSubview(versionLabel)
versionLabel.snp.makeConstraints { (make) in
make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom).offset(-6)
make.centerX.equalToSuperview()
}
}
}

swift iPad Table View not Transparent

In swift, I have a UI Table View and I have the background set as clear for a transparent background, and for the iPhone it works perfectly. But for iPad, it does not, it has a white background, not clear. I saw an answer, but it wasn't for swift, but that didn't work either.
My code for the iPhone is:
tableview.backgroundcolor = UIColor.clearcolor()
I tried adding:
tableview.background = nil
But that doesn't work.
I ran into the same problem. It seems that somewhere in the process of adding a UITableView to the window (between willMoveToWindow and didMoveToWindow), some iPad's reset the backgroundColor of the table view to white. It does this covertly without using the backgroundColor property.
I now use this as a base class in place of UITableView when I need a colored/transparent table...
class ColorableTableView : UITableView {
var _backgroundColor:UIColor?
override var backgroundColor:UIColor? {
didSet {
_backgroundColor = backgroundColor
}
}
override func didMoveToWindow() {
backgroundColor = _backgroundColor
super.didMoveToWindow()
}
}
EDIT: Cells also have their backgroundColor's set to white on my iPad in the same way (i.e. those that are in the table during the move to the window), so the same applies to them, lest you end up with the odd opaque cell popping up from time to time as it is reused ...
class ColorableTableViewCell : UITableViewCell {
var _backgroundColor:UIColor?
override var backgroundColor:UIColor? {
didSet {
_backgroundColor = backgroundColor
}
}
override func didMoveToWindow() {
backgroundColor = _backgroundColor
super.didMoveToWindow()
}
}
Where are you inserting that code? I had a similar problem recently with a tableview that I had subclassed. Setting the background color to clear worked perfectly well in the subclass for iPhone but on iPad it was still displaying as white.
My solution was that I had to also put it in the viewWillAppear function on the specific tableViewController that contained the table.
// myTableViewController
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
myTableView.backgroundColor = UIColor .clearColor()
}

Execute code in Launch Screen

Xcode allows to create launch screen in .xib files via Interface Builder. Is it possible to execute some code with the xib, just like in usual view controllers? It would be great if we can set different text/images/etc while app launching.
No, it's not possible.
When launch screen is being displayed your app will be in loading state.
Even the - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions will not be completely executed while the launch screen is displayed.
So it's clear that, you don't have any access to your app and so at this point you can't execute any code.
I was trying to do the same thing here. :)
I really liked some of the apps, in which they do a little dynamic greeting text and image each time the app is launched, such as "You look good today!", "Today is Friday, a wonderful day", etc, which is very cute.
I did some search, below is how to do it:
(My code is XCode 7, with a launchscreen.xib file)
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var customizedLaunchScreenView: UIView?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
application.statusBarHidden = true
// customized launch screen
if let window = self.window {
self.customizedLaunchScreenView = UIView(frame: window.bounds)
self.customizedLaunchScreenView?.backgroundColor = UIColor.greenColor()
self.window?.makeKeyAndVisible()
self.window?.addSubview(self.customizedLaunchScreenView!)
self.window?.bringSubviewToFront(self.customizedLaunchScreenView!)
UIView.animateWithDuration(1, delay: 2, options: .CurveEaseOut,
animations: { () -> Void in
self.customizedLaunchScreenView?.alpha = 0 },
completion: { _ in
self.customizedLaunchScreenView?.removeFromSuperview() })
}
return true
}
// other stuff ...
}
Just do what ever you wanted to show, text, images, animations, etc. inside the customizedLaunchScreenView here.
At the end of the launching, just fade out this customized UIView using alpha value change, then remove it completely.
How cool is that? I absolutely love it!
Hope it helps.
I was also trying to achieve this. I tried the following, it gives a delay of couple of seconds but works for me.
Create and set a launch screen in project settings.
Create a view controller with custom class (SplashViewController) and set it your starting view controller in storyboard.
Add a container view in it and set it to full screen.
Set embedded segue to a Storyboard Reference.
Select Storyboard Reference and set launch screen in StoryBoard property from Attribute inspector.
Do whatever you want in SplashViewController (play animation or session check etc) and perform segue when done.
Hope it helps!
Language: Swift 4
Hello, here's a solution for using xib for launch screen.
Adding new class named LaunchView to your project, then u'll have a new file LaunchView.swift in project.
Go to LauchImage.xib to set class to LaunchView (which it's your new class).
Adding some code, & reading some information show at the LaunchView.swift. Here's is my code for displaying version of app at launch screen.
class LaunchView: UIView {
lazy var versionLabel: UILabel = {
let label = Factory.label(style: LabelStyle.custom(font: .regular, size: 10, color: .other(ColorUtility.versionGray)), mutiLine: false, textAlignment: .center)
label.text = "ver \(Constants.appVersion)"
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
nibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
nibSetup()
}
private func nibSetup() {
addSubview(versionLabel)
versionLabel.snp.makeConstraints { (make) in
make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom).offset(-6)
make.centerX.equalToSuperview()
}
}
}

Resources