navigation bar button item is bigger than the frame i set - ios

I don't know what's wrong with my code or what did I did that leads to this I spent half an hour trying to figure out what's wrong with my code but I have no idea, I'm calling this func in viewDidLoad()
func setupNavBarBtn(){
let backBtn = UIButton(type: .system)
backBtn.setImage(#imageLiteral(resourceName: "cellarrow").withRenderingMode(.alwaysOriginal), for: .normal)
backBtn.contentMode = .scaleAspectFit
backBtn.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
let callBtn = UIButton(type: .system)
callBtn.setImage(#imageLiteral(resourceName: "Call").withRenderingMode(.alwaysOriginal), for: .normal)
callBtn.contentMode = .scaleAspectFit
callBtn.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
self.navigationItem.leftBarButtonItems = [UIBarButtonItem(customView: backBtn), UIBarButtonItem(customView: callBtn)]
}

You should create UIBarButtonItem instead of UIButton:
let backBtn = UIBarButtonItem(image:UIImage(named: "cellarrow.png"), style: .plain, target: nil, action: nil)
let callBtn = UIBarButtonItem(image:UIImage(named: "Call.png"), style: .plain, target: nil, action: nil)
self.navigationItem.leftBarButtonItems = [backBtn,callBtn]
The size of bar button should better be 20x20

Related

How to customize navigation back button in swift?

I want to change the back button icon and the label and the color of the back button label on the navigation bar. I have written the following code but it's not working. if anybody knows the solution please help me out.
override func viewDidLoad() {
super.viewDidLoad()
let yourBackImage = UIImage(named: "back_arrow")
self.navigationController?.navigationBar.backIndicatorImage = yourBackImage
self.navigationController?.navigationBar.tintColor = .white
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = yourBackImage
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "Find or Invite", style: UIBarButtonItem.Style.plain, target: nil, action: nil)
}
Expected out put
Looks like you have manually added navigationBar without an embedded navigation controller.
For this just connect the outlet like this
#IBOutlet weak var navigationBar: UINavigationBar!
and remove the navigation controller part from your code as follows
let yourBackImage = UIImage(named: "back_arrow")
self.navigationBar.backIndicatorImage = yourBackImage
self.navigationBar.tintColor = .white
self.navigationBar.backIndicatorTransitionMaskImage = yourBackImage
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "Find or Invite", style: UIBarButtonItem.Style.plain, target: nil, action: nil)
Try this:
in viewDidLoad declare your button, image and title
let button = UIButton(type: .custom)
//Set the image
button.setImage(UIImage(systemName: "chevron.backward"), for: .normal)
//Set the title
button.setTitle("Yourtitle", for: .normal)
//Add target
button.addTarget(self, action: #selector(callMethod), for: .touchUpInside)
button.frame = CGRect(x: 0, y: 0, width: 100, height: 30)
button.sizeToFit()
now set spacing between image and title:
let spacing:CGFloat = 10.0; // the amount of spacing to appear between image and title
button.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: spacing)
button.titleEdgeInsets = UIEdgeInsets(top: 0, left: spacing, bottom: 0, right: 0)
after that create your bar button and add to your nav bar:
let barButton = UIBarButtonItem(customView: button)
navigationItem.leftBarButtonItem = barButton
this is the result:
Bonus:
if you want to set navigation bar correctly and in one line, take a look to my extension here https://stackoverflow.com/a/58361273/5575955
I have add both back button and title in Navigation bar button item. I have made dynamic function for using both.
this code for back button, it will return UIBarButtonItem item.
func getBackButton(selector: Selector, target: Any) -> UIBarButtonItem {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "img_back_white"), for: .normal)
button.setImage(UIImage(named: "img_back_white"), for: .highlighted)
button.setImage(UIImage(named: "img_back_white"), for: .selected)
button.imageView?.contentMode = .scaleAspectFit
button.imageEdgeInsets = UIEdgeInsets(top: 0, left: -15, bottom: 0, right: 0)
button.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
//button.imageEdgeInsets = UIEdgeInsets(top: 0.0, left: 0, bottom: 0, right: 0)
button.backgroundColor = .clear
button.addTarget(target, action: selector, for: .touchUpInside)
return UIBarButtonItem(customView: button)
}
Now for add title beside back button
func getNavigationTitleButton(title: String, font: UIFont = UIFont.SFProDisplayRegular(size: 19)) -> UIBarButtonItem {
let navTitle = UILabel()
navTitle.text = title
navTitle.textColor = .AppWhite
navTitle.isEnabled = true
navTitle.font = font
//navTitle.backgroundColor = .red
//navTitle.frame.origin.x = -40
//navTitle.sizeToFit()
return UIBarButtonItem(customView: navTitle)
}
You can customize according your need. I want to add one more method if you want to show both in some screen directly so use this method with title and selector parameter.
func addBackWithTitle(title: String, selector: Selector) {
self.navigationItem.leftBarButtonItems = [self.getBackButton(selector: selector, target: self), self.getNavigationTitleButton(title: title)]
}

First leftBarButtonItem is hiding

I used 2 bar button items. One is for back button and second is for the title. It is working fine. But when the title string is large, the title shifts to left and back button does not appear, but it is working.
I am also using a rightBarButtonItem, that is attached with a badge button. But that is not affecting this as I have tried the same code after removing that button. This is my code -
let backBtnImg: UIImage = UIImage(named: "Back Image")!
let Back: UIBarButtonItem = UIBarButtonItem(image: backBtnImg, style: .plain, target: self, action: #selector(backButtonAction))
let titleStr = ("titleString")
let titleItem: UIBarButtonItem = UIBarButtonItem(title: titleStr, style: .plain, target: nil, action: nil)
self.navigationItem.leftBarButtonItems = [Back, titleItem]
I have attached both the images.
Please try this code if you want to set the title in left side. It may helps to you.
In viewDidLoad method
let navView = UIView(frame: CGRect(x: 0, y: 0, width: (self.navigationController?.navigationBar.frame.size.width)! - 50, height: 40))
lblTitle = UILabel(frame: CGRect(x: 0, y: 0, width: navView.frame.size.width - 40, height: 40))
lblTitle?.text = strTitle
lblTitle?.backgroundColor = UIColor.clear
lblTitle?.textColor = UIColor.white
lblTitle?.textAlignment = .left
navView.addSubview(lblTitle!)
self.navigationItem.titleView = navView
Use this One It help you
-> take only one left button
-> For Title use: self.navigationItem.title = "Navigation Title"
let backBtnImg: UIImage = UIImage(named: "back")!
let Back: UIBarButtonItem = UIBarButtonItem(image: backBtnImg, style: .plain, target: self, action: #selector(backButtonAction))
self.navigationItem.title = "Navigation Title"
self.navigationItem.leftBarButtonItems = [Back]
func setupNevigationBar(){
let btnBack = UIButton(type: .custom)
btnBack.setImage(#imageLiteral(resourceName: "back"), for: .normal)
btnBack.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
btnBack.addTarget(self, action: #selector(btnBackPressed), for: .touchUpInside)
let itemBack = UIBarButtonItem(customView: btnBack)
let titleStr = ("Regular Title")
let titleItem: UIBarButtonItem = UIBarButtonItem(title: titleStr, style: .plain, target: nil, action: nil)
self.navigationItem.leftBarButtonItems = [itemBack, titleItem]
self.navigationItem.setLeftBarButton(itemBack, animated: true)
}

RightBarButtonItem is not displayed in the correct location

I am creating a UINavigationController programmatically and add my ViewController to it:
// wrap in a navigation controller
let navigationController = UINavigationController(rootViewController: myViewController)
self.present(navigationController, animated: true, completion: nil)
And then add an image to navigation item:
let backButton: UIBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: target, action: selector)
backButton.image = UIImage(named: "ic_back")
self.navigationItem.rightBarButtonItem = backButton
But my BarButton is not displayed in the correct location. What am I doing wrong?
You need to init UIBarButton directly to UIImage or Custom View:
i.e.,
Swift 3.0:
let image = UIImage(named: "ic_back")?.withRenderingMode(.alwaysOriginal)
let button = UIBarButtonItem(image: image, style: .plain, target: target, action: selector)
self.navigationItem.rightBarButtonItem = button
This will fix your issue.
alloc and init UIButton with desired frame! set image to that button. Set content mode if required! add target on this button to handle click! then alloc and init UIBarButtonItem using initWithCustomView method and pass UIButton as parameter that you have created.
Then set navigationItem's rightBarbuttonItem to this barbutton!
let btn1 = UIButton(type: .custom)
btn1.setImage(UIImage(named: "imagename"), for: .normal)
btn1.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
btn1.addTarget(self, action: #selector(Class.Methodname), for: .touchUpInside)
let item1 = UIBarButtonItem(customView: btn1)
self.navigationItem.setRightBarButtonItems(item1, animated: true)
You can set the button on navigation bar like this..
let Button = UIButton(frame: CGRect(x: 0, y: 0, width: 35, height: 40))
Button.setBackgroundImage(UIImage(named: "btn.png"), for: .normal)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: Button)
So this code is helps you to achieve your query
Add frame to your backButton using the following code and let us know if it worked.
backButton.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
You may change width and height acc. to your need.

navigation bar right bar button items spacing

I have created a
with left bar button item added from storyboard, titleView and three right bar button items from code.
Here is the code:
override func viewDidLoad() {
super.viewDidLoad()
var screenWidth = UIScreen.mainScreen().bounds.width
// custom title view
var navBarWidth: CGFloat = self.navigationController!.navigationBar.frame.size.width
let customTitleView = UIView(frame: CGRectMake(0, 0, navBarWidth, 44))
titleLabel = UILabel(frame: CGRectMake(20, 0, navBarWidth, 40))
titleLabel.text = conversationName
if let titleFont = UIFont(name: "Roboto-Regular", size: 20) {
titleLabel.font = titleFont
}
titleLabel.textColor = UIColor.whiteColor()
customTitleView.addSubview(titleLabel)
self.navigationItem.titleView = customTitleView
// right bar buttons
var searchImage = UIImage(named: "search")!
var clipImage = UIImage(named: "clip")!
var pencilImage = UIImage(named: "pencil")!
var searchBtn = UIBarButtonItem(image: searchImage, style: UIBarButtonItemStyle.Plain, target: self, action: Selector("searchBtnPressed"))
searchBtn.tintColor = UIColor.whiteColor()
var clipBtn = UIBarButtonItem(image: clipImage, style: UIBarButtonItemStyle.Plain, target: self, action: Selector("clipBtnPressed"))
clipBtn.tintColor = UIColor.whiteColor()
var pencilBtn = UIBarButtonItem(image: pencilImage, style: UIBarButtonItemStyle.Plain, target: self, action: Selector("pencilBtnPressed"))
pencilBtn.tintColor = UIColor.whiteColor()
self.navigationItem.setRightBarButtonItems([pencilBtn, clipBtn, searchBtn], animated: false)
}
My problem is that I want to change the spacing between right buttons but I don't know how.
I've tried to add a fixedButton between them but it just increased the existing space.
Can some one help me? Thanks.
I solved my problem in this way:
var searchImage = UIImage(named: "search-selected")!
var clipImage = UIImage(named: "clip")!
var pencilImage = UIImage(named: "pencil")!
let searchBtn: UIButton = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
searchBtn.setImage(searchImage, forState: UIControlState.Normal)
searchBtn.addTarget(self, action: "searchBtnPressed", forControlEvents: UIControlEvents.TouchUpInside)
searchBtn.frame = CGRectMake(0, 0, 30, 30)
let searchBarBtn = UIBarButtonItem(customView: searchBtn)
let clipBtn: UIButton = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
clipBtn.setImage(clipImage, forState: UIControlState.Normal)
clipBtn.addTarget(self, action: "clipBtnPressed", forControlEvents: UIControlEvents.TouchUpInside)
clipBtn.frame = CGRectMake(0, 0, 30, 30)
let clipBarBtn = UIBarButtonItem(customView: clipBtn)
let pencilBtn: UIButton = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
pencilBtn.setImage(pencilImage, forState: UIControlState.Normal)
pencilBtn.addTarget(self, action: "pencilBtnPressed", forControlEvents: UIControlEvents.TouchUpInside)
pencilBtn.frame = CGRectMake(0, 0, 30, 30)
let pencilBarBtn = UIBarButtonItem(customView: pencilBtn)
self.navigationItem.setRightBarButtonItems([pencilBarBtn, clipBarBtn, searchBarBtn], animated: false)
Now it looks good,
Update for Swift 4.1
let testButton : UIButton = UIButton.init(type: .custom)
testButton.setImage(editImage, for: .normal)
testButton.addTarget(self, action: #selector(didTapCameraButton), for: .touchUpInside)
testButton.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
let addButton = UIBarButtonItem(customView: testButton)
Set testButton.frame doesn't help.
This solution is correct for me!
rightButton.imageEdgeInsets = UIEdgeInsets(top: 3, left: 10, bottom: 7, right: 0)
For Swift 3:
let searchBtn: UIButton = UIButton(type: UIButtonType.custom)
searchBtn.setImage(UIImage(named: "search"), for: [])
searchBtn.addTarget(self, action: #selector(ViewController.searchBtnPressed(_:)), for: UIControlEvents.touchUpInside)
searchBtn.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
let searchButton = UIBarButtonItem(customView: searchBtn)
let clipBtn: UIButton = UIButton(type: UIButtonType.custom)
clipBtn.setImage(UIImage(named: "clip"), for: [])
clipBtn.addTarget(self, action: #selector(ViewController.clipBtnPressed(_:)), for: UIControlEvents.touchUpInside)
clipBtn.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
let clipButton = UIBarButtonItem(customView: clipBtn)
let pencilBtn: UIButton = UIButton(type: UIButtonType.custom)
pencilBtn.setImage(UIImage(named: "pencil"), for: [])
pencilBtn.addTarget(self, action: #selector(ViewController.pencilBtnPressed(_:)), for: UIControlEvents.touchUpInside)
pencilBtn.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
let pencilButton = UIBarButtonItem(customView: pencilBtn)
self.navigationItem.rightBarButtonItems = [pencilButton, clipButton, searchButton]
Replace ViewController with your view controller
// create three nav bar buttons
var searchBtn = UIBarButtonItem(image: searchImage, style: UIBarButtonItemStyle.Plain, target: self, action: Selector("searchBtnPressed"))
searchBtn.tintColor = UIColor.whiteColor()
var clipBtn = UIBarButtonItem(image: clipImage, style: UIBarButtonItemStyle.Plain, target: self, action: Selector("clipBtnPressed"))
clipBtn.tintColor = UIColor.whiteColor()
var pencilBtn = UIBarButtonItem(image: pencilImage, style: UIBarButtonItemStyle.Plain, target: self, action: Selector("pencilBtnPressed"))
pencilBtn.tintColor = UIColor.whiteColor()
// create a spacer
var space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: self, action: nil)
space.width = 10
var buttons = [pencilBtn, space, clipBtn, space, searchBtn]
navigationItem?.rightBarButtonItems = buttons
This solution is in Objective C
UIImage *settingImageName = [UIImage imageNamed:#"Menu_Burger_Icon"];
UIButton * settingButton = [UIButton buttonWithType:UIButtonTypeCustom];
[settingButton setImage:settingImageName forState:UIControlStateNormal];
[settingButton addTarget:self action:#selector(settingsBtnClicked) forControlEvents:UIControlEventTouchUpInside];
settingButton.frame = CGRectMake(0, 0, 30, 30);
UIBarButtonItem *settingBarButton = [[UIBarButtonItem alloc] initWithCustomView:settingButton];
UIImage *notificationImageName = [UIImage imageNamed:#"NotificationON"];
UIButton * notificationButton = [UIButton buttonWithType:UIButtonTypeCustom];
[notificationButton setImage:notificationImageName forState:UIControlStateNormal];
[notificationButton addTarget:self action:#selector(notificationButtonClicked) forControlEvents:UIControlEventTouchUpInside];
notificationButton.frame = CGRectMake(0, 0, 30, 30);
UIBarButtonItem *notificationBarButton = [[UIBarButtonItem alloc] initWithCustomView:notificationButton];
self.navigationItem.rightBarButtonItems = #[settingBarButton,notificationBarButton];
Solution reference by #mikle94. His answer is in Swift.
let rightActionButton:UIButton = UIButton()
if #available(iOS 11.0, *) {
let widthConstraint = rightActionButton.widthAnchor.constraint(equalToConstant: 30)
let heightConstraint = rightActionButton.heightAnchor.constraint(equalToConstant: 30)
heightConstraint.isActive = true
widthConstraint.isActive = true
}
else {
rightActionButton.frame = CGRect.init(x: 0, y: 0, width: 30, height: 30)
}
rightActionButton.setImage(UIImage.init(named: "3-dots-right-button"), for: .normal)
rightActionButton.addTarget(self, action: #selector(handleRightMenu), for: UIControlEvents.touchUpInside)
rightActionButton.setTitle("", for: .normal)
rightActionButton.tintColor = UIColor(hex:K.NODD_GREEN_HEX)
let rightActionBarButton:UIBarButtonItem = UIBarButtonItem(customView: rightActionButton)
let rightBarButtonItem1 = rightActionBarButton
let rightBarButtonItem2 = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(handleRight2Menu))
self.navigationItem.rightBarButtonItems = [rightBarButtonItem1,rightBarButtonItem2]
Try to change the constraintEqualToConstant
[myUIButton.widthAnchor constraintEqualToConstant:24].active = YES;
[myUIButton.heightAnchor constraintEqualToConstant:24].active = YES;
Supporting solution by #mkz, by using function to reduce the code (Swift 4.2.1)
Added most important parameters to the function (note how to pass selector to a function), you may want to add more as per your need.
func makeCustomNavigationButton(imageName: String, action: Selector) -> UIBarButtonItem{
let image = UIImage(named: imageName)!
let btn: UIButton = UIButton(type: UIButton.ButtonType.custom)
btn.setImage(image, for: .normal)
btn.addTarget(self, action: action, for: .touchUpInside)
btn.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
let barBtn = UIBarButtonItem(customView: btn)
return barBtn
}
How to call:
let search = self.makeCustomNavigationButton(imageName: "search", action: #selector(searchBtnPressed(_:)))
let clip = self.makeCustomNavigationButton(imageName: "clip", action: #selector(clipBtnPressed(_:)))
let pencil = self.makeCustomNavigationButton(imageName: "pencil", action: #selector(pencilBtnPressed(_:)))
self.navigationItem.rightBarButtonItems = [search, clip, pencil]
You can also wire things up first in Storyboard.
I have two right bar button items.
(This is objective-c code, which you can modify for swift.)
First create references to them in view controller.
#interface MyViewController ()
#property (weak, nonatomic) IBOutlet UIButton *smsButton;
#property (weak, nonatomic) IBOutlet UIButton *checkoutButton;
#end
Then, in viewDidLoad, adjust their widths and heights.
// Adjust right bar button item spacing.
self.smsButton.frame = CGRectMake(0, 0, 30, 30);
self.lockButton.frame = CGRectMake(0, 0, 30, 30);
This is one of methods to solve that.
Use UIBarButtonItem as a space
let space = UIBarButtonItem(barButtonSystemItem: .FixedSpace, target: nil, action: nil)
space.width = -20 // adjust as needed
self.navigationItem.rightBarButtonItems = [pencilBtn, clipBtn, searchBtn, space]

image for nav bar button item swift

I want to display an image in the left hand side of my nav bar in swift.
I have tried adding a nav bar button item and setting an image there.
The problem is that I have to use a really small image for it to fit in the nav bar nicely. But making such a small image leads to pixelation especially on the bigger phone iPhone 6 and 6 Plus.
Is there a way to use a good quality image and then set the frame to fit within the bounds of the nav bar?
My attempt:
var image = UIImage(named: "Harp.png")
image = image?.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: image, style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
self.navigationItem.leftBarButtonItem.frame = CGRectMake(0, 0, 53, 31)
//image.frame = CGRectMake(0, 0, 53, 31)
I tried putting the frame on the image first and then on the bar button item.
But this is throwing up an error:
Type of expression is ambiguous without more context.
Try This
let button = UIButton(type: UIButtonType.Custom)
button.setImage(UIImage(named: "yourImageName.png"), forState: UIControlState.Normal)
button.addTarget(self, action:Selector("callMethod"), forControlEvents: UIControlEvents.TouchDragInside)
button.frame=CGRectMake(0, 0, 30, 30)
let barButton = UIBarButtonItem(customView: button)
self.navigationItem.leftBarButtonItems = [newBackButton,barButton]
For Swift 3
let button = UIButton.init(type: .custom)
button.setImage(UIImage.init(named: "yourImageName.png"), for: UIControlState.normal)
button.addTarget(self, action:#selector(ViewController.callMethod), for:.touchUpInside)
button.frame = CGRect.init(x: 0, y: 0, width: 30, height: 30) //CGRectMake(0, 0, 30, 30)
let barButton = UIBarButtonItem.init(customView: button)
self.navigationItem.leftBarButtonItem = barButton
Swift 4
let button = UIButton(type: UIButton.ButtonType.custom)
button.setImage(UIImage(named: "getstarted"), for: .normal)
button.addTarget(self, action:#selector(callMethod), for: .touchDragInside)
button.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
let barButton = UIBarButtonItem(customView: button)
self.navigationItem.leftBarButtonItems = [barButton]
Here is action
#objc func callMethod() {
//do stuff here
}
Use this code:
self.navigationItem.leftBarButtonItem = nil
let button = UIButton(type: .custom)
button.setImage(UIImage (named: "ChatTab"), for: .normal)
button.frame = CGRect(x: 0.0, y: 0.0, width: 35.0, height: 35.0)
//button.addTarget(target, action: nil, for: .touchUpInside)
let barButtonItem = UIBarButtonItem(customView: button)
let button2 = UIButton(type: .custom)
button2.setImage(UIImage (named: "ActivityTab"), for: .normal)
button2.frame = CGRect(x: 0.0, y: 0.0, width: 35.0, height: 35.0)
//button.addTarget(target, action: nil, for: .touchUpInside)
let barButtonItem2 = UIBarButtonItem(customView: button2)
self.navigationItem.rightBarButtonItems = [barButtonItem, barButtonItem2]
Output:
Swift 5, XCode 11 to make Navigation Bar Item with rounded image, image from assets or to download from URL.
1) New file: UIBarButtonItem+RoundedView.swift
import Foundation
class ImageBarButton : UIView {
var imageView: UIImageView!
var button: UIButton!
convenience init(withUrl imageURL: URL? = nil, withImage image: UIImage? = nil, frame: CGRect = CGRect(x: 0, y: 0, width: 40, height: 40)) {
self.init(frame: frame)
imageView = UIImageView(frame: frame)
imageView.backgroundColor = .white
imageView.layer.cornerRadius = frame.height/2
imageView.clipsToBounds = true
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
addSubview(imageView)
button = UIButton(frame: frame)
button.backgroundColor = .clear
button.setTitle("", for: .normal)
addSubview(button)
if let url = imageURL { // you can use pods like Nuke or Kingfisher
URLSession(configuration: .default).dataTask(with: URL(string: imageUrl)!) {[weak self] (data, response, error) in
if let data = data , let image = UIImage(data: data) {
DispatchQueue.main.async {
self?.imgView.image = image
}
}
}.resume()
} else if let image = image {
self.imageView.image = image
}
}
func load()-> UIBarButtonItem {
return UIBarButtonItem(customView: self)
}
}
2) Add navigation bar items, you can use navigationItem.rightBarButtonItems, navigationItem.leftBarButtonItems:
private func initalizeNavigationBarItems() {
let searchBarButtonView = ImageBarButton(withImage: #imageLiteral(resourceName: "greenSearchIcon")) // Assets
searchBarButtonView.button.addTarget(self, action: #selector(presentSearchViewController), for: .touchUpInside)
if let user = AccountManager.currentUser, let userProfilePictureURL = user.imageUrl { // API Url
let profileBarButtonView = ImageBarButton(withUrl: userProfilePictureURL)
profileBarButtonView.button.addTarget(self, action: #selector(presentMoreViewController), for: .touchUpInside)
navigationItem.rightBarButtonItems = [searchBarButtonView.load(), profileBarButtonView.load()]
} else {
let profileBarButtonView = ImageBarButton(withImage: #imageLiteral(resourceName: "profileIcon"))
profileBarButtonView.button.addTarget(self, action: #selector(presentMoreViewController), for: .touchUpInside)
navigationItem.rightBarButtonItems = [searchBarButtonView.load(), profileBarButtonView.load()]
}
}
#objc func presentMoreViewController(_ sender: Any) {
// present MoreViewController
}
#objc func presentSearchViewController(_ sender: Any) {
// present SearchViewController
}
Preview
Swift 4 and 5:
let imageView = UIImageView(image: UIImage(named: "Harp"))
let buttonItem = UIBarButtonItem(customView: imageView)
self.navigationItem.leftBarButtonItem = buttonItem
There is a way to use images of different sizes, depending on the device. It's called an Asset Catalog. You'll probably already have one in your project, or if not, you can add one with File > New > File > Resource > Asset Catalogue.
Within your Asset Catalog, you can have multiple 'Image Sets' (these will be shown down the left-hand side). Add a new Image Set with the '+' at the bottom. For each Image Set, you can supply different images (e.g. of different sizes) for each of #1x, #2x, and #3x.
Then, to use one of these images in code, you simply use UIImage(named: "name_of_image_set") - note no extension. The correct image will be loaded, depending on the device.
Hope this helps!
Swift 5
You need to use constraints to properly set up nav bar button with image.
let button = UIButton(type: .custom)
button.setImage(UIImage(named: yourImageName), for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.widthAnchor.constraint(equalToConstant: 40).isActive = true
button.heightAnchor.constraint(equalToConstant: 40).isActive = true
let barButton = UIBarButtonItem(customView: button)
navigationItem.rightBarButtonItem = barButton

Resources