Can't change UIImageView image in function (SWIFT)
I think that the problem is the sleep(3), this line block the main thread.
Instead of that use:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
// your code here
}
Apple Reference
Note:
For the most part, use UIKit classes only from your app’s main thread. This is particularly true for classes derived from UIResponder or that involve manipulating your app’s user interface in any way.
Regards
Why can't I use an image variable to change the image inside of a UI Image
Im not sure if this is the best practice to do but I basically initialized the image I wanted to update and used else if statements to change the image.
import UIKit
class ViewController: UIViewController {
var tapCount : Int = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.addSubview(displayImage)
view.addSubview(displayText)
setupControls()
setupLayout()
}
// Initalized the display image to facebook icon and is updated when next or previous is tapped
private let displayImage: UIImageView = {
let imageName = "facebook_icon.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image)
imageView.frame = CGRect(x: 0, y: 0, width: 250, height: 250)
return imageView
}()
private let displayText: UITextView = {
let textView = UITextView()
let attributedText = NSMutableAttributedString(string: "Like us on Facebook", attributes: [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 18)])
attributedText.append(NSAttributedString(string: "\n\n\nLorem ipsum Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit.", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14), NSAttributedString.Key.foregroundColor: UIColor.gray]))
textView.attributedText = attributedText
textView.textAlignment = .center
textView.isEditable = false
textView.isScrollEnabled = false
textView.translatesAutoresizingMaskIntoConstraints = false
return textView
}()
private let nextButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("NEXT", for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 18)
button.addTarget(self, action: #selector(nextButtonTapped), for: .touchUpInside)
return button
}()
@objc func nextButtonTapped() {
tapCount += 1
pageCounter.currentPage += 1
updatePageContent()
print("NEXT \(tapCount)")
}
@objc func backButtonTapped() {
tapCount -= 1
pageCounter.currentPage -= 1
updatePageContent()
print("PREV \(tapCount)")
}
func updatePageContent() {
if tapCount == -1 {
tapCount = 0
} else if tapCount == 0 {
displayImage.image = facebookImage.image
} else if tapCount == 1 {
displayImage.image = twitterImage.image
} else if tapCount == 2 {
displayImage.image = instagramImage.image
} else if tapCount == 3 {
displayImage.image = linkedinImage.image
} else if tapCount == 4 {
displayImage.image = youtubeImage.image
} else if tapCount == 5 {
tapCount = 4
}
}
private let previousButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("PREV", for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 18)
button.addTarget(self, action: #selector(backButtonTapped), for: .touchUpInside)
return button
}()
private let pageCounter: UIPageControl = {
let control = UIPageControl()
control.currentPage = 0
control.numberOfPages = 5
control.currentPageIndicatorTintColor = .systemBlue
control.pageIndicatorTintColor = .gray
return control
}()
private let facebookImage: UIImageView = {
let imageName = "facebook_icon.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image)
return imageView
}()
private let twitterImage: UIImageView = {
let imageName = "twitter_icon.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image)
return imageView
}()
private let instagramImage: UIImageView = {
let imageName = "instagram_icon.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image)
return imageView
}()
private let linkedinImage: UIImageView = {
let imageName = "linkedin_icon.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image)
return imageView
}()
private let youtubeImage: UIImageView = {
let imageName = "youtube_icon.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image)
return imageView
}()
private let facebookText: UITextView = {
let textView = UITextView()
let attributedText = NSMutableAttributedString(string: "Like us on Facebook", attributes: [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 18)])
attributedText.append(NSAttributedString(string: "\n\n\nLorem ipsum Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit.", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14), NSAttributedString.Key.foregroundColor: UIColor.gray]))
textView.attributedText = attributedText
textView.textAlignment = .center
textView.isEditable = false
textView.isScrollEnabled = false
textView.translatesAutoresizingMaskIntoConstraints = false
return textView
}()
// Sets image and text properties
private func setupLayout() {
//Facebook icon constraints
displayImage.translatesAutoresizingMaskIntoConstraints = false
displayImage.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
displayImage.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
displayImage.widthAnchor.constraint(equalToConstant: 250).isActive = true
displayImage.heightAnchor.constraint(equalToConstant: 250).isActive = true
//Description contraints
displayText.topAnchor.constraint(equalTo: displayImage.bottomAnchor, constant: 120).isActive = true
displayText.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
displayText.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
displayText.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
}
// Sets control buttons and counter
private func setupControls() {
view.addSubview(nextButton)
view.addSubview(previousButton)
view.addSubview(pageCounter)
//Next button constraints
nextButton.translatesAutoresizingMaskIntoConstraints = false
nextButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
nextButton.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
nextButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
nextButton.widthAnchor.constraint(equalToConstant: 120).isActive = true
// Next button constraints
previousButton.translatesAutoresizingMaskIntoConstraints = false
previousButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
previousButton.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
previousButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
previousButton.widthAnchor.constraint(equalToConstant: 120).isActive = true
// Counter contsraints
pageCounter.translatesAutoresizingMaskIntoConstraints = false
pageCounter.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0).isActive = true
pageCounter.centerYAnchor.constraint(equalTo: nextButton.centerYAnchor, constant: 0).isActive = true
pageCounter.leadingAnchor.constraint(equalTo: previousButton.trailingAnchor, constant: 5).isActive = true
pageCounter.trailingAnchor.constraint(equalTo: nextButton.leadingAnchor, constant: 5).isActive = true
}
}
Issue with changing UIImageView Position
Try this:
var offset: CGPoint = CGPoint.zero
override func touchesBegan( . . . ){
offset = touch.location(in: imageView)
offset.x = (imageView.bounds.width / 2) - offset.x
offset.y = (imageView.bounds.height / 2) - offset.y
location = touch.location(in : self.view)
location.x = location.x + offset.x
location.y = location.y + offset.y
. . .
imageView.center = location
. . .
}
override func touchesMoved( . . . ){
location = touch.location(in : self.view)
location.x = location.x + offset.x
location.y = location.y + offset.y
. . .
imageView.center = location
. . .
}
Changing an Image in UIImageView at runtime
Once you have an image view, you don't need to create new ones (every time you hit your button).
You could declare these at the top of your class (with the imageView)
let ofImage = UIImage(named: "OF_farm.png")
let opaImage = UIImage(named: "OPA_farm.png")
and in your case statement just reassign either image to your imageView
switch farmSegment.selectedSegmentIndex {
case 1:
imageView.image = ofImage
// other things
break
default:
imageView.image = opaImage
// other things
}
In viewDidLoad, after adding the imageView to the scrollView you can add auto layout constraints if they are needed. Just be sure to set this first:
imageView.translatesAutoresizingMaskIntoConstraints = false
One last note: Don't forget to view your work in the simulator along the way using the 7+ and the SE settings (and others) to ensure that you have something that will work for everyone.
UIImageView within UITableViewCell not changing image
It appears that this is a bug on the iOS 15 simulator on M1 processors. The code functions perfectly on a real device but not on a simulator. I intend to file a radar for this.
imageView.image = UIImage(ciImage: ) won't update a second time
Quick searching ... seems to be either a "bug" or a change...
Changing your generator code to this seems to correct the issue:
func generateQRCode(from string: String) -> UIImage? {
let data = string.data(using: String.Encoding.ascii)
let context = CIContext()
if let filter = CIFilter(name: "CIQRCodeGenerator") {
filter.setValue(data, forKey: "inputMessage")
let transform = CGAffineTransform(scaleX: 3, y: 3)
if let output = filter.outputImage?.transformed(by: transform) {
if let retImg = context.createCGImage(output, from: output.extent) {
return UIImage(cgImage: retImg)
}
}
}
return nil
}
func generateBarcode(from string: String) -> UIImage? {
let data = string.data(using: String.Encoding.ascii)
let context = CIContext()
if let filter = CIFilter(name: "CICode128BarcodeGenerator") {
filter.setValue(data, forKey: "inputMessage")
let transform = CGAffineTransform(scaleX: 3, y: 3)
if let output = filter.outputImage?.transformed(by: transform) {
if let retImg = context.createCGImage(output, from: output.extent) {
return UIImage(cgImage: retImg)
}
}
}
return nil
}
ImageView won't update with new image
Try this, it worked for me:
DispatchQueue.main.async {
profilePictureImageView.image = croppedImage
profilePictureImageView.setNeedsDisplay()
}
Essentially you need to specify that you want to update the image via
profilePictureImageView.setNeedsDisplay()
Related Topics
Does _Arraytype or _Arrayprotocol Not Available in Swift 3.1
How to Use Querystartingatvalue in My Searchcontroller to Search for Users
What Does the Snapshot/Observer Code Do in Firebase
Swift Tuple Has Unexpected Print Result
Getting the Time Remaining in the Time Interval of a Timer in Swift
How to Change the Order of Functions Triggered
Cannot Read Property 'Keycode' 'Character' Assertion Failure When Detect Modifier Key + Numeric Key
Is There Any Particular Use of Closure in Swift? and What's the Benefit
Error: Argument Type Double/String etc. Does Not Conform to Expected Type "Anyobject"
Problem Creating and Writing a Subdirectory in Swift 5
How to Handle Async Requests in Swift
Self. in Trailing Swift Closures, Meaning and Purpose