I'm developing an iOS 4 application and I have developed some classes that I want to use in others projects.
One of this classes, called MapViewController, is a UIViewController subclass. This class uses a XIB file that I've created with interface builder.
I'm wondering if a use MapViewController in another project as a super class from a new class, How can I use it associated XIB?
I want to reuse MapViewController and its XIB, but I don't know if I have to do something special with the XIB file.
I don't know how to explain this. If you need more details, please tell me.
UPDATE:
I want to create a new class that inherit from MapViewController, like this:
...
#interface NewMapViewController : MapViewController {
...
And, now if I want to continue using the same XIB (the one from MapViewController), what must I do?
Since you are gonna inherit from MapViewController, your MapViewController becomes the super class. And you also have MapViewController.xib. It seems pretty straightforward to me if you use the initializer for NewMapViewController
NewMapViewController.m
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
NSLog(#"Subclass initWithNibName called");
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
Initialize your NewMapViewContoller like:
//Nib of super class is MapViewController
NewMapViewController *nmapController = [[NewMapViewController alloc] initWithNibName:#"MapViewController" bundle:[NSBundle mainBundle]];
Related
Here is my problem:
I have a basic application with a UIViewController embedded in a NavigationController. It is also the RootViewController of the application. From there I have a push segue to a normal UIViewControllerand a second push segue to a UITableViewController with its own UIViewController for the detailed view.
In the root view there is an instance of the class whose purpose is to send message with a define protocol.
In the table view the user will select the type of message he wants to send and in the detail view the content of that particular type of message.
Now the user has specified everything and I want him to push a "send" button. That button must do two things: pop back to the root view and send the user defined message by the protocol class instance.
I can do the pop back just fine with:
[self.navigationController popToRootViewControllerAnimated:true];
but I have no idea how to send the message (a class instance) back to the root view. The application is still fresh so I can completely change the structure if this one is not correct.
The best for me would be to access the protocol class instance from everywhere (I will need it in the other UIViewController) but I am not sure how to do that so that's why I thought of sending the message back to the root view.
If you know how to do one of the two above please give me a hand!
Cheers.
EDIT: Technically the NavigationController is the initial ViewController so I am not really sure who is the RootViewController anymore.
First: You could do: (only works when your view has been added to a the window)
[self.view.window.rootviewcontroller doSomething];
Second option is to define a property on your appDelegate:
#property (nonatomic, strong) UIViewController *root;
And call it through:
AppDelegate *appDelegate= (YourAppDelegateClass *) [[UIApplication sharedApplication] delegate];
[appDelegate.root doSomething];
you can Create an application object and assign the message to it. and use it on your root view controller. if i understood your question correctly this might help.
You could try:
UIApplication *myApp = [UIApplication sharedApplication];
UIWindow *frontWindow = [myApp.windows lastObject];
UIViewController *myRootViewController = frontWindow.rootViewController;
You Can also send Notification whenever you move to root view controller
by adding observer to it.
one way is to use protocol and other way is to pass your root view controller instance to your tableviewcontroller(via view controller) using your custom init method like:
UIViewController.m
- (id)initWithRoot:(id)rootInstance
withNibNameOrNil:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
self.root = (RootView *)rootInstance;
}
}
RootViewController.m
viewcontrollerInstance = [[viewcontroller alloc] initWithRoot:self withNibNameOrNil:#"viewcontroller"
bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:viewcontrollerInstance animated:YES];
UITableViewController.m
- (id)initWithRoot:(id)rootInstance
withNibNameOrNil:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
self.root = (RootView *)rootInstance;
}
}
ViewController.m
tableViewInstance = [[tablecontroller alloc] initWithRoot:self withNibNameOrNil:#"tablecontroller"
bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:tableViewInstance animated:YES];
UITableViewController.m
now on table view controller use your root instance(come from view controller) to call the function of root view controller like:
[self.root displayMessage:message];
sorry for the typo. hope this will help.
I have been trying for a while now, but I can't figure out how to integrate InAppSettingsKit in an App, that uses Storyboard and a TabBar.
I've got my tab bar defined in a Storyboard, now I want one tab to have this InAppSettingsKit as the root view. Is this possible after all?
Thanks everyone.
Well, after trying various things, I figured out, that my problem actually was, that I put all the IASK-stuff into a static library (and I had no Settings Bundle). After moving all the code and nibs to the same project as the MainStoryboard, it worked by adding a TableView Controller to my storyboard and settings its custom class to IASKAppSettingsViewController.
Alternatively, if you want button handlers and other custom code, do following:
Create a class derived from UITableViewController
Modify the header file to derive from IASKAppSettingsViewController
<IASKSettingsDelegate> Remove all methods but the initWithCoder and the
settingsViewControllerDidEnd protocol (or make calls to super). This
is so that the default UITableVC code doesn't override IASK
functionality. Be sure to stick self.delegate = self; into the
initWithCoder to get the buttons to work.
//SettingsViewController.h
#import "IASKAppSettingsViewController.h"
#interface SettingsViewController : IASKAppSettingsViewController <IASKSettingsDelegate>
#end
//SettingsViewController.m
// ...
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
self.delegate = self;
}
return self;
}
#pragma mark -
#pragma mark IASKAppSettingsViewControllerDelegate protocol
- (void)settingsViewControllerDidEnd:(IASKAppSettingsViewController*)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
Set custom class of the table view in storyboard to
your class
I have a question regarding how to pass around NSManagedObjectContext. In my app, it seems like it's my AppDelegate that handles NSManagedObjectContext, so I shouldn't create other NSManagedObjectContexts in my other ViewControllers.
So the question is...
There is any convention or smart method to do this?
Thanks.
The way I pass the NSManagedObjectContext is to simply have an iVar in each view controller you pass it to. I usually modify the initialiser to include assignment, something like this....
MyNewViewController.h
#interface MyNewViewController : UIViewController {
NSManagedObjectContext *managedObjectContext;
}
...
MyNewViewController.m
#implementation MyNewViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andContext:(NSManagedObjectContext *)ctx {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
managedObjectContext = ctx;
}
return self;
}
....
Then when you call the view controller, you simply use the modified initialiser. Like...
MyNewViewController *nv = [[MyNewViewController alloc] initWithNibName:#"MyNewViewController" bundle:nil andContext:self.managedObjectContext];
Now you've got a reference to the managedObjectContext which you can use within your view controller.
I make all my controllers in code and most of the GUI too. Some GUI's I make with IB. I then set the file's owner to the viewcontroller and drag an connection from the file's owner to the view. But initWithNibName confuses me...
I am override the designated initializer to this
- (id)init {
[super initWithNibName:nil bundle:nil];
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
return [self init];
}
Why do I not need to set which nib the viewController shall use in the init-initalizer? Because it works without. I thought I must use [super initWithNibName:#"SomeNib" bundle:nil];
In the init-initalizer
From docs: If you specify nil for the nibName parameter, you must either override the loadView method and create your views there or you must provide a nib file in your bundle whose name (without the .nib extension) matches the name of your view controller class. (In this latter case, the class name becomes the name stored in the nibName property.) If you do none of these, the view controller will be unable to load its view.
It works without only if your nib name is the same as your controller class name. In that case Apple does some magic. It is generally good form to specify the nib name.
I need to create my own UIView class and it is not something I have had to do. I created the class, then laid out the small view in IB (it's just a few labels that i will later need to add data to ). but now im stuck on how to actually put an instance of it in my main view. Can someone point me in the direction of a good tutorial? The closest thing I have done to this is creating a custom tableViewCell.
DataTagViewController.m:
- (id)initWithNibNamed:(NSString *)DataTagViewController bundle:bundle {
if ((self = [super initWithNibName:DataTagViewController bundle: bundle])) {
// Custom initialization
}
return self;
}
MapView.m:
DataTagViewController *dataTag = [[DataTagViewController alloc] initWithNibNamed:#"DataTagViewController" bundle:nil];
[theMap addSubView: dataTag.view]; <<< this line causes the crash (theMap is a UIView)
I now get this runtime error when adding the subview:-[UIView addSubView:]: unrecognized selector sent to instance 0x470f070'
2010-06-06 21:22:08.931
UIViewController is not a view, but controls a view. If your DataTagViewController class extends UIViewController, then you'll want to add it's view, not the class itself:
[theMap addSubView:dataTag.view];
Also, do you have a DataTagViewController.xib file created that has your view in it? If you don't, you'll need to create one and use the UIViewController's initWithNibName:bundle method. Otherwise, you'll have to implement the loadView method instead to provide your own view via code.
Edit
Your init function is using the name of your class as a variable. That probably won't work. Use the default sigature:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
{
}
}
If you aren't doing anything beyond the init function, you don't need to implement this method. Your alloc/init statement is enough.
For a good tutorial, read the View Controller Programming guide in the docs.
What is the parent class of DataTagViewController? You say you need to create "my own UIView class", but your example suggests that you actually want to create UIViewController subclass. initWithNibNamed: is UIViewController method. If your parent is UIView, then "unrecognized selector" makes sense.