Second UITabBar - ios

I already looking since a hour for a solution of my problem.
A picture can tell more then thousand words:
I have two TabBars in my ViewController. The first one I created with the storyboard, and it works. Now I would like to have the second one to select the type of connection. Because every connection type has some own things to fill. I just drag and drop a new UITabTab into my ViewController, added a third TabBar item but I don't know what is next. How to handle the second TabBar. What methods do I need? How to catch touches on this items, so I can change a view?

You're using a UITabBarViewController or a UIViewController? I suspect the first is the case and you don't know how to hook up two of the same to one ViewController. What you need to do is to take apart the delegate methods for the UITabBar so you can do it twice in the same controller.
You should do the following:
Use a regular UIViewController
Drag two UITabBars onto the View
Connect them to your ViewController
Create two implementations of the UITabBarDelegate for each UITabBar in separate classes
At viewDidLoad or a similar event create instances of those classes and set the "delegate" of each UITabBar to that instance
Some example code
First create a new class for the bar on top. It only needs to do one thing:
#import "LVDTopTabDelegate.h"
#implementation LVDTopTabDelegate
// This is the only required part of the delegate
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item;
{
// Handle what you wanted to do
}
#end
The second one is more or less the same
#import "LVDBottomTabDelegate.h"
#implementation LVDBottomTabDelegate
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item;
{
// Handle what you wanted to do
}
#end
You viewDidLoad should look approximately like this:
#implementation LVDViewController
- (void)viewDidLoad;
{
LVDTopTabDelegate *topTabDelegate = [[LVDTopTabDelegate alloc] init];
self.topTabBar.delegate = topTabDelegate; // self.topTabBar is an IBOutlet for your tab bar
LVDBottomTabDelegate *topTabDelegate = [[LVDBottomTabDelegate alloc] init];
self.bottomTabBar.delegate = bottomTabDelegate;
}
#end

Related

Is it possible to design like three layouts in iOS devices (both iPhone and iPad also)like in the attached picture (for reference see the pic.)?

Three Column(i.e Three Table Views in each Column) UI Design View.
To design the UI on the both iPhone and iPad is possible like 3 column of different tableviews
And among all of columns there is also need interaction like when ever one cell selected in the first tableview then corresponding cell details need to display in the middle table view.(Like Split View Controller.)
And, finally in third table view controller need to display some retailer names too.
Yes, it is possible to create as shown in the iProSoccer app screenshot below. Selecting a plan on left table shows the drills in the middle column. The right column contains the available drills that can be dragged into a plan (middle column). This is a single view controller containing three table controllers added as child view controllers.
EDIT
Each of the UITableViewController's defines a protocol and delegate the containing UIViewController subscribes to. When an action by the user, for example, tapping a plan in the left table view, the left table view controller tells (sends a message to) the delegate (the containing UIViewController). In this example the message includes the plan that was selected. The containing UIViewController updates the center UITableViewController with the plan. The center UITableViewController then loads the details of the plan.
Snippet of (the child) PlanTableViewController.h including protocol and delegate definition:
#import "Plan.h"
#class PlanTableViewController;
#protocol PlanTableViewControllerDelegate <NSObject>
-(void)planSelected:(Plan *)plan sender:(id)sender;
// Additional protocol methods here...
#end
#interface PlanTableViewController : UITableViewController
#property (nonatomic, weak)id <PlanTableViewControllerDelegate>delegate;
// Additional properties and methods here...
#end
Snippet of (the parent) PlanningTableViewController.m including the implementation of the delegate method:
#interface PlanningTableViewController () {
PlanTableViewController *planTableViewController;
// Additional properties declarations here...
#end
#implementation PlanningTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
planTableViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"planTableViewController"];
planTableViewController.delegate = self;
}
#pragma mark - PlanTableViewController delegate methods
- (void)planSelected:(Plan *)plan sender:(id)sender {
[drillTableViewController planSelected:plan];
}
// Additional delegate methods here...
#end

ObjectiveC - [self.view viewWithTag] returning null

I am completely stumped and have been researching for days. Probably something really simple that I am missing.
I have a ViewController which contains a custom UIView called GameView, and a UIView called buttonBox which contains a "next level" button. What I am trying to achieve is when the level is completed in GameView, it fires a function in my ViewController which shows the buttonBox so the user can click the "next level" button. It simply will not work.
I have attempted this in 3 ways, neither have worked:
Creating an IBOutlet in the ViewController, connecting it to the hidden UIView (and it was definitely connected) and calling setHidden:NO.
Calling the [self.view viewWithTag:xxx] and then calling setHidden:NO.
Using hidden=NO instead of setHidden:NO.
Relevant code for ViewController as follows:
#interface PlayViewController : UIViewController
#property GameView *gv;
#property (strong, nonatomic) IBOutlet UIView *buttonBox;
-(void) showButtonBox;
#end
#implementation PlayViewController
#synthesize buttonBox;
...
- (IBAction)showButtonBox {
UIView *uiv = (UIView*) [self.view viewWithTag:999];
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"Showing box function");
NSLog(#"%#", uiv);
uiv.hidden = NO;
});
}
#end
And my custom view:
#implementation GameView
...
dispatch_async(bgQueue, ^{
_loopRunning = true;
//NSLog(#"Calling main loop...");
while ([self loopRunning])
{
...
PlayViewController * pvc = [[PlayViewController alloc]init];
[pvc showButtonBox];
...
}
#end
The thing is, the variable uiv is returning null in NSLog, which is obviously why hidden is not working, but I have no idea why. It also didn't work when I was using IBOutlet.
Also, current output from NSLog is as follows:
2015-11-24 00:18:38.612 ib[12579:1264539] Showing box function
2015-11-24 00:18:38.612 ib[12579:1264539] (null)
Thanks in advance.
Correct Answer:
The problem was that I was using StoryBuilder to build my UI, but by using the alloc init method was creating a new view controller (which is never shown) instead of correctly referencing the view controller which was being displayed. This is achieved by passing the view controller being displayed to the view in the viewDidLoad function, see below:
#implementation PlayViewController
#synthesize buttonBox;
#synthesize gv;
- (void)viewDidLoad
{
[super viewDidLoad];
gv = [self.view viewWithTag:777];
[gv setPlayViewController:self];
}
...
Man, it's simple. Let's take a look at:
#implementation GameView
...
dispatch_async(bgQueue, ^{
_loopRunning = true;
//NSLog(#"Calling main loop...");
while ([self loopRunning])
{
...
PlayViewController * pvc = [[PlayViewController alloc]init];
[pvc showButtonBox];
...
}
#end
Here we have the issue:
dispatch_async(bgQueue, ^{
I assume, bgQueue stands for "background queue", which means this is not served by the main thread (the UI thread).
Having that said, it's quite naive to expect
[pvc showButtonBox];
to work properly. Just move this code into the main thread. For instance, you can just wrap the aforementioned line of code into a dispatch_async on the main queue. That should solve your probem, if your outlets and/or tags are OK. Cheers.
[[PlayViewController alloc]init];
This creates a new instance of PlayViewController. Where have you defined your outlets and views?
In a storyboard? You can't use this initialiser - nothing from the storyboard will be picked up, you have to use a segue or initializeViewControllerWithIdentifier:.
In a xib file? Is it called PlayViewController.xib? If not, it won't be picked up by the initialiser. Plain alloc/init of a view controller will only find a nib file as described in the documentation of the nibName property.
Do you really want alloc / init at all? Do you actually want to make a new view controller, or is one already on the screen?
From your comments it seems option 3 is the right answer. The PlayViewController is already on the screen, alloc/init is creating a new instance of it, which is never being put on screen, which never loads any views regardless of storyboards or nibs.
You need to get a reference to the existing instance of PlayViewController. Without knowing the structure of your app it's not too easy to say how that's done - is it presenting the game view? Is the game view a subview of the view controller's view? You may need to pass in a reference (weak) to the game view when it is created, at viewDidLoad, or set up an outlet in the storyboard.

Executing code/triggering UI Elements between two viewcontrollers

I'm new to objective C and design patterns like MVC, protocols and so on but this is it:
I am trying to write an iOS app within two viewcontrollers: the first has a textview where the user can write into, and the second has a UISwitch that triggers on "Value changed" and saves a file.
If I toggle by hand the switch on the SecondViewController it will save the file and that's ok.
But I wish the file could be saved from the FirstView just when the user types a specific word, it auto-switches to the second view, and auto-activates the UIswitch and all the method already behind it.
I still can't get the two interfaces working this way. Thanks everybody in advance for helping. Cheers!
this is connected in SecondViewController.h in the storyboard
-(IBAction)toggleFileSave:(id)sender;
and it is implemented as usual...
#interface SecondViewController ()
#property (nonatomic,weak) IBOutlet UISwitch *mySaveFileSwitch;
#end
- (void) toggleFileSave:(id)sender {
// how do I execute this code when the user
// type a specific word in the first view??
}
Create a BOOL flag in your SecondViewController.
Set it when the specific word is typed and push the view controller.
In the viewDidLoad of SecondViewController check the flag condition.If it is set call the required method.
When the specific word is typed:
ViewController2 *viewController = [ViewController2 alloc]init];
viewController2.flag = YES;
[self.navigationController pushViewController:viewController2 animated:YES];
In your text field delegate (add one if it doesn't exist) add this method:
- (void)textFieldDidEndEditing:(UITextField *)textField {
/* at this point the user finished editing */
NSString *currentText = /* read text field value */
if ([currentText isEqualToString:/* the magic word */]) {
/* save the file, present a view controller, etc. */
}
}
Check UITextFieldDelegate to know the available methods, you may need more than one to get the desired behaviour.
If you want to load the second view controller in order to show the UI and the save the file you can do as サンディープ said in his or her answer:
SecondViewController *controller = [SecondViewController new]; /* init as usual */
controller.saveOnLoad = YES;
[self.navigationController pushViewController:controller animated:YES];
Then, in SecondViewController:
- (void)viewDidLoad {
if (self.saveOnLoad) {
/* save file in async block */
/* set switch on */
}
}
If you don't need to show the second view I'd move the saving functionality to its own class and use it from the first controller, showing just a confirmation message for instance.

What is required of me to implement to be able to add new items to a tableViewController from another viewController?

I am trying to learn iOS development but have stalled a bit so I hope that there is some kind soul here who might be able to help me in the right direction.
Let's say I have a UITableViewController that displays a number of items, consisting of a title and subtitle ( Subtitle style of a Tableview Cell). Items.m/h only consist of two properties, title and subtitle and a init method to set the properties. In my app delegate i create some default items and pass them/set them to my tableViewController's property tvc.items, which is a NSMutableArray. What do I need to do / what components do I need, to be able to add more items and then display them in my tableViewController?
I started with the following:
Added a new view controller in the storyboard
Embeddade the viewController in a Navigation Controller
Added a Bar Button Item at my Table View Controller with an identifier of add
Ctrl + drag from BarButtonItem (add) to my new view controller selected modal segue
Created a new class AddNewItemViewController
Entered this as the class under the Identity Inspector for the new view controller
I then added two Bar Button Items, Cancel and Done (with cancel and done as identifiers) in the storyboard for the new View Controller
This was followed by me adding two UITextFields, one for the Title and one for the Subtitle
Ctrl + drag from these outlets into AddNewItemViewController.m, between #interface AddNewItemViewController () ... here ...#end (so they become Private? Should I drag it here or to AddNewItemViewController.h ?, What is the standard way for doing similar outlets?).
In AddNewItemViewController I added two properties, NSString's (nonatomic, copy) * title and *subtitle which I thought would keep the input data from an intended user.
So, after this I now want do two things, and it is here as it becomes difficult (for me at least):
Making so that by clicking on Cancel, one return to the Table View controller, ie a dismissed the modal .
Adding the data within the text fields to that NSMutableArray which is the datasource by clicking Done.
So what is required of me to do the last two steps?
Where should I ctrl + drag from the Cancel and Done (so there will be actions)? I guess they must be submitted to AddNewItemViewController.m, but what must be done to dismiss the modal (by clicking on the 'Cancel') and what should be called at or performed when clicking on 'Done'?
Which or what class (es) must know about the other class?
Last but not least, what should I send in the prepareForSegue call (which I guess I will need to have to use to send the input data back to the table view controller)?
Where to start and what methods should i learn about in order to achieve my mission?
Best Regards,
Rookie
much quesetions :)
I will beginn with the close action.
Have a look at the AppleDocumentation, dismissViewController with sender self (your AddViewController).
To store your data from AddViewController to your TableViewController, it's a better way to use delegation.
AddViewController.h
#protocol AddViewControllerDelegate;
#interface AddViewController : UIViewController
#property (nonatomic, weak) id<AddViewControllerDelegate>delegate;
#end
#protocol AddViewControllerDelegate <NSObject>
- (void) addViewControllerDidFinishTakingData:(AddViewController *)addViewController withTitle:(NSString *)title andSubtitle:(NSString *)subTitle;
#end
AddViewController.m
- (IBAction)done:(id)sender
{
NSString *title = ...;
NSString *subtitle = .. .;
[self.delegate addViewControllerDidFinishTakingData:self withTitle:title andSubtitle:subtitle];
}
TableViewController.m
#interface TableViewController ()<AddViewControllerDelegate>
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"yourIdentifier"])
{
AddViewController *addViewController = (AddViewController *)segue.destinationViewController;
addViewController.delegate = self;
}
}
Last but not least to implement your new delegate-method
- (void)addViewControllerDidFinishTakingData:(AddViewController *)addViewController withTitle:(NSString *)title andSubtitle:(NSString *)subTitle
{
// handle your data here (store to array)
// reload your table
}
Better way, to create a Class (Model) for every entry.
The simplest thing to do would be to assign tvc.items to the destinationViewController's property during prepareForSegue.
You are correct in thinking that the Cancel and Done buttons belong to the AddNewItemViewController.
In the action for Done, you could add the new item to the items array you passed in during prepareForSegue, then in the presenting view controller (the one you launched the modal from), during viewDidAppear just reload the table. It'll be called when the modal disappears.

How to ensure a UIView has loaded?

This may sound silly, but read on...
I want to set the text of a UILabel from outside of a UIViewController that is instantiated by a storyboard. I need to make sure that the label property of the view controller is set when I set its text otherwise the label's text won't be set(because it won't be loaded yet to receive a text value).
Here's my current solution:
// Show pin entry
if (!self.pinViewController) {
// Load pin view controller
self.pinViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"pinScreen"];
self.pinViewController.delegate = self;
if (!self.pinViewController.view) {
// Wait for pin screen to fully load
}
[self.pinViewController setMessageText:#"Set a pin for this device"];
}
Initially I had a while loop that looped until the value of view was not nil, But it seems the very act of checking the view loads it(as mentioned here: http://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006926-CH3-SW37)
I tried using the isViewLoaded method with no success. It just looped forever.
I've gone forward with the above code as my current solution, but it feels wrong.
Is there a better way ensure a UIView has loaded?
I want to propose an alternative way where you don't have to rely on the availability of the view.
If you need to wait for the view to load before you can call other methods on your viewController you break encapsulation, because the viewController that calls your PinViewController has to know about the inner workings of your PinViewController. That's usually not a good idea.
But you could save objects like NSStrings in the PinViewController instance, and when the view of the PinViewController will appear you set its views according to the properties you have set before.
If you need to change the text of an label from outside your viewController you can also create a custom setter that sets the label.text for you.
Your .h
#interface PinViewController : UIViewController
#property (copy, nonatomic) NSString *messageText;
// ...
#end
And your .m
#implementation PinViewController
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.messageLabel.text = self.messageText;
}
// optional, if you want to change the message text from another viewController:
- (void)setMessageText:(NSString *)messageText {
_messageText = messageText;
self.messageLabel.text = messageText;
}
// ...
#end
viewDidLoad should solve this I guess.
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html
I would rather see you change your logic and do it the way that #MatthiasBauch shows in his answer. However, to answer your actual question, you can simply set a view property in order to force it to load:
self.pinViewController.view.hidden = NO;

Resources