Prevent image overlay in image view swift - swift

I have a tableViewCell with image view.
Even though I clear the imageView and set the image I get the below unintended behaviour, where one image is overlaid over the other.
Please advice how this could be resolved.
Code on Resetting Image in ImageView:
self.profileImageLabelTVCell.cellImageView.image = nil // Clearing previous image
self.profileImageLabelTVCell.cellImageView.image = image
Here is the link for the tableViewCell code and roundedImageView class, that I've used. (Since SO did not allow the entire code to be posted here)
https://gist.github.com/pravishanth/14cdb8bf14dd8899b081bdc97988b985

Add your reset image code to the TableViewCell's
func prepareForReuse() method.
override func prepareForReuse() {
super.prepareForReuse()
cellImageView.image = nil
}

Related

Playground, unable to set same UIImageView to more than one UIView

I've got this code
override public func viewDidLoad() {
let imageBlankCard = UIImage(named: "BlankCard.png")
let imageViewBlankCard = UIImageView(image: imageBlankCard)
rockCard.addSubview(imageViewBlankCard)
scissorCard.addSubview(imageViewBlankCard)
paperCard.addSubview(imageViewBlankCard)
self.view.addSubview(rockCard)
self.view.addSubview(scissorCard)
self.view.addSubview(paperCard)
}
But when I run the playground, only the latest UIView (paperCard) is displayed properly, the other cards are not shown at all as you can see in the image here: there should be two cards like the last one, in place of the arrows.
Can someone help me? Thanks everybody!
According to the documentation,
Views can have only one superview. If view already has a superview and that view is not the receiver, this method removes the previous superview before making the receiver its new superview.
This explains the behaviour that you're getting.
One solution to this is to create three separate image views and add each of them as a subview.
Judging by the variable names, I think you are creating something similar to a rock paper scissors game. And you have three views that each holds an image view with the image of a blank card. And you want to add the image of a stone, paper and scissors as an overlay to the image view. If that's what you want to do, why not just make rockCard, paperCard and scissorsCard themselves UIImageViews and set the image to be BalnkCard.png?
let imageBlankCard = UIImage(named: "BlankCard.png")
rockCard.image = imageBlankCard
scissorsCard.image = imageBlankCard
paperCard.image = imageBlankCard

Swift - instance of backgroundColor not working

If I set up an image in the Image/Image View of the Attributes Inspector the following subsequent call does not work:
picture.backgroundColor = UIColor.greenColor()
If I setup the image in the code, such as in viewDidAppear, it does.
Am I missing something, is this a quirk and how do I get it to behave?
It does work. But you can't see it in some cases.
For example: in the following image I have change the background color and set it to aspect fit. The gap between the two appears in green. So the image must have some transparency to it in order to see the background color.
Image with white background
Image with transparent background
Edit:
This is how I changed the background color
#IBOutlet weak var picture: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
picture.backgroundColor = UIColor.greenColor()
}

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.

Swift - Cropping images *outside* of allowsEditing

I have a very very simple project set up that allows you to click a "browse photo" button. The user then selects a photo from their photo gallery, and it's displayed on a programmatically created UIImageView.
Works like a charm. However - I am missing key functionality that is required.
I need the user to be able to scale the image (via pinching and dragging) after it is displayed within the UIImageView. allowsEditing = true, lets the user crop before. I need similar functionality, however, allowing them to edit once it's on the main UI.
Help is appreciated. Please and thank you!!
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
var imageViewLayer: CALayer{
return imageView.layer
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
imageViewLayer.contents = UIImage(named: "ss3.jpg")?.CGImage
imageViewLayer.contentsGravity = kCAGravityResizeAspect
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func newGesture(sender: AnyObject) {
imageViewLayer.transform = CATransform3DMakeScale(sender.scale, sender.scale, 1)
}
}
I did something similar a while back. I added the image to UIImageView's layer property, added gesture recognizer to the view and implemented the gesture call backs modifying the layer property and not the view. Adding the image to the UIImageView's layer did the trick. As a side note, I would like to add that every UIView is supported by CALayer class. It has a lot of methods and properties which help to dynamically change the view, which in your case will be done by gestures.
As an alternative, you can also use CALayer's hitTest method instead of implementing the call backs for gesture recognizers.
EDIT- Sample Code
You could do some thing like this:
#IBOutlet weak var imageView: UIImageView!
var imageViewLayer: CALayer{
return imageView.layer
}
In the viewDidLoad, set up the image
imageViewLayer.contents = UIImage(named: "CoreDataDemoApp")?.CGImage
imageViewLayer.contentsGravity = kCAGravityResizeAspect
Add pinch gesture to the imageview in storyboard (or programmatically) and in it's call back you could do something like this:
#IBAction func pinchGestureRecognized(sender: AnyObject) {
imageViewLayer.transform = CATransform3DMakeScale(sender.scale, sender.scale, 1)
}
Again this is just to give you an idea of how it could work and it is not the complete code. Hope this helps!
This is another way of doing it:
Stackoverflow link to related question

viewDidLayoutSubviews is called when label changes (xcode) (swift)

I have a label, toggle button and an animation in my code. When I press the toggle button -> animation starts , label changes. Below is my code sample.
override func viewDidLayoutSubviews() {
println("viewDidLayoutSubviews is called")
// Initial state of my animation.
}
#IBAction func Toggled(sender: AnyObject) {
CallTextChange()
// Two different Animations
}
func CallTextChange() { // Change text here}
Every time I change the text in label viewDidLayoutSubviews is called.
Is there a way to stop calling it every time I change the label?
I found the answer for my problem.
When we create UIImage by drag and dropping from the object provided by Xcode, the image is temporary placed where it was statically placed. So when animating in middle when viewDidLayoutSubviews is called the image is placed in the static place.
So the UIImage has to be created programmatically.
CreateImage.image = UIImage(named: "Image.png")
CreateImage = UIImageView(frame: CGRect(x: 0, y: 0, width: CreateImage.image!.size.width/6, height: CreateImage.image!.size.height/6))
self.view.addSubview(CreateImage)
Try to pass one boolean flag values in function
I think when you change text of and UILabel it will change its intrinsic content size that in turn will notify the system to relayout the view hierarchy. So it seems inevitable that viewDidLayoutSubviews will be called.
Either you put a boolean flag to make your initial animation code execute once only or move your code to other place like viewDidLoad() method.