UIToolbar implemented with storyboard: how to change a button? - ios

in my app I've implemented this toolbar within Storyboard:
As you can see, I've used four buttons and three flexible space bar button items.
For each button I created an outlet and the corresponding action and I've linked it all with Storyboard. Everything works well.
Now I want to dynamically replace a button of the toolbar.
I know that, if the toolbar itself was implemented programmatically, this can be easily achieved with the following:
[toolbarButtons replaceObjectAtIndex:4 withObject:newButton];
I'm wondering if this is possible also in my case, where toolbar and buttons are implemented via Storyboards. Any ideas?
Thanks in advance,
yassa

If your UIToolbar is part of a UINavigationController then you can access it directly with toolbarItems property. Otherwise you would have to create a IBOutlet in your viewController and link your toolbar to it to access it.
This would be the case whether you were using a storyboard or NIB.

If you've created outlets, Use the Outlet property to change it.
self.myToolBarButton = newButton;
where "myToolBarButton" is the name you gave that button.

Related

How to add a custom action for a UIBarButtonItem in the StoryBoard?

I want to have a couple of buttons in my iOS app at the bottom of the screen and so used a UIToolBar and added a couple of Bar Button Items to it. But I realized that these BarButtonItems are not considered to be regular buttons. So I am not able to set actions on mouse up on these. Is there a way to set a function to be called when these buttons are clicked? If this is not possible through the storyboard, can I access it programmatically?
Select the UIBarButtonItem, Control+Dragging at the implementation section in .m file. Create an IBAction. You may put a NSLog statement to check the user tap.
Do not make an IBAction from the bar button item object or the code will not run.
In the document outline, control+drag from the button INSIDE the bar button item container. The IBAction should run normally now.
Create one outlet:
#property (weak, nonatomic) IBOutlet UIBarButtonItem *menuBarBtn;
In ViewDidLoad or somewhere you can add like this:
[_menuBarBtn setAction: #selector( revealToggle:)];

Swift custom toolbar implementation

I'm trying to implement a custom UIToolbar. The toolbar currently has 5 buttons: 3 change the content on the page (keeping the same toolbar with toggled item selected) & the other two segue to modal view controllers.
How to segment the code/views amongst the several different "pages"?
I currently have a class called ToolbarViewController that instantiates the toolbar with the different items. It has a generic action that switches the button titles "ON" and performs different actions depending on which one was tapped. Each subsequent VC that needs to have that toolbar just subclasses ToolbarViewController and the toolbar is automatically created without code replication.
By segueing this way, if the user is in tab1 and presses button1 the program crashes, because there's no segue from tab1 to tab1. One way I have been able to fix this is by having an initializer in ToolbarViewController that receives the "currentTab" and doesn't allow segues for that tab. This seems incredibly inefficient.
Another solution I've been considering is having a single VC that has the toolbar. By pressing a button, I would be able to change the View of that VC. This also has a problem, I can't have AutoLayout set in storyboard, because the VC doesn't segue to anything, just changes the view itself. This will become a problem when I need some complex views with constraints everywhere.
Are any of the 2 approaches I listed advisable? If not, what approach should I take & how should I implement these changes?
I think you should use a TabBar instead of a toolbar as you can achieve much of the same functionality I believe you are trying to achieve with greater ease.
However if you are determined to preserve the modal segues you can setup actions for each of your toolbar button presses. Give your toolbar buttons action properties.
In Swift:
UIBarButtonItem(title: "YourTitle", style: UIBarButtonItemStyle.Plain, target: self, action: #selector(YourVC.yourMethod(_:)))
func yourMethod() {
(code here)
}
As far as your problem with AutoLayout, you should drop an empty view into your ToolBarViewController then create custom UIView subclasses with nibs. Setup the way you want each view to look in the nibs with your constraints. Then, in code, load each custom UIView Subclass into the empty view on your ToolBarViewController.
Good luck!

Multiple outlets with Multi-Scenes and ViewControllers for iOS

So I have have three scenes with three individual textFields. I set up three ViewControllers for each of the scenes to handle dismissing the keyboard on each respective textField in it's own scene. But I can't get the textField object to create a IBAction outlet using the control drag method. Even created a custom UITextField class to try and resolve the solution but that didn't seem to help. Any ideas why I can't get this to work?
Here is my Storyboard set up:
This is what it looks like when I try an control drag
So I finally found the solution. Even though the UITextField had it's own class the scene it's self I had was under the wrong UIViewController class. I selected the UIViewController by selecting the black bar underneath it (this can also be done using Document Outline or Shft+Cntrl+Click and selecting the proper UIViewController) and changing the Custom Class setting under the Identity Inspector to that of the UIViewController that I intend to interact with it.

How can I edit a manually added UINavigationBar sub view in interface builder using storyboards?

I've added a UIView as a sub view of a navigation bar and resized it to look like a tool bar.
It will house 3 buttons:
One for changing the style of how clothing items in a collection view
One for filtering results e.g. favourites, recommended etc
One for refining results
I'd prefer to create these buttons and doing all the editing in interface builder. Is this possible?
Here is my current code I use to create the view:
#interface MyCollectionViewController () <UIScrollViewDelegate>
#property (nonatomic, weak) UIView *filterBar;
#end
#implementation MyCollectionViewController
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
UIView *filterBar = [[UIView alloc] initWithFrame:CGRectMake(0, 42, self.view.frame.size.width, self.navigationController.navigationBar.frame.size.height)];
[[[self navigationController] navigationBar] addSubview:filterBar];
[filterBar setBackgroundColor:[[UIColor whiteColor] colorWithAlphaComponent:0.9f]];
[filterBar setTag:1];
}
My buttons will be like select buttons that trigger UIActionSheet instances or push other controllers onto the top of the stack where I can provide an interface for carrying out an action e.g. refining types of clothes then searching.
Here is a photo of the an app with the bar I'm talking about:
Anyway the is this possible, can I link the view I created in code above up in interface builder and work on it visually rather than in code?
Thanks for your time.
Kind regards
Short answer: you can't really...
Storyboards/IB don't allow much customization of UINavigationBar aside from setting title and left/right barButtonItems. Most of what (it seems like) you want to do has to be done in code using a custom UIView subclass.
Longer answer:
To use the standard UINavigationBar, your menu, search, star & suitcase(?) icons at the top would need to be added as arrays of barButtonItems set to the left & right sides. This can only be done in code (you could use a segmented control but need to customize appearance in code anyway).
See 2nd response here for an example: How to add multiple buttons to a NavigationBar?
For the 2nd "filter" row, looks like it would have to be a separate view created & added separately as you've already done, but ideally an instance of a custom UIView subclass. You can't expand/add that many things to the navigation bar in IB.
Create a new UIView subclass. Then in IB drag out/resize a UIview and set it to be your custom class. You could then drag out items to sort of approximate your design.
The issue is that IB only has stock UIKit items and options for customizing them can be limited.
The collection view toggle could be a segmented control, but you
can only change/remove the default blue-rounded border in code, so
you're not saving any work.
Your middle "filter" dropdown would have to be a UIPickerView
(spinner), or perhaps a UITableView subclass. Either of these you'd
have to code a bunch of separately anyway.
The right-side "refine" button could be just a simple UIButton w/a
label. You'd have to change the default color & add a border in code or w/a custom image anyway (since iOS7 removed button borders).
You really might as well code it. IB isn't going to save much time or energy for this many custom elements...
In Interface Builder, you can drag a UIView to a UINavigationItem in a UINavigationBar:
This view you just dragged is accessible as:
self.navigationItem.titleView
You can also link the buttons or whatever you put in that view to your .m file

Segues from a subView

Just trying to teach myself storyboarding and have run into a question I was hoping people may have an answer to.
I wanted to create a reusable upper toolbar so that in case I ever had to change it, it would update all of my scenes. I created a sized ViewController in my storyboard. I then load it into a subview of each of my scenes using the menu's identifier. THat seems to work pretty well (although, feel free to tell me that's the wrong way to do it).
Here's where the problem starts. On that top toolbar, I have a UIButton which I connect to another sized ViewController in my storyboard as a popover. Basically, a drop down menu. If I just load up the top toolbar, works fine. If I connect just a regular button to that popover scene using a segue, that works too. If, however, I try to click the button and follow the segue while the toolbar is within a subView I crash with EXC_BAD_ACCESS. I presume I'm not allowed to spawn a popOver from a subView or follow a segue within a subview? The latter seems wrong since you effectively do that with any UI object.
How else should I handle this?
Thanks!
I'd recommend using a UINavigationController and setting the toolbar to include your UIButton (as a UIBarButtonItem). If you have any trouble "keeping track" of the toolbar or button you can subclass UINavigationController, add the UIButton (or entire toolbar) as a property of the subclass, and access it from any subsequent view through the self.navigationController property (might violate strict OO, but you could use a protocol).
As for the popover, I think you're OK on iPad but not on iPhone. There are custom projects on github to implement UIPopoverController, and indeed the Facebook app makes use of a custom popover for notifications in their app. iPhone raises an exception if you try to show a UIPopoverController.

Resources