Show multiple images in ViewController in Swift - swift

I have tried the following code to load multiple images in sequence in my ViewController.
import SwiftUI
class ViewController: UIViewController {
var ctrl = MainPageController()
override func viewDidLoad() {
super.viewDidLoad()
Thread.sleep(forTimeInterval: 4.0)
let width = UIScreen.main.bounds.size.width
let height = UIScreen.main.bounds.size.height
var backgroundImageView = UIImageView(frame: CGRect(x:0, y:0, width: width, height: height))
backgroundImageView.image = UIImage(named: "loading")
backgroundImageView.contentMode = .scaleAspectFill
self.view.addSubview(backgroundImageView)
Thread.sleep(forTimeInterval: 5.0)
backgroundImageView.removeFromSuperview()
Thread.sleep(forTimeInterval: 5.0)
backgroundImageView = UIImageView(frame: CGRect(x:0, y:0, width: width, height: height))
backgroundImageView.image = UIImage(named: "loading1")
backgroundImageView.contentMode = .scaleAspectFill
self.view.addSubview(backgroundImageView)
Thread.sleep(forTimeInterval: 5.0)
backgroundImageView.removeFromSuperview()
self.performSegue(withIdentifier: "MainViewSegue", sender: self)
But I see only the second image. I want to load the first image, show it for about 5 seconds, then replace it with the second image, display that for 5 seconds. I have removed the image from the Launch.storyboard. Currently I cannot see any image. The self.performSegue works. How do I fix this problem?
Thanks
Vyasa

It looks like you are creating new image views. If you goal is to simply change the image after 5 seconds you can simplify this code to be something more like:
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
imageView.image = UIImage(named: "Load 1")
imageView.contentMode = .scaleAspectFill
self.view.addSubview(imageView)
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
// the code in this block will only execute after 5 seconds
imageView.image = UIImage(named: "Load 2")
}

Related

Why UIImageView does not render image in UIView?

I am able to set system image as a button icon and add subviews under views but whatever I try, UIImageView never renders a system image. What am I doing wrong?
override func viewDidLoad() {
super.viewDidLoad()
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
imageView.image = UIImage(named: "pencil")
imageView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(imageView)
}
You should use UIImage(systemName: "pencil") initializer instead of UIImage(named: "pencil") in order to use images from SFSymbols. You can read more about it here.

Issue reusing the same UI Image code across multiple view controllers | Swift 5

I have the following function I use to customize the navigation bar across almost all the apps view controllers and table view controllers - instead of replicating the code numerous times I am looking for way to easily call the function on those view controllers needing it.
I have tried wrapping in extension UIViewController { } but run into a selector issue saying the following:
Argument of '#selector' cannot refer to local function
'Tapped(tapGestureRecognizer:)'
Code:
func navBar(){
// Profile Image
let containView = UIView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
imageView.image = UIImage(url: URL(string: "test.com"))
imageView.contentMode = UIView.ContentMode.scaleAspectFit
imageView.layer.cornerRadius = 20
imageView.layer.masksToBounds = true
containView.addSubview(imageView)
let rightBarButton = UIBarButtonItem(customView: containView)
self.navigationItem.rightBarButtonItem = rightBarButton
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:)))
imageView.isUserInteractionEnabled = true
imageView.addGestureRecognizer(tapGestureRecognizer)
}
#objc func imageTapped(tapGestureRecognizer: UITapGestureRecognizer) {
print("Profile Tapped")
}
How can this UIImage be seen in the navigation bar across various view controller without needing to rewrite the same code across all.
Lot a way to do it. I'll usually istance and personalize an UIViewController and use it around the whole app.
class baseController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//call your navBar here
navbar()
}
func navBar(){
// Profile Image
let containView = UIView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
imageView.image = UIImage(url: URL(string: "test.com"))
imageView.contentMode = UIView.ContentMode.scaleAspectFit
imageView.layer.cornerRadius = 20
imageView.layer.masksToBounds = true
containView.addSubview(imageView)
let rightBarButton = UIBarButtonItem(customView: containView)
self.navigationItem.rightBarButtonItem = rightBarButton
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:)))
imageView.isUserInteractionEnabled = true
imageView.addGestureRecognizer(tapGestureRecognizer)
}
}
Now instance this class whenever you want and your controller will get your navBar() every time with this
class mineController:baseController {
//your code here...
}

Change UIBarButton image from gallery

I have UIBarButton and user can change image just chose photo or gallery image with image picker. My problem is bad scale image.
If I use AspectFit my UIBarButton look like this:
If I use AspectFill my UIBarButton look like this:
and if I try first change size image and after set it, image all time scratched:
This is my code:
func createPhotoBarButton(image: Data) {
let barbtn = UIBarButtonItem()
var image = UIImage(data:image)
if image == nil {
image = UIImage(named: "photoIcon")
}
let imageView = UIImageView(frame: CGRect(x: 0.0, y: 0.0, width: 35.0, height: 35.0))
imageView.image = image?.resizedImage(newSize: CGSize(width: 35, height: 35))?.withRenderingMode(.alwaysOriginal)
// imageView.image = cropToBounds(image: image!, width: 35, height: 35)
// imageView.image = image
imageView.contentMode = .scaleAspectFill
imageView.layer.cornerRadius = imageView.frame.size.height / 2
imageView.layer.masksToBounds = true
imageView.clipsToBounds = true
self.navigationItem.rightBarButtonItem = barbtn
barbtn.customView = imageView
barbtn.customView?.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(photoTapped(_:))))
}
And here func for resize image:
func resizedImage(newSize: CGSize) -> UIImage? {
guard size != newSize else { return self }
let hasAlpha = false
let scale: CGFloat = 0.0
UIGraphicsBeginImageContextWithOptions(newSize, !hasAlpha, scale)
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
let newImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
Help me plz find the right way to resolving my problem.
As I understand your question. I found a solution.
Try this
func createPhotoBarButton(image: Data) {
let barbtn = UIBarButtonItem()
let imageView = UIImageView(frame: CGRect(x: 0.0, y: 0.0, width: 35.0, height: 35.0))
var image = UIImage(data:image)
if image == nil {
image = UIImage(named: "photoIcon")?.resize(maxWidthHeight: Double(imageView.frame.size.width))
}
imageView.image = image
imageView.contentMode = .scaleAspectFill
imageView.layer.cornerRadius = imageView.frame.size.height / 2
imageView.layer.masksToBounds = true
imageView.clipsToBounds = true
self.navigationItem.rightBarButtonItem = barbtn
barbtn.customView = imageView
barbtn.customView?.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(photoTapped(_:))))
}
Resize method
extension UIImage {
func resize(maxWidthHeight : Double)-> UIImage? {
let actualHeight = Double(size.height)
let actualWidth = Double(size.width)
var maxWidth = 0.0
var maxHeight = 0.0
if actualWidth > actualHeight {
maxWidth = maxWidthHeight
let per = (100.0 * maxWidthHeight / actualWidth)
maxHeight = (actualHeight * per) / 100.0
}else{
maxHeight = maxWidthHeight
let per = (100.0 * maxWidthHeight / actualHeight)
maxWidth = (actualWidth * per) / 100.0
}
let hasAlpha = true
let scale: CGFloat = 0.0
UIGraphicsBeginImageContextWithOptions(CGSize(width: maxWidth, height: maxHeight), !hasAlpha, scale)
self.draw(in: CGRect(origin: .zero, size: CGSize(width: maxWidth, height: maxHeight)))
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
return scaledImage
}
}
Output
Try to create a custom button with the code below:
func createPhotoBarButton(image: Data) {
let imageBtnContainer = UIButton()
let imageBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
var image = UIImage(data:image)
if image == nil {
image = UIImage(named: "photoIcon")
}
imageBtn.setImage(image, forState: UIControlState.Normal)
imageBtn.frame = CGRectMake(0, 0, 53, 31)
imageBtn.imageView?.contentMode = .scaleAspectFit
imageBtnContainer.addSubview(imageBtn)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: imageBtnContainer)
...
}
You don't need anymore resizedImage(..) function
Here is working code (swift 4)
override func viewDidLoad() {
let containView = UIView(frame: CGRect(x: 0, y: 0, width: 35, height: 35))
let Button : UIButton = UIButton.init(type: .custom)
Button.frame = CGRect(x: 0, y: 0, width: 35, height: 35)
Button.Round = true
Button.setImage(UIImage(named: "photoIcon"), for: .normal)
Button.addTarget(self, action: #selector(btnTapped), for: .touchUpInside)
containView.addSubview(Button)
let rightBarButton = UIBarButtonItem(customView: containView)
self.navigationItem.rightBarButtonItem = rightBarButton
}
Button Action Here
#objc func btnTapped(_ sender: Any) {
print("Click Event")
}
Extension to Round
extension UIView{
#IBInspectable var Round:Bool{
get{
return false
}
set{
if newValue == true {
self.layer.cornerRadius = self.frame.size.height/2;
self.layer.masksToBounds = true;
}
}
}
}
Output:

How center a Navigation Bar Image [Swift]

in my project I have a Navigation Bar with a Button to open a slide menu.
Now I am trying to set a title image instead of the title string. Unlikely the image is pushed slightly to the right instead of being centered. I thought its because of the slide menu button in the left corner of my navigation bar. If I set a title in main.storyboard everything look properly. Why is it so, that my image won't be centered.
Image function:
func addNavBarImage() {
let navController = navigationController!
let image = UIImage(named: "TransparentLogo")
let imageView = UIImageView(image: image)
let bannerWidth = navController.navigationBar.frame.size.width
let bannerHeight = navController.navigationBar.frame.size.height
let bannerX = bannerWidth - image!.size.width
let bannerY = bannerHeight - image!.size.height
imageView.frame = CGRect(x: bannerX, y: bannerY, width: bannerWidth, height: bannerHeight)
imageView.contentMode = .scaleAspectFit
navigationItem.titleView = imageView
}
Button function:
func addSlideMenuButton(){
let btnShowMenu = UIButton(type: UIButton.ButtonType.system)
btnShowMenu.setImage(self.defaultMenuImage(), for: UIControl.State())
btnShowMenu.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
btnShowMenu.addTarget(self, action: #selector(BaseViewController.onSlideMenuButtonPressed(_:)), for: UIControl.Event.touchUpInside)
btnShowMenu.tintColor = UIColor(red: 3, green: 49, blue: 79)
let customBarItem = UIBarButtonItem(customView: btnShowMenu)
self.navigationItem.leftBarButtonItem = customBarItem;
}
Change the frame of your titleView in func addNavBarImage() like this:-
func addNavBarImage() {
let navController = navigationController!
let image = UIImage(named: "TransparentLogo")
let imageView = UIImageView(image: image)
let bannerWidth = navController.navigationBar.frame.size.width
let bannerHeight = navController.navigationBar.frame.size.height
let bannerX = bannerWidth - image!.size.width
let bannerY = bannerHeight - image!.size.height
imageView.frame = CGRect(x: bannerX, y: bannerY, width: bannerWidth, height: bannerHeight)
imageView.contentMode = .scaleAspectFit
navigationItem.titleView = imageView
}
to this
func addNavBarImage() {
let imageView = UIImageView(image: #imageLiteral(resourceName: "TransparentLogo"))
imageView.frame = CGRect(x: 0, y: 0, width: 170, height: 30)
imageView.contentMode = .scaleAspectFit
let titleView = UIView(frame: CGRect(x: 0, y: 0, width: 170, height: 30))
titleView.addSubview(imageView)
titleView.backgroundColor = .clear
self.navigationItem.titleView = titleView
}
func centeredNavBarImageView() {
if let navcontroller = navigationController {
let image = #imageLiteral(resourceName: "logo")
let imageView = UIImageView(image: image)
let bannerWidth = navcontroller.navigationItem.accessibilityFrame.size.width
let bannerHeight = navcontroller.navigationBar.frame.size.height
let bannerX = bannerWidth / 2 - image.size.width / 2
let bannerY = bannerHeight / 2 - image.size.height / 2
imageView.frame = CGRect(x: bannerX, y: bannerY, width: bannerWidth, height: bannerHeight)
imageView.contentMode = .scaleAspectFit
self.navigationItem.titleView = imageView
}

How to make tappable UIImages that run functions?(Swift)

(I just started using Swift a few days ago and am relatively new to programming, so please bear with me.) I am trying to make random blocks appear on the screen, and the user must tap them to make them disappear. I have been able to create the blocks, but I have no idea how to actually make them tappable. Can someone please help me? This is my code so far:
func createBlock(){
let imageName = "block.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: xPosition, y: -50, width: size, height: size)
self.view.addSubview(imageView)
UIView.animateWithDuration(duration, delay: delay, options: options, animations: {
imageView.backgroundColor = UIColor.redColor()
imageView.frame = CGRect(x: self.xPosition, y: 590, width: self.size, height: self.size)
}, completion: { animationFinished in
imageView.removeFromSuperview()
self.life-=1
})
}
I want to make the block disappear when tapped; any suggestions on how I can do that?
It's extremely simple to do, just use a UITapGestureRecognizer. I typically initialize the recognizer as a global variable.
let tapRecognizer = UITapGestureRecognizer()
Then in your viewDidLoad:
// Replace with your function
tapRecognizer.addTarget(self, action: "removeBlock")
imageView.addGestureRecognizer(tapRecognizer)
func removeImage(gesture: UIGestureRecognizer) {
gesture.view?.removeFromSuperview()
}
func createBlock() {
let imageName = "block.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: xPosition, y: -50, width: size, height: size)
imageView.userInteractionEnabled = true // IMPORTANT
imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "removeImage:"))
self.view.addSubview(imageView)
UIView.animateWithDuration(duration, delay: delay, options: options, animations: {
imageView.backgroundColor = UIColor.redColor()
imageView.frame = CGRect(x: self.xPosition, y: 590, width: self.size, height: self.size)
}, { _ in
imageView.removeFromSuperview()
self.life-=1
})
}
Notice imageView.userInteractionEnabled = true it is really important because that will allow touch events on that view, it is set to false as defaul in UIImgageView.