Why My UITapGestureRecognizer method not calling for Navigationbar titleView in swift - swift

with the below code i am able to get title image in navigationbar but the titlePressed method is not calling.. and if i tap title i am unable to go HomeVC.. please do help.. where am i wrong
func setUpNavigationBar(){
let logoImageView = UIImageView.init(image: #imageLiteral(resourceName: "pic-logo"))
logoImageView.tintColor = .darkGray
logoImageView.frame = CGRect(x:0.0,y:0.0, width:100,height:25.0)
logoImageView.contentMode = .scaleAspectFit
logoImageView.widthAnchor.constraint(equalToConstant: 200).isActive = true
logoImageView.heightAnchor.constraint(equalToConstant: 50).isActive = true
self.navigationItem.titleView?.isUserInteractionEnabled = true
let titleTap = UITapGestureRecognizer(target: self, action: #selector(titlePressed))
self.navigationItem.titleView?.addGestureRecognizer(titleTap)
self.navigationItem.titleView = logoImageView
}
#objc func titlePressed(){
print("title clicked...")
let vc = StoryBoard.main.instantiateViewController(identifier: "HomeVC") as! HomeVC
self.navigationController?.pushViewController(vc, animated: true)
}

self.navigationItem.titleView?.addGestureRecognizer(titleTap)
self.navigationItem.titleView = logoImageView
You add a gesture recognizer, if title view is not nil, and then on the next line you change the title view right away to a different thing altogether, which won't have a gesture recognizer on it.
self.navigationItem.titleView = logoImageView
logoImageView.addGestureRecognizer(titleTap)
This line:
self.navigationItem.titleView?.isUserInteractionEnabled = true
Is also problematic because: titleView is likely nil at this point, so this line will do nothing, and you change the title view later anyway.

Related

Cant change colour of searchBar and it jumps to top of view when selected

I'm trying to attach a search bar to the top of my tableView and change its attributes (eg. colour, placeholder). However, I can't figure out how. I've tried embedding the tableView in another view but that didn't help. Any ideas?
func setupSearch(){
search.delegate = self
search.automaticallyShowsCancelButton = false
search.searchBar.tintColor = UIColor.red
search.searchBar.barTintColor = UIColor.red
search.obscuresBackgroundDuringPresentation = false
search.hidesNavigationBarDuringPresentation = false
search.searchBar.placeholder = "Type something here to search"
navigationItem.searchController = search
tableView.tableHeaderView = search.searchBar
}
This function is called in the viewDidLoad() and the tableView is added but not with the right colour or placeholder and jumps to the top of the screen when selected.
Any help would be appreciated.
This is the updated code for setupSearch (everything is working fine except the bar jumps to the top when selected):
func setupSearch(){
search.delegate = self
search.automaticallyShowsCancelButton = false
search.searchBar.barTintColor = UIColor.red
search.obscuresBackgroundDuringPresentation = false
search.hidesNavigationBarDuringPresentation = false
tableView.tableHeaderView = search.searchBar
}
I declare the search bar at the start using:
let search = UISearchController(searchResultsController: nil)
Any ideas on how to stop the bar jumping to the top?
Just add search bar as tableview's headerview not with navigation's item searchcontroller(not add search bar with both(tableview and navigation) as in your code). You can try with updated code below:
func setupSearch(){
search.delegate = self
search.automaticallyShowsCancelButton = false
search.searchBar.barTintColor = UIColor.red
search.obscuresBackgroundDuringPresentation = false
search.hidesNavigationBarDuringPresentation = false
search.searchBar.placeholder = "Type something here to search"
tableView.tableHeaderView = search.searchBar
self.definesPresentationContext = true
}
override func viewDidLoad() {
super.viewDidLoad()
setupSearch()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil) // be notified when the keyboard changes your table View frame
}
#objc func keyboardWillShow(notification: NSNotification) {
tableView.frame.origin.y = 0 // reset the table view to its original coordinates
}
func setupSearch(){
// for iOS 12 and lower, you can change the placeholder like this :
let textFieldSearchBar = searchBar.value(forKey: "searchField") as? UITextField
textFieldSearchBar?.textColor = .red
let searchBarLabel = textFieldSearchBar!.value(forKey: "placeholderLabel") as? UILabel
textFieldSearchBarLabel?.textColor = .red
}

UITapGestureRecognizer works first time, but not second time

[Greatly simplified]
I'm following a "Let's Build That App" YouTube series on Firebase 3. It's from 2016, so I've had to rework some of the code since Swift has evolved since then, but mostly it's a useful tutorial.
But, I'm stuck on something.
The red box is intended to be a custom titleView with an Image and Name, but I've simplified it to try to find the problem.
viewWillAppear calls setupNavbar which sets up the navbar.titleView:
func setupNavbar() {
let titleView = UIView()
titleView.frame = CGRect(x: 0, y: 0, width: 300, height: 40)
titleView.backgroundColor = .red
let containerView = UIView() // for the Image and Label, later
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.backgroundColor = .green
// left, top, width, height anchors equal to same for titleView
containerView.leftAnchor.constraint(equalTo: titleView.leftAnchor)
// top, width, height are similar
titleView.addSubview(containerView)
self.navigationItem.titleView = titleView
let recognizer = UITapGestureRecognizer(target: self, action: #selector(showChatController))
titleView.addGestureRecognizer(recognizer)
}
The selector's function is:
#objc func showChatController() {
let chatController = ChatLogTableViewController()
navigationController?.pushViewController(chatController, animated: true)
}
The class ChatLogTableViewController has just the default viewDidLoad().
First, I'm surprised the box is red, and not green. Why is that?
Second, if I click the red box, the ChatController is loaded, as expected. But, when I click "Back" and return to this screen, the red box is not visible, thus I can no longer tap on it. BUT....If I sign out and sign in/up again, the box is red and I can click it again.
What am I missing?
Update 1: The "+" creates a new controller and presents it.
present(UINavigationController(
rootViewController: NewMessageTableViewController()),
animated: true,
completion: nil)
That controller is currently empty, except for a leftBarButtonItem which is just a barButtonSystemItem (.cancel). Just like "Sign Out", this also "resets" the gesture and it works.
Update 2: Code added upon request.
Update 3: question greatly simplified. Also, if I change the showChatController code to just print ("show Chat Controller"), I can click to my heart's content; the red box and its tap gesture both remain.
So, there is something happening when I ...pushViewController and then come back.
Have you tried to set isUserInteractionEnabled property of the label which you set as the navBar's titleView? I know it's silly but I've missed this a lot of times :)
let recognizer = UITapGestureRecognizer(target: self, action: #selector(YourViewController.titleWasTapped))
titleView.isUserInteractionEnabled = true
titleView.addGestureRecognizer(recognizer)
you can try following things:
1. "User Interaction Enabled" in the UILabel Attributes Inspector in the Storyboard.
2. override func viewDidLoad(animated: Bool) {
super.viewDidAppear(animated)
self.titleView.userInteractionEnabled = true
var tapGesture = titleView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(showChatController)))
self.titleView.addGestureRecognizer(tapGesture)
}
func showChatController() {
println("Tap Gesture recognized")
}
Hi #Zonker I've tested your setupNavBar(). It's working fine nothing worng with your code when I press and go back clicking titleView. Reason why you're not getting .green color is you have to give height and width for containerView and big reason is you've put addSubView code below the anchor and there is no .isActive = true in your containerView.leftAnchor.constraint... Please check setupNavBar() code below:
func setupNavbar() {
let titleView = UIView()
titleView.frame = CGRect(x: 0, y: 0, width: 300, height: 40)
titleView.backgroundColor = .red
let containerView = UIView() // for the Image and Label, later
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.backgroundColor = .green
titleView.addSubview(containerView)
// left, top, width, height anchors equal to same for titleView
containerView.widthAnchor.constraint(equalToConstant: 300).isActive = true
containerView.heightAnchor.constraint(equalToConstant: 40).isActive = true
containerView.leftAnchor.constraint(equalTo: titleView.leftAnchor).isActive = true
// top, width, height are similar
self.navigationItem.titleView = titleView
let recognizer = UITapGestureRecognizer(target: self, action: #selector(showChatController))
titleView.addGestureRecognizer(recognizer)
}
It would better if you push your code in github so we can test your code

How to Change back button title on navigation controller in swift3?

I want to change the title of backbutton to any name in swift 3.I tried many ways but none of them worked for me.
self.navigationItem.backBarButtonItem?.title="Title"
self.navigationController?.navigationItem.backBarButtonItem?.title="Title"
Just for information i have written below code in appdelegate.
let backImage : UIImage = UIImage(named:"backArrow")!
UINavigationBar.appearance().barTintColor = UIColor(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 1.0)
UINavigationBar.appearance().tintColor = UIColor.white
UINavigationBar.appearance().backIndicatorImage = backImage
UINavigationBar.appearance().backIndicatorTransitionMaskImage = backImage
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName : UIColor.white]
UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffsetMake(0, 0), for: .default)
IQKeyboardManager.sharedManager().enable = true
self.window?.backgroundColor = UIColor.white
Navigation item back button name will be same as the title of previous view controller which is pushing it to the navigation stack :)
So if VC A pushes VC B, back button in VC B will be A.
So all you can do is, to change the title of the previous viewController before pushing the new viewController using code :)
self.navigationItem.title = "ABCD"
And in ViewWillAppear of VC A,you can revert the title back to whatever it was earlier :)
self.navigationItem.title = "Back to xyz"
All that being said, if you don't want all this circus :) you can simply hide the default back button using,
self.navigationItem.hidesBackButton = true
in your VC B, create a UIBarButton item, set whatever the title you want to set and then set that as leftBarButtonItem :) using,
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: NSLocalizedString("ABCD", comment: "ABCD"), style: .plain, target: self, action:#selector(self.abcdTapped:)
of course now that will not show "<" icon :) Now if you want that as well you can add it as a image to back bar button item :) but its cumbersome :)
Hope it helps :)
You will have to set the backBarButtonItem property of the navigationItem of the viewController that you push the said viewController from.
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.plain, target: nil, action: nil)
However, you must set this for each viewController.
This is the way:
extension UINavigationController {
func addCustomBackButton(title: String = "Back") {
let backButton = UIBarButtonItem()
backButton.title = title
navigationBar.topItem?.backBarButtonItem = backButton
}
}
In Swift 3.0 put below code in appdelegate didFinishLaunchingWithOptions method its worked perfectly for me
let backImage = UIImage(named: "BackNavigation")?.withRenderingMode(.alwaysOriginal)
UINavigationBar.appearance().backIndicatorImage = backImage
UINavigationBar.appearance().backIndicatorTransitionMaskImage = backImage
UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffsetMake(0, -80.0), for: .default)
The last line will remove the title of Navigation Back Button if you don't want to remove title then just comment it
I didn't find the answer that I was looking for so I share with you my solution.
Sometimes you have to change the text of the back button in the parent ViewController and not in the ViewController where seems to be defined the back button, remember that a navigation controller stacks ViewControllers one after another.
In my case I did this on the function prepare(for segue: ) of the "ParentViewController":
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showChildViewController" {
if let childViewController = segue.destination as? ChildViewController {
let backItem = UIBarButtonItem()
backItem.title = "Back"
navigationItem.backBarButtonItem = backItem
}
}
Try following steps to set image to your back button..
Output:
Step 1:
Add following code to your AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
var backButtonImage = UIImage(named: "Your Image Name")
backButtonImage = backButtonImage?.stretchableImage(withLeftCapWidth: 0, topCapHeight: 0)
UIBarButtonItem.appearance().setBackButtonBackgroundImage(backButtonImage, for: .normal, barMetrics: .default)
UINavigationBar.appearance().barTintColor = UIColor(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 1.0)
UINavigationBar.appearance().tintColor = UIColor.white
return true
}
Step 2:
Add following code to your MainVC
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
title = "Title 1"
navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName:UIColor.white, NSFontAttributeName:UIFont(name:"HelveticaNeue", size: 20)!]
}
Step 3:
Add following code to your DestVC or 2ndVC
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
title = "Title 2"
navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName:UIColor.white, NSFontAttributeName:UIFont(name:"HelveticaNeue", size: 20)!]
}
Step 4:
Select your navigationBar from your StoryBoard and goto Attribute Inspector. Under Navigation Item change your Back Button name enter a empty space or programatically create a back button with plain title..
Step 5:
Add icon image to your Assets. 1x29pt,2x58pt and 3x87pt. I am not sure about the asset image size.Check with apple doc about the size class..
Update:
My Similar answer related to this post.
How to customize the navigation back symbol and navigation back text?
You can easily do that from the storyboard by setting the title of the previous screen. Image explaining how to do that from storyboard - or you can do that by adding the following code to the view controller you're navigating BACK to.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(true)
let backItem = UIBarButtonItem()
backItem.title = "Title"
navigationItem.backBarButtonItem = backItem
}
in viewDidLoad()
let backBarButtonItem = UIBarButtonItem(title: "You back button title here", style: .plain, target: nil, action: nil)
navigationItem.backBarButtonItem = backBarButtonItem

Why LeftBarButtonItem doesn't appear in the navigationbar in swift

I have two view A and view B.
From view A to view B, I do not use navigation controller, I used performSegueWithIdentifier() and I don't want to use navigation controller to pass view A to view B.
But in the view B, I want to add a leftBarButtonItem in the navigation bar(I have embed a navigation controller for view B) like a back button with a arrow.
In order to achieve 100% same with the system backbitten with arrow. I use NSMutableAttributedString and UIButton. code is below:
let string = "< Retour" as NSString
var attributedString = NSMutableAttributedString(string: string as String)
let ArrowAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor(), NSFontAttributeName: UIFont.systemFontOfSize(20)]
let TextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor(), NSFontAttributeName: UIFont.systemFontOfSize(10)]
attributedString.addAttributes(ArrowAttributes, range: string.rangeOfString("<"))
attributedString.addAttributes(ArrowAttributes, range: string.rangeOfString(" Retour"))
let backbutton = UIButton(type: .Custom)
backbutton.addTarget(self, action: "back:", forControlEvents: .TouchUpInside)
backbutton.setAttributedTitle(attributedString, forState: UIControlState.Normal)
self.navigationItem.setLeftBarButtonItem(UIBarButtonItem(customView: backbutton), animated: true)
rightBtn = UIBarButtonItem(title: "Ok", style: .Plain, target: self, action: "save:")
But I can not see left button in the navigation bar in view B…why I can not see it in the navigation bar? Why the left button disappear?
Thank you very much.
I have tried the new code for a label, but it doesn't work yet...
let barButtonBackStr = "< Back"
let attributedBarButtonBackStr = NSMutableAttributedString(string: barButtonBackStr as String)
attributedBarButtonBackStr.addAttribute(NSFontAttributeName,
value: UIFont(
name: "AmericanTypewriter-Bold",
size: 18.0)!,
range: NSRange(
location:0,
length:1))
let label = UILabel()
label.attributedText = attributedBarButtonBackStr
label.sizeToFit()
let newBackButton = UIBarButtonItem(customView: label)
self.navigationController!.navigationItem.setLeftBarButtonItem(newBackButton, animated: true)
Thank you
Try a backbutton.sizeToFit() you'll see your button
You create a button but you never set the frame
You can also set the frame directly instead of sizeToFit() method like backbutton.frame = CGRectMake(0, 0, 100, 20)
PS: TextAttributes wasn't used
You must write it to :
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
...
}
Try to set a breakpoint after your UI design and try to launch the Debug View Hierarchy to see if your button exist or is hidden by another object
Next, after you have set your button try to make:
self.navigationController!.navigationItem.leftBarButtonItem.customView.sizeToFit()

Why is my image not showing up Fullscreen?

I have the following problem. I have about 10 different images which are in a view controller. Now I want the image to switch to fullscreen when they are tapped on. I already set the allow user interaction option to yes, and put in the following code i found on this website:
import UIKit
class ImageViewController: UIViewController {
#IBAction func imageTapped(sender: UITapGestureRecognizer) {
let imageView = sender.view as! UIImageView
let newImageView = UIImageView(image: imageView.image)
newImageView.frame = self.view.frame
newImageView.backgroundColor = .blackColor()
newImageView.contentMode = .ScaleAspectFit
newImageView.userInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: "dismissFullscreenImage:")
newImageView.addGestureRecognizer(tap)
self.view.addSubview(newImageView)
}
func dismissFullscreenImage(sender: UITapGestureRecognizer) {
sender.view?.removeFromSuperview()
}
Does anyone know why my images are not tappable and turning fullscreen?
Make sure both the image view have userInteractionEnabled = YES and
here's an example for what you are trying to do here https://github.com/abhinavsingh77/ImagePreview