How do stop repeating images in TableView Cell - ios

I created programmatically a ImageView in the cellForRowAt method and added also to the cell:
let imageName = "Default.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: 29, y: 17, width: 14, height: 13)
cell.addSubview(imageView)
It works, there is nothing to grumble. Now I want to show this image only if the indexpath.row equals 2, so I added a simple if-statement:
if indexPath.row == 2 {
let imageName = "Default.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: 29, y: 17, width: 14, height: 13)
cell.addSubview(imageView)
}
It works. But when I scroll down, some cells have the image too. I suspected there works something wrong in the cellForRowAt, so I added in the UITableViewCell the method prepareForReuse to hidden each imageView and only if the if-statement is true, the hide will be remove:
override func prepareForReuse() {
super.prepareForReuse()
self.imageView!.isHidden = true
}
if indexPath.row == 2 {
let imageName = "Default.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: 29, y: 17, width: 14, height: 13)
imageView.isHidden = false
cell.addSubview(imageView)
}
Unfortunately it doesn't work and I have no idea what I could improve.

prepareForReuse in your cell's subclass is referencing the subclass' property imageView and setting it to hidden. However, in your if statement, you are creating a new image view and adding it to the cell's hierarchy. This is a bad idea as it'll never be removed and more and more will be added as you scroll around.
Instead, reference the cell's image view:
if indexPath.row == 2 {
let imageName = "Default.png"
let image = UIImage(named: imageName)
cell.imageView?.image = image
cell.imageView?.isHidden = false
}

In cellForRowAt add the else part with the empty imageView to solve this issue.
if indexPath.row == 2 {
let imageName = "Default.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: 29, y: 17, width: 14, height: 13)
cell.addSubview(imageView)
} else { // ## Add this else methode.
let imageView = UIImageView()
imageView.frame = CGRect(x: 29, y: 17, width: 14, height: 13)
cell.addSubview(imageView)
}

Hi the problem with your code is when the cell is reused the imageView is still in the hierarchy, so in prepareForReuse remove the subviews that are of type image view simply also because the cell already had default imageview so create a new imageView class and remove of that specific type, Im adding code for it, Hope it helped :).
class CustomImageView : UIImageView { //CustomImageView
}
func removeCustomImageViewIfNeeded() {
self.subviews.forEach { (subView) in
if subView is CustomImageView {
subView.removeFromSuperview()
}
}
}
override func prepareForReuse() {
super.prepareForReuse()
removeCustomImageViewIfNeeded()
}
if indexPath.row == 2 {
let imageName = "Default.png"
let image = UIImage(named: imageName)
let imageView = CustomImageView(image: image!)
imageView.frame = CGRect(x: 29, y: 17, width: 14, height: 13)
imageView.isHidden = false
cell.addSubview(imageView)
}else {
removeCustomImageViewIfNeeded()
}

Related

Adding image in the Navigation Bar

I was wondering the best approach to put an image into the navigation bar.
My initial thought was to create a cocoa touch class for UINavigationController and set it up that way, but I can seem to get it to working using the below code:
class NavBarImage: UINavigationController {
override func awakeFromNib() {
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
self.setupView()
}
func setupView()
{
let navController = navigationController!
let image = #imageLiteral(resourceName: "BarTabsNavLogoWhite")
let imageView = UIImageView(image: image)
let bannerWidth = navController.navigationBar.frame.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
navigationItem.titleView = imageView
}
}
I keep getting an "unexpectedly found nil while unwrapping an optional value" on let navController = navigationController!.
However, this method has also been working for me too. I created a cocoa touch class for UINavigationBar and used this code below:
import UIKit
class NavBarImg: UINavigationBar {
override init(frame: CGRect) {
super.init(frame: frame)
initialise()
}
required init(coder aDecoder: NSCoder){
super.init(coder: aDecoder)!
initialise()
}
func initialise(){
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 225, height: 40))
imageView.contentMode = .scaleAspectFit
let image = UIImage(named:"BarTabsNavLogoWhite")
imageView.image = image
imageView.frame.origin = CGPoint(x: self.superview?.center.x, y: self.superview?.center.y)
addSubview(imageView)
}
}
The only problem with this is that on different iPhones I cant figure out how to get the image to always be centered on any device using CGPoint.
Then for the last method I found and implemented is done by the code below:
#IBDesignable class test: UINavigationBar { #IBInspectable var imageTitle: UIImage? = nil {
didSet {
guard let imageTitle = imageTitle else {
topItem?.titleView = nil
return
}
let imageView = UIImageView(image: imageTitle)
imageView.frame = CGRect(x: 0, y: 0, width: 40, height: 30)
imageView.contentMode = .scaleAspectFit
topItem?.titleView = imageView
}
}
}
I really like this method because with the IBDesignable function you can see it in the storyboard. However the way I have my viewcontrollers set up with tableviews, after i go past the first view controller, the navigation bar image disappears in all other view controllers when I run the simulator.
Looking for advice to see which method is the best approach and how to possibly solve the problems I am having. Or if anyone has a different method that they have found that works, id love to see how it works!
you can simply add a image or customize the barbutton as follows:
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "icon_right"), for: .normal)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
button.frame = CGRect(x: 0, y: 0, width: 53, height: 31)
button.imageEdgeInsets = UIEdgeInsetsMake(-1, 32, 1, -32)//move image to the right
let label = UILabel(frame: CGRect(x: 3, y: 5, width: 20, height: 20))
label.font = UIFont(name: "Arial-BoldMT", size: 16)
label.text = "title"
label.textAlignment = .center
label.textColor = .black
label.backgroundColor = .clear
button.addSubview(label)
let barButton = UIBarButtonItem(customView: button)
self.navigationItem.rightBarButtonItem = barButton

Setting content mode in UIImageView no longer works in iOS 11

I have this code in order to put an UIImageView in the center of a navigation controller bar and properly scale the image:
override func viewDidAppear(_ animated: Bool) {
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 150, height: 28));
imageView.contentMode = .scaleAspectFit;
let image = UIImage(named: "image_title.png");
imageView.image = image;
self.navigationItem.titleView = imageView;
}
The code works fine in iOS 10, however in iOS 11 the ".scaleAspectFit" property is not considered and the images is not scaled in the UIImageView size.
I tried with some solutions i found:
Setting the frame of the UIImageView after setting the "contentMode" property
Setting imageView.setNeedsLayout()
Setting imageView.setNeedsDisplay()
unfortunately, no one of these solutions works. The "contentMode" property is simply ignored,
Any idea on what the problem could be?
Thank you in advance
Works for me such way (using additional UIView)
let titleView = UIView(frame: CGRect(x: 0, y: 0, width: 120, height: 40))
let image = UIImageView(image: UIImage(named: "img-logo"))
image.contentMode = .scaleAspectFit
image.frame = titleView.bounds
titleView.addSubview(image)
viewController.navigationItem.titleView = titleView
let imageView = UIImageView(image: UIImage(named: "img-logo"))
imageView.contentMode = .scaleAspectFit
navigationItem.titleView = imageView

Custom navigation bar image and text

I need in my app a custom navigation bar with an image and a text but I can't add the text.
Here is the code to add the image, how can I add the title?
let logo = #imageLiteral(resourceName: "navigationbaricon")
let imageView = UIImageView(image:logo)
self.navigationItem.titleView = imageView
Thanks
Where is the frame assigned for self.navigationItem.titleView? Set the frame for imageView and it will work.
You can wrap the UIImageView and the UILabel (which will hold the custom title) in an UIView and then assign the UIView to the self.navigationItem.titleView. Something like this:
let view = UIView(...);
let label = UILabel(...);
label.text = "Custom Title";
let image = UIImageView(image: UIImage(named: "..."));
view.addSubview(image);
view.addSubview(label);
self.navigationItem.titleView = view;
This one is worked for me
override func viewDidLoad() {
super.viewDidLoad()
let titleView = UIView()
titleView.frame = CGRect(x: 0, y: 0, width: 100, height: 40)
titleView.backgroundColor = UIColor.redColor()
let imageView = UIImageView(image: UIImage(named: "img")!)
imageView.frame = CGRectMake(0, 0, 40, 40)
imageView.contentMode = .ScaleAspectFill
titleView.addSubview(imageView)
self.navigationItem.titleView = titleView
}

Unable to set image width in Swift

In my view controller, I added the following to be able to customize the NavigationBar, but when I got to setting the width and height of the logo, all I can change is the height.
When I edit the value in width - Nothing happens, even if I set it to 0.
Also, is it possible to use px instead of points?
override func viewDidAppear(animated: Bool) {
// 1
var nav = self.navigationController?.navigationBar
// 2
nav?.barStyle = UIBarStyle.Black
nav?.tintColor = UIColor.whiteColor()
// 3
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
// imageView.contentMode = .ScaleAspectFit
// 4
let image = UIImage(named: "trotterlogo.png")
imageView.image = image
// 5
navigationItem.titleView = imageView
}

How do you create a UIImage View Programmatically - Swift

I'm trying to create a UIImage View programmatically, I have a new view and I tried doing this
let imageName = "yourImage.png"
yourview.backgroundColor = UIColor.colorWithPatternImage(UIImage(named:imageName))
this did not work because I don't know what this should be yourview in the second line.
Question:
How do I make a UIImageView appear on the screen by coding it instead of doing it in the storyboard
First you create a UIImage from your image file, then create a UIImageView from that:
let imageName = "yourImage.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image!)
Finally you'll need to give imageView a frame and add it your view for it to be visible:
imageView.frame = CGRect(x: 0, y: 0, width: 100, height: 200)
view.addSubview(imageView)
First create UIImageView then add image in UIImageView .
var imageView : UIImageView
imageView = UIImageView(frame:CGRectMake(10, 50, 100, 300));
imageView.image = UIImage(named:"image.jpg")
self.view.addSubview(imageView)
This answer is update to Swift 3.
This is how you can add an image view programmatically where you can control the constraints.
Class ViewController: UIViewController {
let someImageView: UIImageView = {
let theImageView = UIImageView()
theImageView.image = UIImage(named: "yourImage.png")
theImageView.translatesAutoresizingMaskIntoConstraints = false //You need to call this property so the image is added to your view
return theImageView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(someImageView) //This add it the view controller without constraints
someImageViewConstraints() //This function is outside the viewDidLoad function that controls the constraints
}
// do not forget the `.isActive = true` after every constraint
func someImageViewConstraints() {
someImageView.widthAnchor.constraint(equalToConstant: 180).isActive = true
someImageView.heightAnchor.constraint(equalToConstant: 180).isActive = true
someImageView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
someImageView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 28).isActive = true
}
}
You can use above in one line.
let imageView = UIImageView(image: UIImage(named: "yourImage.png")!)
In Swift 3.0 :
var imageView : UIImageView
imageView = UIImageView(frame:CGRect(x:10, y:50, width:100, height:300));
imageView.image = UIImage(named:"Test.jpeg")
self.view.addSubview(imageView)
In Swift 4.2 and Xcode 10.1
//Create image view simply like this.
let imgView = UIImageView()
imgView.frame = CGRect(x: 200, y: 200, width: 200, height: 200)
imgView.image = UIImage(named: "yourimagename")//Assign image to ImageView
imgView.imgViewCorners()
view.addSubview(imgView)//Add image to our view
//Add image view properties like this(This is one of the way to add properties).
extension UIImageView {
//If you want only round corners
func imgViewCorners() {
layer.cornerRadius = 10
layer.borderWidth = 1.0
layer.masksToBounds = true
}
}
Thanks, MEnnabah, just to add to your code where you are missing the = sign in the declaration statement:
let someImageView: UIImageView = {
let theImageView = UIImageView()
theImageView.image = UIImage(named: "yourImage.png")
theImageView.translatesAutoresizingMaskIntoConstraints = false //You need to call this property so the image is added to your view
return theImageView
}()
Everything else is, all perfect for Swift 3.
Make sure to put:
imageView.translatesAutoresizingMaskIntoConstraints = false
Your image view will not show if you don't put that, don't ask me why.
Swift 4:
First create an outlet for your UIImageView
#IBOutlet var infoImage: UIImageView!
Then use the image property in UIImageView
infoImage.image = UIImage(named: "icons8-info-white")

Resources