I set up a right navigation button like so inviewWillAppear in . a class ChatMessageViewController..
let button2 = UIBarButtonItem(image: nil, style: .plain, target: self, action: #selector(blockPressed(sender:)))
button2.title = "Block"
self.navigationItem.rightBarButtonItem = button2
Now on the click of blockPressed another shared function is called like so...
#objc fileprivate func blockPressed(sender: UIButton) {
XMPPConfig.shared.blockUser(userJID: theUserJID!) //XMPPConfig is another class having some common functions and delegate methods.
}
(This function basically blocks a certain user like blocking a whatsapp user. Once blocking happens, certain delegate methods are called. One such delegate method after which I change the Block button is given as follows..)
func xmppBlocking(_ sender: XMPPBlocking!, didBlockJID xmppJID: XMPPJID!) {
print("successfully blocked!")
ChatMessageViewController.shared.setupUnBlock()
}
Doing this also properly calls setupUnBlock() function in ChatMessageViewController like so...
func setupUnBlock() {
if XMPPConfig.shared.sectionGroupsFlag == false {
let button2 = UIBarButtonItem(image: nil, style: .plain, target: self, action: #selector(unblockPressed(sender:)))
button2.title = "Unblock"
self.navigationItem.rightBarButtonItem = button2
}
}
But the button title still remains unchanged...i.e. it is still "Block"..what could be the reason for this...?
You should initialize your UINavigationBarButton using another initializer:
let right = UIBarButtonItem(title: "Some title", style: .plain, target: self, action: #selector(rightNavBarButtonPressed))
You are using UIBarButtonItem(image:... instead.
I tried to duplicate your code and apparently everything works.
So, the problem may be due to three possible problems, as far as i can see.
it may be thread problem. This is unlikley unless you have not turned on the thread checker in xcode.. But inside both unblock and block codes, enter
print(Thread.current)
to see both blocks of codes in setting the rightbarButton is in main thread. If not, you should know how to solve them.
It may be view update problem, unlikely still, but worth a try.. So in your block of codes where you are adding rightBarButton, add one more line of code.
self.navigationController?.viewIfLoaded?.setNeedsLayout()
to update the navigationController's view after you have set the rightBarButtonItem.
The most likely problem in my opinion is that, you have been doubling calling block barButtonItem codes. This means when you have called unblock barButtonItem setup codes, you accidentally called the block barButtonItem too.
To debug this is easy, you just put a statement in each of block of the codes, to see if they appear together.
Related
So I was making a to-do list app, and I had this variable inside VIEWDIDLOAD:
var edit = UIBarButtonItem (title: "Edit", style: .plain, target: self, action: #selector(editfunc))
I wanted that when someone finishes editing, the button changes from 'edit' to 'done' so I wrote this:
#objc func editfunc () {
table.isEditing = !table.isEditing
if table.isEditing == true {
edit.title = "Done"
}
else {
edit.title = "Edit"
}
}
It didn't work. I googled it and it seems like the solution was to write 'var edit' outside of the viewdidload func, and also to use 'lazy' before it. It worked, but I still didn't understand why? What's the difference between defining properities inside and outside viewdidload and why did it work only when I used 'lazy'm, a
It's as Lorem ipsum commented that it's about the scope of the variable.
But to answer your second question about the lazy property is used on variables where you want to use self as Lazy waits for init to be run. self is still available as a property, but as init has not been run yet, you are basically asserting nil to the target property
I am wondering how do I get the following programmable button to action when pressed to go to another viewController.
Currently the button calls a function in the same view controller but I want it to go to SocialLoginViewController as Apple rejected my app because it does not allow Apple Signin so I need to change my app to allow that.
let rightBarButton = UIBarButtonItem(title: "Person", style: UIBarButtonItem.Style.done, target: self, action: #selector(FirstViewController.checkLogin(_:)))
rightBarButton.image = buttonIcon
self.tabBarController?.navigationItem.rightBarButtonItem = rightBarButton
So I am wondering what do I need to change to get the action to load
SocialLoginViewController
When pushing a controller to the navigation stack i execute:
self.navigationItem.title = "";
As i dont want the next view to show the name of the previous controller on the back button.
When i get back to that controller i do this:
override func viewWillAppear(_ animated: Bool) {
self.navigationItem.title = "Title Of View";
...
}
The title is set appropriately but it lags for about 1 second or so.. I remember using this techinique for quite some time without having a problem in the past. The code that sets the titles isn't within a network call or anything like that..
Any ideas about what might be causing this?
In order to hide the back button title you should set empty UIBarButtonItem instance to the self.navigationItem.backBarButtonItem
right after you push the new view controller, like so:
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .done, target: nil, action: nil)
This way you don't have to manipulate the title of the view controller.
I'm writing a to-do list type app, in order to learn swift for iOS development. I had a settings button on the Navigation bar, on the right side, and whenever a person clicked a button on top of the table view, they could add a new item to their list. That causes a "cancel" button to appear on the left side of the bar and a "add" button to appear on the right side. When the person is done, however, those buttons disappear, and so I programatically re-create the settings button, with a call to a function that is supposed to call the segue.
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "modify"), style: UIBarButtonItemStyle.Plain, target: nil, action: Selector("showSettings:"))
This is the code that creates the button on the navbar (and it is indeed created)
func showSettings(sender: AnyObject?) {
print("segueShouldBeDone!")
performSegueWithIdentifier("showSettings", sender: sender)
}
And this is the function that is supposed to call the segue (I added the print to see if it was at least being called, and it isn't).
I've had this same problem in another place in my code, but I had given up on fixing it cause it wasn't that important for me then. But now it is interfering with how the app works, so I wanted to know how to fix it.
Any help would be great.
Your showSettings: selector isn't being called because you specified nil instead of self for the bar button item's target. Change the line to:
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "modify"), style: UIBarButtonItemStyle.Plain, target: self, action: Selector("showSettings:"))
This assume the showSettings: method is in the same class that contains this line of code.
Read the documentation for this initializer, specifically the info about the target parameter.
I have a pretty common scenario. A tree of unknown depth based on data, so I have a navigation controller with a tableView controller as the root controller. Every time I need to go deeper, I create a new tableview controller, populate it with data based on the previous selection, and push the new tableview controller onto the navigation controller stack:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)
let cellText = cell?.textLabel?.text
let bcti = CustomDataClass(querystring: cellText!)
if(bcti.getStatus() == "Drill")
{
let bctvc = CustomTableViewControllerClass(tableinfo: bcti)
//Note: self in this instance is my custom UITableViewController class
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: cellText, style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
self.navigationController?.pushViewController(bctvc, animated: true)
}
This works fine, a new tableview controller is created based on the selected cell from the previous controller, pushing it on the navigation stack works fine as well. The weird thing is I can't seem to get the back bar item to display the selected value from the previous controller.
If I use the cellText variable containing the text of the previously selected cell (as shown in the code above) to assign the UIBarButton title, it seems to ignore that and default to having 'Back' as the title anyway.
The cellText variable clearly has the correct value in it, I verified with NSLog statements, and also even tried conditionally unwrapping it to be 100% sure it has a value at run-time. It's being used to progress in the first place, so I think we can hopefully rule out an optional nil issue.
What's really strange to me though is that hard-coding a string into the title works just fine. So for instance if I replace:
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: cellText, style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
with:
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "Bananas", style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
It correctly displays Bananas instead of Back. I can also declare a variable and hard code that with a different value and it works fine. I.E:
let tempvar = "Bananas!"
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: tempvar, style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
It seems to only be when I try to access the text associated with the cell that it doesn't work.
Does anyone know what I'm missing here? Something else that might be worth noting is that I'm using a Storyboard to set up my initial navigation controller & tableview controller, I'm only creating the new instances of the tableview controller programmatically.
Check what the documentation of backBarButtonItem says. The cell text might simply be too long.
Instead of trying to hardcode the same values, try to change the datasource so that it has very short text values and see if it works. E.g. the cells might be displaying the first line of the multiline text now and you might have hardcoded a copy of only the first (the only visible) line. Hardcode is bad, even for tests.