StoryBoard and initialization - ios

Question: How do I perform custom initializations when using StoryBoards?
I have read several questions with the same keywords that are in my title, but could not find any answer. I beg your pardon if this question has already been asked or it is too basic: I have just started developing iOS apps.
Currently I have an application whose:
AppDelegate reads from a source (currently a remote URL) two URLs that need to be displayed in instances of UIWebView;
main controller is a TabBarController with two tabs, that are instances of UIWebView;
the two UIWebView have methods (init and setter) for receiving the URL of the file they need to display. These two UIWebView display the URLs read by the AppDelegate.
I am trying to perform the same operations using a StoryBoard but do not know how to pass the URL of the content to the two UIWebView. I have read the answers concerning the initWithCoder method, but cannot figure out how to pass the parameters.
Is there anyone who figured out what I meant in my (incredibly confused) question who is also able to help me?

I think the right place to do this is your ViewController. You should create an outlet of the UIWebView within your ViewController in order to be able to access them. Then to pass the URL to them you can use:
- (void)loadRequest:(NSURLRequest *)request
I don't understand why you read remotely the URLs in your AppDelegate but you can access your AppDelegate from your ViewController if needed as follows:
[[UIApplication sharedApplication] delegate]

On the general question of accessing references to view controllers in a tab bar controller...
A tab bar controller has a public property called viewControllers, which is an array of view controllers which the tab bar controller contains.
You can access elements of this array just as you would any other array, but in this case, they're references to all your view controllers.
[tabBarController.viewControllers firstObject];
[tabBarController.viewControllers objectAtIndex:3];
for(UIViewController *vc in tabBarController.viewControllers) {
if([#"MyFirstVC" isEqualToString:vc.title]) {
// do stuff
}
}
etc. etc. etc.

Related

How to find Instance of View Controller made by storyboard

I am trying to make a tabbed application in Xcode that allows the user to take a photo and edit it on the FirstViewController class and when they are done display it on the SecondViewController.
When I started the project, Xcode automatically made the two viewControllers for me in the storyboard. What I need now is to find the instance of the second viewController that was generated so I can call a method and pass an argument (the UIImage) from the first view controller to the second like this.
FirstViewContoller.m
-(void) passImageToSecondVC (UIImage *) img
{
[<instanceOf_SecondViewController> receiveImg: img];
}
SecondViewContoller.m
-(void) receiveImage (UIImage *) img
{
//Code to display the image received
}
What Im asking is how can I find the name of the instance of the SecondViewController (shown by <> in the example code) generated by Xcode so I can call this method.
Although I'm very close to just doing this programmatically which I find much easier I wanna learn how to do this through the storyboard also I'm very open to hear other solutions to this problem. Thank you!
There's no way to do this through the storyboard. You don't access the view controller by its name. Each view controller has access to the tab bar controller through self.tabBarController. You can access individual controllers from the tab bar controller's viewControllers array. So, to get a reference to the controller in the second tab, you would use self.tabBarController.viewControllers[1].
Use delegates pattern.
Make one vc be a delegate of the other vc and communicate data between them. I think It's a common scenario.
https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/Delegation.html

How to pass data between viewcontrollers in tabbed applications?

I have found 2 methods but am wondering if there's a better solution with xcode 5.
How to Pass Data Between iOS Tab bar Using Protocol and delegate
Xcode: Storyboard Tabbed Application Passing Data Back and Forth
Tried printing a NSLog in prepareForSegue but it doesn't even get called?
What is the current best practice to pass data between viewcontrollers for tabbed applications using storyboard and with io6 support?
Have a look at this question: iPhone: How to Pass Data Between Several Viewcontrollers in a Tabbar App
Also the imho cleanest way is to use the NSNotificationcenter. It's simple: How to use NSNotificationcenter
singleton is a good idea. You can also do it by using AppDelegate. If your data is not huge you can store your data in AppDelegate and access those from any viewcontroller.
I have used delegate approach from 1. I wanted to pass data between third and second view controller so I just added this into third view controller viewDidLoad to catch if user goes to third tab after the tab bar starts in the first view controller
SecondViewController *svc = [self.tabBarController.viewControllers objectAtIndex:1];
self.delegate = svc;

Using a UINavigationController for a set path without Back options

I am using a UINavigationController within my app (as expected) for a specific path the user takes when taking a turn in my turn based game.
When they move through the turn controllers they do not actually have the option to go Back from the Navigation Controller. This is planned/expected behaviour.
My question is, is it best to keep the other controllers on the UINavigationController stack when they are not going to be used again.
Should they be de-alloced immediately, or wait for the whole turn to be complete and let them go when the navigation controller goes (how it is at the moment). Some of the controllers hold data/images etc as properties so I am wondering if it would be more efficient to get rid of these on the fly?
If it is, what is the best method to load new controllers into the UINavigationController at present I am using self performSegue... or buttons that push to the VC from the storyboard setup.
You can manipulate navigation controller viewControllers using this code
NSMutableArray *viewControllers = self.navController.viewControllers;
//remove or add in the array
[self.navController setViewControllers:viewControllers];

Stacked UINavigationController

I'm new in iOS and I'm working with Storyboards.
I have an application with some views.
My rootViewController (1) is a UINavigationController that connects to other views. At one point in the application (2), I include a component (SWRevealViewController, Facebook Side Menu Style) that is an instance of UINavigationController, so I have two UINavigationControllers nested within each other. I want to remove or change the first UINavigationController by the new one (2), and just have only one. All views are accessed via custom segues.
Detailed Image Here
I think the solution is to change the rootViewController before loading the view (2), and set the second UINavigationController as the main of the application.
Detailed Image Here
I tried to solve it accessing by:
[UIApplication delegate].window.rootViewController = myController;
but I only have nil or a empty window.
I read many post that the solution could be in my AppDelegate in the method
- (void) applicationDidFinishLaunching: (UIApplication *) application I can't understand how to apply it to my structure, because that method is called when the application is launched.
I think that my workflow application is wrong.Any feedback or help is welcome!
Thanks in advance.
It's fine to change the root view controller from another controller, but your code is wrong. It should be:
[UIApplication sharedApplication].delegate.window.rootViewController = myController;
If you're doing this action from a controller whose view is currently on screen, you can do it this way instead:
self.view.window.rootViewController = myController;
This should work as long as myController has been properly instantiated.
You could possibly remove (1) or off load it into another view controller that is hidden and once the user goes back to a point where you want (1) back you can load it back in. This could be done in the - (void) applicationDidFinishLaunching: (UIApplication *) application.

How to pass a managedObjectContext from the appDelegate to the first ViewController when their is a navigation controller between the two views

I've been beating my head against the keyboard for a better of 3 days now in researching and trying to figure out how i can solve the following problem.
I have a story board that looks like this:
Initial app launch arrow -> to a Navigation Controller -> to the Main View Controller.
My appDelegate is creating the managedObjectContext and it populates some entities with data (for testing purpose only atm, it will be removed once I'm ready to integrate with an outside source). This work fine. Now my problem is that I don't know how i can pass the MOC from the appDelegate to my first ViewController because the Navigation controller is in the way. My current code in the appDidFinish Method looks like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Pass the managed object context to the root view controller
MainMenuViewController *rootView = (MainMenuViewController *)self.window.rootViewController;
rootView.managedObjectContext = self.managedObjectContext;
//My actual Core data setup and adding data to it, it works I've tested it.
return YES;
}
Now my code works when I change where the app launch arrow in the storyboard to point to my mainMenuViewController, but than I do however lose my navigation bar in all my views. I also know how to pass the MOC from my mainMenu to another view via the - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)senderbut I just can't seem to figure out how to do the initial pass from the appDelegate to the MainViewController because of the darn navigation controller being in-between the two.
I've already searched numerous threads on this site (and others) and i've only found the solution for a "Tabbed application" and others want me to serialize the object, but for my purposes I can't do that. (only a few views will receive the MOC and other will be passes data that one view has created and altered to be tailored for specific purposes in the unique views)
Any help to this nub in iOS and Objective-C is greatly appreciated. Thank you in advance.
EDIT: THe error i get is "terminating app due to uncaught exception ... [UINavigationController setManagedObjectContext] unrecognized selector sent to instance...
If you create a new application from the "Master-Detail" app template in Xcode 4.3 (and 4.2 as well, I think), with the "Use Storyboard" and "Use Core Data" options checked, you'll find the following in AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
MasterViewController *controller = (MasterViewController *)navigationController.topViewController;
controller.managedObjectContext = self.managedObjectContext;
return YES;
}
This seems to be exactly what you're looking for. The key bit is that you can query a navigation controller for its view controllers.
If the NSManagedObjectContext was setup in AppDelegate, you don't pass it; rather, you create a reference to it:
AppDelegate *appDel = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = appDel.managedObjectContext;
The type of object you reference it from is irrelevant, as is any other kind of object between the receiving object and AppDelegate.
In addition to my first answer, which is essentially the same as the accepted answer—except that, with mine, you can use it with or without any template (and not just the split view template)—I'm providing an answer that even more directly answers your question, and that is how to pass a reference to your context manager object to the destination view controller subsequent to a segue.
This answer, like my first one (and unlike the accepted answer), assumes that you at least know where the managed object context is in your app, and that you have the basic skills necessary to create a reference to it (unlike the accepted answer, which assumes you can't use Find... in Xcode nor can you remember how to assign a value to a pointer, such as:
id moc = [reference to the managed object context object that you can find]
Since you seem to respond better to answers that involve a template, try the prepareForSegue method override provided in the UIViewController subclass in the Single Application View template. Inside, you will note a couple of comments left there by Apple.
In short, you will create a reference to the destination view controller like this:
SecondVC *vc2 = segue.destinationController;
Then, you set the value of the pointer reference to the managed object context variable in the destination view controller to the value of the point of reference to it wherever the instance was created:
vc2.mbo = AppDelegate.mbo;
I provided a really thorough example (with a video demonstration) of creating segues without storyboards (i.e., programmatically) at:
Set segue identifier programmatically
By the way, if you're having difficulty with understanding the use of the AppDelegate reference in my answer, I'll explain it:
Apple puts its Core Data managed object context reference in AppDelegate.h/.m whenever you create a new project using any Xcode template, and also check the Use Code Data checkbox during template setup. To use that reference throughout the app (i.e., within other .m files, and so you don't in advertently create multiple instances of it), you create global, application-wide reference to AppDelegate—which happens to be a delegate of UIApplication, which is a singleton, making AppDelegate a singleton, too—by merely adding this to every implementation file in which you intend to reference the managed object context:
import "AppDelegate.h"
define AppDelegate ((AppDelegate *)[[UIApplication sharedApplication] delegate])
Now, you access the managed object context object anywhere these two lines are added:
[AppDelegate.mbo...];

Resources