I've implemented UINavigationController in my iphone application as main navigation interface.
When I need to add some new xib to my UINavigationController stack I have to write new method like this (example for ContactsView.xib):
- (void) switchToContactsView
{
// lazy load
if (self.contactsViewController == nil)
{
ContactsViewController *contactsController = [[ContactsViewController alloc]
initWithNibName:#"ContactsView" bundle:nil];
self.contactsViewController = contactsController;
[contactsController release];
}
[navigationController pushViewController:contactsViewController animated:YES];
}
The problem is, I have lots and lots of .xib screens in my application now now and for every new screen I have to copy and paste the same code, just changing the name of method and class names in it.
Is there some more efficient way of doing this? Like maybe create some single method that accepts parameters (xib and uiviewcontroller subclass name), so I can just call it with those parameters to load new xib and switch to it. The problem is, I don't know how to pass class name to a method (eg ContactsViewController class in the example above). Any help?
- (void) switchToAViewController: (NSString *)vCName: (NSString *)nibName
{
// lazy load
if (self.toBePushedViewController == nil)
{
//Assuming all VCs are subclasses of UIViewController
UIViewController *tempViewController = [[NSClassFromString(vCName) alloc]
initWithNibName:nibName bundle:nil];
self.toBePushedViewController = tempViewController;
[tempViewController release];
}
[navigationController pushViewController:self.toBePushedViewController animated:YES];
}
Also refer to NSClassFromString returns nil
Is there a reason you have many xibs in your project ? Read the apples interface guidelines, Many new-commers to iPhone development misunderstand the rationale behind some of the interface elements.
Aside from that, if you need many xibs, but all of them have exactly the same functions consider linking the xibs to the same class file, so one controller having 3 xibs etc. that way you will only need to point to the correct xib instead of copy the whole method.
Just a thought, but please explain the reason behind having so many xibs, what is your application's purpose?
Related
I have an iPhone app with TabBar and tabs. Each tab is loaded with UIViewControllers, what I want for a particular tab is to change UIViewController associated with tab. When I call PresentViewController it changes UIViewController but also hides the TabBar which i dont want.
Can anybody please explain what needs to be done ?
Thanks
UITabBarController keeps a collection of it's view controllers in a property aptly named viewControllers. You can modify this at runtime. There are side effects that probably are fine for your app, but read the docs to be sure.
A convenience method (and illustration of how to modify that immutable array) would look like this:
- (void)replaceTabBarViewControllerAtIndex:(NSUInteger)index with:(UIViewController *)newVC {
NSMutableArray *newVCs = [NSMutableArray arrayWithArray:self.tabBarController.viewControllers];
if (index < newVCs.count) {
newVCs[index] = newVC;
self.tabBarController.viewControllers = [NSArray arrayWithArray:newVCs];
}
}
Call this with the new vc instead of presenting it.
I am working on application for Ipad.in this application i have a UIButton on my first class Xib ,Now i want to add second class XIB in this first Class XIB on Button click.i know the how to call second class XIB.which is just like this..
-(IBAction)displaysecondclass
{
secondview *sec=[[secondview alloc] initWithNibName:#"secondview" bundle:nil];
[self presentModalViewController:sec animated:YES];
[sec release];
}
But i not want to go secondclass ,i need to display second class XIB on firstview just like this.
-(IBAction)displaysecondclass
{
secondview *sec=[[secondview alloc] initWithNibName:#"secondview" bundle:nil];
[self.view addSubView:sec];
}
can any one help me how to add second class xib in first view.thanx in advance.
change the button code to
-(IBAction)displaysecondclass
{
secondview *sec=[[secondview alloc] initWithNibName:#"secondview" bundle:nil];
[self.view addSubView:sec.view];
}
Please note that you will need to add additional functions to release the viewcontroller once you dont need it anymore
Thanx for everyone actually i am working as part time IOS programmer.All though its was not difficult task That i mention in my quesiton.i was little bit confuse when i ask this question whether it is related about Subclass or newclass,thats why i post Question.Thanx for every one to help me.now i got its solution using this link may be it help to Some one new commer.
http://www.roseindia.net/tutorial/iphone/examples/iPhone-Create-SubView.html
a quick question,
I have been dabbling with XCode off late and am trying to understand the View Controller, while I get the nitty gritty of it, one thing I fail to see is where the View Controller class object is instantiated. It is, in essence a class and hence has to have an object instantiated to be able to send messages to it.
It's kind of left me scratching my head.
Thanks much!
It is instantiated whenever it needs to be displayed. By you.
For example, if you wanted to display a new view on the navigation stack on the press of a button?
-(IBAction)buttonClicked:(id)sender{
/* Create VC here */
YourViewController *controller = [[YourViewController alloc]initWithNibName:#"ViewName"];
/* Push */
[self.navigationController pushViewController:controller animated:YES];
/* Let go since you don't have control over it anymore. */
[controller release];
}
I believe it is generally better to do this instead of holding an instance in memory in most situations, to prevent too much memory usage.
Now (assuming iOS5 is out of NDA now that most of it has been announced today), you can use Storyboarding in XCode that will handle all this for you.
The view controller is instantiated in it's init function designated initializer being the following:
-(id)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil
{
if( (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) )
{
// Custom initialization
}
return self;
}
As you will perhaps have noted in some of Apples examples or any other source code you've looked through you might have seen a line of code similar to
MyViewController* viewController = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
This is where/when the view controller gets instantiated. You'll notice that a view controller has a member object of type UIView called view it is this that gets added to the window or view that this view is to be apart of.
The view controller is created to handle messages pertaining to this view. It's all spelled out here.
I have a tab bar application with 4 different tabs.(4 different views)
When my app first launches, the first thing I need to do is bring in my data which is located in a plist. This isn't a problem. My problem is, the data is displayed in each tab in a different way.
Where do you suggest the best place to load the data is?
Currently I'm using viewDidLoad of the first viewController. But from here, what do you think the best way to make the data available to the other views is? Perhaps make the other 3 views become a delegate for the 1st view?
Any suggestions would be much appreciated
Thanks for you help.
Mike.
I don't know why each of the four views can't have a reference to the dictionary, and your application delegate loads from the plist and set the references. Is your data very large?
The little data I've had that is truly global in this way I've made a property on my AppDelegate class. Your view controllers can all access it with
MyAppDelegate* delegate = [UIApplication sharedApplication].delegate;
id thing = [delegate.myDictionary objectForKey:#"someKey"];
This is an often asked question here. You should look at the MVC design pattern. Your dictionary would be a model in this scenario and all the controllers/views that need to access it should have their own property for it. The loading can be done in another controller/view with a progress bar, in the application delegate or in the first tab; that depends on your situation.
The classes would look a bit like this:
#interface Model : NSObject {…}
- (void) load;
#end
#interface ControllerA : UIViewController {…}
#property(retain) Model *model;
#end
#interface ControllerB : UIViewController {…}
#property(retain) Model *model;
#end
#implementation ApplicationDelegate
- (void) applicationDidFinishLaunchingAndWhateverElseIsUsuallyHere
{
Model *model = [[Model alloc] init];
[model load];
ControllerA *controllerA = [[ControllerA alloc] init…];
[controllerA setModel:model];
ControllerB *controllerB = [[ControllerB alloc] init…];
[controllerB setModel:model];
[model release];
// The syntax here is probably off, you should get the idea
UITabBarController *tabs = …;
[tabs setViewControllers:controllerA, controllerB, nil];
[window addSubview:tabs.view];
[window makeKeyAndVisible];
}
I don't have any experience with Tab Bar views, but it looks like you want to create a singleton class, so that you can access your dictionary globally.
I am creating a delegate view controller and presenting it to the user to perform an action but I would like to change a NSString on the delegate view controller based on the originating view controller. For example if the delegate view controller is a delegate of viewControllerA, then display Foo, but if its a delegate of viewControllerB then display Blah. ALthough I cant figure out how to pass some sort of information that indicates what the originating view controller is. I noticed that if i do an NSLog(#"I'm from %#",[self delegate]); it will tell me what the originating view controller is, as well as the memory address, but I cant seem to translate that into an NSString object to examine its value. If theres a way to make that work, or a better way to do this then that works too...
- (IBAction)editDate {
DatePickerViewController *datePickerView = [[DatePickerViewController alloc] init];
datePickerView.delegate = self;
datePickerView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:datePickerView animated:YES];
[datePickerView release];
}
It seems like you're using some terminology in ways that are different from what most Objective-C coders would mean.
Here you're instantiating a view controller to show as a modal view. That view controller has a property called delegate that allows it to call some methods to report changes to its state. That doesn't make it a "delegate view controller", that makes it "an object with a delegate".
You happen to be using another view controller class as the delegate, but any object that implements the methods that DatePickerViewController objects want to call to report changes could be assigned to that delegate property.
I think that the question you're asking is "how do I make the DatePickerViewController display different information depending on what kind of object it's reporting to?", and the answer is much the same as "how do I make a UILabel show different text depending on the view controller that created it?"—you set properties or call methods on in when you create it.
If you really just want to pass a string to DatePickerViewController, you could add an NSString* property to DatePickerViewController and set it with arbitrary text, with
datePickerView.myString = #"some information that you want";
You could use the class of the delegate.
if([[self delegate] isKindOfClass:[ViewControllerA class]]) {
[self doViewControllerAThings];
}
else {
...
}