Set all back button titles in UINavigationController - ios

I'm trying to be clever about setting all title properties of the the "Back" buttons in a UINavigationController so that I don't have to do self.navigationController.navigationBar.backButtonItem.title = "Back" everywhere or subclass a UINavigationController and set it everywhere, so I've created this extension:
extension UINavigationItem {
open var backBarButtonItem: UIBarButtonItem? {
get {
return self.backBarButtonItem
}
set {
newValue?.title = "Back"
backBarButtonItem = newValue?
}
}
}
But it says 'backBarButtonItem' used within its own type.
Has anybody done this before or can think of a way to make it work?

You are getting this error because you cannot create a variable with the name which is similar to those variables which are defined in the SDK.
You can't override the existing functionality
Like in your case you are naming it as backBarButtonTitle which is defined as open var backBarButtonItem: UIBarButtonItem? in UINavigationBar class of UIKit
As it is mentioned in doc of Apple
Extensions can add new functionality to a type, but they cannot
override existing functionality.

Please follow this Screen shot Image then run your project . I think you can solved your problem easily :)

Related

Change TabBar Items after changing app language from inside of app

I have an app and from inside of it I am changing its language.
Language getting properly updated to other screens by changing UIView appearance.
Localize.setCurrentLanguage("ar")
UIView.appearance().semanticContentAttribute = .forceRightToLeft
I'm not able to get control back in my tabcontroller file. TabBar is custom created. I checked with awakefromNib() but it is not getting invocated every time. Is there any tab bar method where I can get control when it appears every time or is there any way to change language of tab bar item titles?
After changing app language in your VC create and call function localizeTabBar():
func localizeTabBar() {
tabBar.items![0].title = "1tab".localized
tabBar.items![1].title = "2tab".localized
tabBar.items![2].title = "3tab".localized
tabBar.items![3].title = "4tab".localized
}
For .localized use this String Extension
Or something like that:
func localizeTabBar() {
tabBar.items?.enumerated().forEach{ (index, item) in
item.title = "\(index)tab".localized
}
}
For .localized use this String Extension

Set title of navigation bar

So I have a basic view controller with a navigation bar, this is view controller B, so I'm performing a segue to go here, and I'm trying to change the title like this:
override func viewDidLoad() {
debugPrint(self.selectedName)
super.viewDidLoad();
self.navigationItem.title = "A NEW TITLE"
}
But it doesn't do anything
To set Title on NavigationBar simply we can do by below code
self.title = "Your Title"
For Swift 3:
If you want to set just the navigation title without using a UINavigationController then make an outlet of the navigation item as
#IBOutlet weak var navItem: UINavigationItem!
and then in viewDidLoad() write
navItem.title = "ANY TITLE"
There are plenty of methods which you can follow to achieve this. Here is few of those.
First things first.
If you are ready to "Embed in" a navigation controller or if you have already one then you can access that using following code.
self.navigationController?.navigationBar.topItem?.title = "Your Title"
Now for more customization:
Place a UINavigationBar object on ViewController scene and add constraints to it.
Make an outlet of newly placed UINavigationBar like as follows -
#IBOutlet weak var orderStatusNavigationbar: UINavigationBar!
Now set the title using the outlet.
orderStatusNavigationbar.topItem?.title = "Your Title"
All this above code are in Swift 3 but will work on lower versions of Swift also(atleast on Swift 2.0)
Hope this helped.
Swift 4 / XCode 10
Add new NavigationBar -> Drap and Drop it to your view
Press CTRL to add new Outlet Action
Example : #IBOutlet weak var main_navbar: UINavigationBar in ViewController class.
Then set the title : main_navbar.topItem?.title = "YOUR TITLE"
This solution worked for me, hope it does for you too.
- rust
Ok,
So you need to embed the whole thing in a Navigation Controller first, and then make that navigation controller as the initial controller.
Select your storyboard, click the first controller then click this -
Then you remove the navigation bar you set(put) over the last controller named "title".
The reason this didnt work, as you are trying to change the title of the navigation controller's navigation bar, but it doesnt have it, hence it cant change it.

Set initial viewController in Navigation controller programmatically (Layer SDK)

I want to add Layer SDK to my application (using Swift).
All view controllers here are created programmatically. Therefore I can't segue to them. I have 4 tabs in my application (UITabBarController). One of them is chat. In the chat tab I created a segue to UINavigationController. Now I want to load conversationListViewController in this UINavigationController. For that I created a class for this UINavigationController i.e. ConversationListViewController and added the following code:
class ChatNavigationViewController: UINavigationController {
var conversationListViewController: ConversationListViewController!
var layerClient: LYRClient!
override func viewDidLoad() {
let appDelegate = UIApplication.sharedApplication().delegate as!AppDelegate
self.layerClient = appDelegate.layerClient
self.conversationListViewController = ConversationListViewController(layerClient: appDelegate.layerClient)
self.conversationListViewController.displaysAvatarItem = true
self.navigationController!.pushViewController(self.conversationListViewController, animated: true)
}
}
But this is not working. And giving this kind of effect: the ConversationViewController is not loaded in UINavigationController. I am not sure if I am doing it the correct way. I'm searching for the correct way, but unable to find.
I Solved it. I dragged new NavigationViewController and added ConversationListViewController to rootviewController.I think i should try this first. Anyways thanks guys for your help.
Because you want to do this programatically:
You need to manually initialize the controller before stacking it up on the Navigation Controller. Try this:
navigationController?.pushViewController(self.conversationListViewController.init(), animated: true)

Creating a floating menu in an iOS application

Looking to create a floating menu in Swift for an iOS application I am developing. Something along the lines of the little red circle menu as shown in the following image.
My initial thoughts were to extend the UIViewController class and add the respective drawing/logic there, however, the application is comprised of a few other controllers, more specifically the UITableViewController which in itself extends UIViewController. Is there perhaps a good place for an extension perhaps? Or is there a more eloquent way of drawing the menu on specific views without the mass duplication of menu related code?
The menu itself will be shown on most screens, so I need to selectively enable it. It'll also be somewhat contextual based on the view/screen the user is currently on.
Any awesome ideas?
You can create your own with the animations and all the things, or you can check this library
https://github.com/lourenco-marinho/ActionButton
var actionButton: ActionButton!
override func viewDidLoad() {
super.viewDidLoad()
let twitterImage = UIImage(named: "twitter_icon.png")!
let plusImage = UIImage(named: "googleplus_icon.png")!
let twitter = ActionButtonItem(title: "Twitter", image: twitterImage)
twitter.action = { item in println("Twitter...") }
let google = ActionButtonItem(title: "Google Plus", image: plusImage)
google.action = { item in println("Google Plus...") }
actionButton = ActionButton(attachedToView: self.view, items: [twitter, google])
actionButton.action = { button in button.toggleMenu() }
}
There is another alternative with this great library :
https://github.com/yoavlt/LiquidFloatingActionButton
You just have to implement the delegate and the dataSource in your ViewController:
let floatingActionButton = LiquidFloatingActionButton(frame: floatingFrame)
floatingActionButton.dataSource = self
floatingActionButton.delegate = self
You could use view controller containment. The menu can be its own view controller with its view laid transparently over top the content view controller.
For example this can be set up in the storyboard by dragging out two container views into a vanilla view controller.

How do I refer to the title of a view controller from an embedded container view's view?

I have a UIViewController (let's call it "EditViewController") which has a Container View on it (call it "ContainerView") where I switch in and out various subviews (call the one I'm most concerned with "EditDetailsView").
From the EditDetailsView I need to change the title in the navigation bar of the EditViewController. I can't seem to be able to figure out how to reference it.
From inside EditViewController I can simply make a statement like:
self.title = #"Some new title";
and it changes just fine.
But from the EditDetailsView view that is currently the subview of ContainerView nothing seems to work:
self.title = ... is obviously wrong.
super.title = ... doesn't work and seems wrong anyway.
super.super.title = ... errors out as super is not a property found on UIViewController.
Can someone please tell me how to reference the title? I'm kinda lost.
Thanks!
While digging through the parentViewController chain is possible, it is error prone and unrecommended. It is considered a bad design. Imagine you set up your view controller hierarchy in some manner, but after a few months change it a bit and now there is one level deeper. Or, you would like to use the same view controller in several different scenarios. A much better design would be to pass the new title to the container view controller using delegation. Create a delegate protocol, with a method for setting the title.
- (void)childViewController:(ChildViewController*)cvc didChangeToTitle:(NSString*)title;
I know this is an old thread, but in case someone else needs it: to avoid boilerplate code with delegation, and avoid digging into the parentViewController, I did it the other way around.
I've referenced the child view controller from the parent and got their title. So no matter which child you show, you will always get the right title.
This is in Swift 3.
So, basically, this is your parent:
class EditViewController: UIViewController {
override func viewDidLoad() {
if let child = self.childViewControllers.first {
self.title = child.title
}
}
}
And this is your child:
class ContainerView: UIViewController {
override func viewDidLoad() {
self.title = "Sbrubbles"
}
}
Another good way to avoid excess code with delegation is to use RxSwift, if you are familiar to Reactive programming.

Resources