Set UIImageView as background - Swift 4 - swift

I want to set a background image behind everything that already exists in the view.
I tried :
override func viewDidLoad() {
super.viewDidLoad()
let backgroundImage = UIImageView(frame: UIScreen.main.bounds)
backgroundImage.image = UIImage(named: "bg-img")
backgroundImage.contentMode = UIViewContentMode.scaleAspectFill
self.view.insertSubview(backgroundImage, at: 0)
}
But it didn't work (it didn't even add the img). So I imported the ImageView component and added the image using the Xcode GUI and it did add the image but is on top of everything. I have tried several Stack Overflow answers (that's where I get the above code from), but I didn't have any luck.
My folder structure looks like this:
My image is inside the Assets.xcassets folder.
UPDATE:
I restarted Xcode and my code worked.

Setting the subviews' frames in viewDidLoad is not a good practice because subviews aren't yet correctly placed at that point. You should set the frames of subviews in viewDidLayoutSubviews, which is called after the self.view and it's subviews are correctly laid out.
Your ViewController:
var backgroundImage: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
self.backgroundImage = UIImageView(image: UIImage(named: "bg-img"))
self.backgroundImage.contentMode = .scaleAspectFill
self.view.insertSubview(self.backgroundImage, at: 0)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.backgroundImage.frame = self.view.bounds
}

All you have to do is give the full name of the jpg image:
backgroundImage.image = UIImage(named: "bg-img.jpg")
If it were placed in Assets.xcassets, or a png file, then specifying the extension would have been optional.
Sometimes all you need is to Clean your Build Folder ⇧⌘K, or just restart Xcode.

Related

Adding UIImage to new Scroll View

I'm trying to create a simple app in Xcode that lets me press a button and it adds an image to a view. I originally had everything working until I decided to add a scroll view, as I wanted to create multiple buttons. My problem is, the created image follows down when scrolling. Im sure this is an easy fix. My code looks like this for each button:
#IBAction func btnAddColorfulLights1(_ sender: Any) {
let image: UIImage = UIImage(named: "ColorfulLights.png")!
let imageView = UIImageView(image: image)
self.view.addSubview(imageView)
imageView.tag = 10
imageView.frame = CGRect(x: 67, y: 39, width: 240, height: 338)
}
I think my problem is in,
self.view.addSubview(imageView)
Where I'm adding the image to view, where I need to be adding it to the scroll view.
This is my control viewer organization/set up:
Here's what it should look like:
Here's the problem:
I know this is probably very easy but I can't seem to find any answers to my specific problem or anything that can help me. Thank you so much!
You need to add the UIImageView containing the image of your lights to the UIView that is the contentView of the UIScrollView.
An easy way to do this is to create an #IBOutlet for the UIView in your scrollView. control-drag from the View under the ScrollView in the Document Outline to your ViewController code. Give the #IBOutlet a name such as:
#IBOutlet weak var scrollViewsView: UIView!
Then, use it to add your adornments:
#IBAction func btnAddColorfulLights1(_ sender: Any) {
let image = UIImage(named: "ColorfulLights.png")!
let imageView = UIImageView(image: image)
self.scrollViewsView.addSubview(imageView)
imageView.tag = 10
imageView.frame = CGRect(x: 67, y: 39, width: 240, height: 338)
}

Changes in Xcode 9 not reflecting in mainStoryboard, however, same changes are reflecting in simulator

I am trying to set the dimensions of an image by writing code, but when I try to run the code it works and shows the changes in the simulator but not in MainStoryboard. Why might this be happening?
Import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let imageView = UIImageView(frame: CGRect(x: 100, y: 500, width: 258, height: 64)); // set as you want
let image = UIImage(named: "signInLogo.png");
imageView.image = image;
self.view.addSubview(imageView);
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Storyboard is NOT a live view of what is running in your application. Storyboard is only going to display the views that are within it. If you are creating views (your UIImageView) pro grammatically within your ViewController, they won't show up in your Storyboard because they never touch it.

app crash on iphone not on simulator

Whenever I tap on the last row in the column, the app crashes on the iPhone, but not on the simulator. Everything else works fine. I do not get any error message. The code is working perfectly fine along with the simulator.
import UIKit
class EarthVC: UIViewController {
#IBOutlet var slideShow1: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
slideShow1.animationImages = [
UIImage(named: "Earth1.jpg")!,
UIImage(named: "Earth2.jpg")!,
UIImage(named: "Earth3.jpg")!,
UIImage(named: "Earth4.jpg")!,
UIImage(named: "Earth5.jpg")!,
UIImage(named: "Earth6.jpg")!,
UIImage(named: "Earth7.jpg")!,
UIImage(named: "Earth8.jpg")!,
UIImage(named: "Earth9.jpg")!,
UIImage(named: "Earth10.jpg")!,
UIImage(named: "Earth11.jpg")!,
UIImage(named: "Earth12.jpg")!,
UIImage(named: "Earth13.jpg")!,
UIImage(named: "Earth14.jpg")!,
UIImage(named: "Earth15.jpg")!,
UIImage(named: "Earth16.jpg")!,
UIImage(named: "Earth17.jpg")!,
UIImage(named: "Earth18.jpg")!,
UIImage(named: "Earth19.jpg")!,
UIImage(named: "Earth20.jpg")!,
UIImage(named: "Earth21.jpg")!,
UIImage(named: "Earth22.jpg")!,
UIImage(named: "Earth23.jpg")!,
UIImage(named: "Earth24.jpg")!,
UIImage(named: "Earth25.jpg")!,
UIImage(named: "Earth26.jpg")!,
UIImage(named: "Earth27.jpg")!,
UIImage(named: "Earth28.jpg")!,
UIImage(named: "Earth29.jpg")!,
UIImage(named: "Earth30.jpg")!,
UIImage(named: "Earth31.jpg")!
]
slideShow1.animationDuration = 93
slideShow1.startAnimating()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
With all of the images you are loading, it's likely you are running out of memory on the phone - I had this problem recently. No error, but sometimes I did see "low memory warning" on the debug console.
To diagnose it, make an array of the image names, loop over that to populate an array of UIImage's, but check that they load as you go. Then you can set that as the animationImages. So,
let imageNames = [
"Earth1.jpg",
"Earth2.jpg",
// ...
"Earth31.jpg"
]
var images = [UIImage]()
for name in imageNames
{
guard let image = UIImage(named: name) else {
NSLog("Failed to load image \(name)")
continue
}
images.append(image)
}
slideShow1.animationImages = images
You can set a breakpoint at the continue to see how far you are getting.
Assuming that is what's going on, to fix the problem, you will need to use an image editing program make the images smaller (in terms of pixels). In my case, my images were photographs taken at 4000x6000 pixels; I found that resizing them to be the size they would actually be displayed made a difference. Also, saving the files with 50% loss made them about 15% of the original size (in terms of bytes), which made them load a lot faster. I showed the original and resized/lossy images to colleagues, they couldn't see a difference (one thought it was a joke of some kind).
I had a similar problem with an App I made with a large number of images (100). Their existence also slowed the app down somewhat. When I reduced the file size of each image - without affecting image Quality. It worked!! Easily done in 'Preview' on Apple.
Solution:
Open the images in mac OSX with 'Preview'
Goto menu at top... 'Tools'...'Adjust Size'
Reduce the pixel size of the image + Save
Put the newly saved images back into Xcode for your App
Reducing the file sizes by 40% without seeing any reduction in image quality on App worked!

Assigning "aspect fill" option for background image of uibutton Swift

We can set the image of the button to be of aspect fill by :
imageView?.contentMode = UIViewContentMode.ScaleAspectFill
but since I am dealing with the background image, I'm not sure how to access contentMode for the background image.
I know that instead of doing so, I can create a custom class where the image can be centered with the button text centered on top, then set the imageview as aspect fill with the above code, but that seems like a lot more work to achieve the same result.
What's the best way to accomplish this?
It's been a long time since question asked but anyone who wonder,If you set your button image using setImage() it will show the image with its width and height no matter you scale, but If you set using setBackgroundImage() It will be just fine,didn't even need to scale
For whoever stumbles across this:
The UIImageView that contains backgroundImage is not publicly accessible. See https://developer.apple.com/documentation/uikit/uibutton, there is no such property. I do not why Apple protected that.
First solution
However you can filter your UIButton for all the UIImageViews and set their property to .scaleAspectFit:
override func layoutSubviews() {
super.layoutSubviews()
button
.subviews
.filter { $0 is UIImageView }
.forEach { $0.contentMode = .scaleAspectFit }
}
Second solution
The first solution could possibly conflict with any other UIImageViews you have in your UIButton. So you could also filter only for the exact background image:
override func layoutSubviews() {
super.layoutSubviews()
let backgroundImage = UIImage(named: "backspace-button")
let backgroundImageView = button
.subviews
.filter { $0 is UIImageView }
.first(where: { ($0 as? UIImageView)?.image == backgroundImage}) as? UIImageView
backgroundImageView?.contentMode = .scaleAspectFit
}
I would not recommend to access the backgroundImageView by its array index. There is no guarantee that this order will be like that forever.

How to apply Swift constraints on imageView on rotation in code?

The following elegant code derived from the new text by Vandad Nahavandipoor on Swift works fine in landscape however since the scrollView is constructed by code one cannot use usual constraints to properly display the chart named CrossTalk.png in landscape. In fact in landscape the chart initially displays in 50% of the screen and when dragged to the right in an attempt to fill the screen the initiating viewController-1 that segued into the current, displaying viewController-2 takes over the entire landscape view. Is there a way to fix this problem in code?
SWIFT latest version 6.1
import UIKit
class ChartViewController: UIViewController, UIScrollViewDelegate,UIGestureRecognizerDelegate {
var imageView: UIImageView?
var scrollView: UIScrollView?
let image = UIImage(named: "CrossTalk.png")
override func viewDidLoad() {
super.viewDidLoad()
imageView = UIImageView(image: image)
scrollView = UIScrollView(frame: view.bounds)
if let theScrollView = scrollView{
theScrollView.addSubview(imageView!)
theScrollView.contentSize = imageView!.bounds.size
view.addSubview(theScrollView)
}
}