How the deleted xib gets loaded? - iphone

I have created a class 'abc' which a subclass of UIViewController. At the time of creating it i clicked the option for creating an xib for it automaticaly. Now the xcode creates 3 files for me
1. abc.h
2. abc.m
3. abc.xib.
Now whenever i create an object of abc class like
abc *a=[abc alloc];
Even when i am not initialising the object with initiwithNibName and using it, it is loading the xib file. So how this xib file got associated with the abc object. And even if i deleted the abc.xib, then also it loads that xib file. I couldnt understand from where it is loading the xib file, if it it not present in the project space. And where the association of xib and controller is stored?
Thanks in advance.

What's going on is that the default implementation of initWithNibName:bundle: searches the Main Bundle for a Nib file that has the same name as your View Controller class. This happens whether you select the option for creating the Nib automatically or not. See UIViewController documentation (the discussion portion of initWithNibName:bundle:).
Now the initWithNibName:bundle: method is UIViewController's default initializer, which means that even if you don't use it directly (say that you use init instead) it will get called under the hood anyway.
Finally, even if you delete the Nib file from XCode, for some reason (not sure why) it doesn't get deleted from the Main Bundle (at least in the simulator). Even if you clean & build the project it stays there. The solution I use to get completely rid of the Nib file is to delete the App from the simulator, then clean & build again.
Hope this helps!

The xib is probably still in your compiled area, so you need to perform a clean to get rid of it fully. (Product >> Clean). The default init method of UIViewControllers will automatically look for a xib of the same name, which is why it's still allocating that xib. Once you clean it will stop.
Reference:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#//apple_ref/occ/instm/UIViewController/initWithNibName:bundle:
Note this part: 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.

Related

iPhone Obj C - change startup root class?

I am learning iPhone Obj C slowly. I have a XIB with several views and all works well. I need to have a 2nd XIB to control another set of views but haven't been able to make it work.
So I created the 2nd class and a 2nd XIB, all called one.h one.m one.xib and the same for the new one is all two.*
As it didnt work I was going try and change the app to start on the TWO class rather than the ONE class. In the plist I changed the Main Nib base file but that didnt seem to do anything.
Where do you specify what the start up class is? That way I can make sure I did everything correctly first, and then go back to the code that is supposed to call the two class and xib.
Also if anyone has any sample code to go from one class and xib to another, please let me know.
thanks!
In your AppDelegate class make sure the ViewController being allocated and set to the window is the one desired.
Your project's [ProjectName]-Info.plist file decides which Nib file is used when the application starts, in the key NSMainNibFile. (By default, this is set to MainWindow.)
A standard MainWindow.nib file will define the "root" class, which is usually [ProjectName]AppDelegate. You can, however, change this by editing the nib.
I had to set the CLASS IDENTITY to the proper class for the app delegate on the XIB for both XIB.
Then I changed the plist to point to the XIB I wanted to start as root.
Both of the answers above helped me find this.
THANK YOU

'NSInternalInconsistencyException', reason: '-[UIViewController _loadViewFromNibNamed:bundle:] loaded the GameView nib but the view outlet was not set

This is not the same situation as the multitude of other similar questions here.
* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UIViewController _loadViewFromNibNamed:bundle:] loaded the GameView nib but the view outlet was not set.'
You might be thinking "do as it says, connect the File's Owner to the View in IB!". But the thing is, I don't even HAVE a GameView.xib in my project or even in the project directory.
I do have a "GameViewController.m" and matching "GameViewController.xib" in my project. Using that GameViewController is what brings up this error, but I don't understand where it gets the idea to try and load "GameView.xib". Shouldn't it use "GameViewController.xib" instead?
If I grep my project directory, I do see it referenced from "UserInterfaceState.xcuserstate".
<string>file://localhost/Users/bemmu/Dropbox/b2/iphone/ValleyStory/ValleyStory/GameView.xib</string>
This mentioned file does not exist. I might have had a file with that name before and renamed/deleted it, but it's not being referenced to from anywhere that I can see in IB.
Did I manage to confuse xcode?
My solution was a little different.
Click on the xib in interface builder
Select File's Owner on the left
Open the File's Owner's connections inspector
If the view property isn't yet wired, control-drag it to the view icon (under the file's owner and first responder icons).
Check any nib files you're using (like MainWindow.xib). If you are loading GameViewController from a nib, check the file it's loading from (under the info tab in the inspector). Make sure it's set to "GameViewController" and not "GameView".
I had this issue as well, but had to solve it a different way. Basically, I have a view controller name MainViewController, which has a xib named MainViewController.xib. This nib has it's view property set to the File Owner which was MainViewController.
I also made a MainView.xib that contained a view that was going to be programmatically added to the view defined in MainViewController.xib and it's view. It basically encapsulated an internal view that would be in the MainViewController.xib's view, and also had it's File Owner set to MainViewController.
So basically, I wanted MainViewController.xib to load as the nib for the MainViewController object, and inside MainViewController, at some later point, I would add the internal view specified by MainView.xib.
A couple issues arose:
1.) I found in the Apple docs that when loading a view controller via storyboard or nib:
"If the view controller class name ends with the word “Controller”, as
in MyViewController, it looks for a nib file whose name matches the
class name without the word “Controller”, as in MyView.nib.
It looks for a nib file whose name matches the name of the view
controller class. For example, if the class name is MyViewController,
it looks for a MyViewController.nib file."
Therefore, you cannot have a nib called MainView.xib if you also have a nib called MainViewController and want MainViewController.xib to be the primary nib for MainViewController.
2.) Even if you delete MainView.xib or rename it to something else (MainInternalView.xib in this case), you MUST delete / clean your iOS simulator as the old nib file (MainView.xib) will still remain in the application. It doesn't overwrite the whole application package when you rebuild / rerun your application.
If you don't want to reset your content settings (perhaps you have some data you want to preserve), then right-click on your application in your iOS Simulator folder, Show Package Contents, find MainView.nib, and delete it. Xcode will NOT do this automatically for you when you rebuild, so we need to manually remove the old nib.
Overall, don't make nibs named MainViewController and MainView, i.e. nibs with the same prefix. Call MainView.xib something else, like MainInternalView.xib.
I recently solved this issue. Make sure you back up your project before following the steps given here (just in case). These steps solved my issue
Quit Xcode
Navigate to UserInterfaceState.xcuserstate located at .xcodeproj/project.xcworkspace/xcuserdata/<username>.xcuserdata and delete the file.
Reopen Xcode. Xcode will create a new UserInterfaceState.xcuserstate which will be clean.
In my case this error was produced by dumb mistake - I delete _view view
In my case, I was not using a xib at all. I needed remove the .m file from Build Phases > Compile Sources and added it back.
Given you referenced it previously it sounds like xcode hasn't ackowledged it no longer exists. From the Product menu select "Clean" and then "Build" hopefully this will get past the old reference for you.
Face the same Problem, had to change the view's name in code:
MyViewController *controller = [[MyViewController alloc] initWithNibName:#"WrongViewName" bundle:nil];
To
MyViewController *controller = [[MyViewController alloc] initWithNibName:#"RightViewName" bundle:nil];
I had multiple views, and by accident (I don't know how this happenned) but my background view didn't have a file owner, so for anyone else who has this problem in the future, make sure all your views have a file owner.
I was gettint the same error then check the classname from interface builder and see that I typed the view controller class name at the custom class attribute.
UIViewController searches for a nib with the same name as the controller when passed nil to initWithNibNamed:bundle: Check that the file name that you pass to the initializer is correct and exists!
For example:(e.g. [[CCVisitorsController alloc] initWithNibName:nil bundle:nil] then UIViewController tries to load nib with name CCVisitorsController as default.
If that file does not exist then the error you mentioned is thrown.
I had this problem because I was doing something bad in
(id) initWithCoder:(NSCoder *) coder
which the NIB loads.

was unable to load a nib named "TwitterDrilldownView"

-[UIViewController _loadViewFromNibNamed:bundle:] was unable to load a nib named "TwitterDrilldownView"
I get the above error when I push a new ViewController onto the navigation stack. This is the push code,
[self.navigationController pushViewController:[[[TwitterDrilldownViewController alloc] initWithTwitterAnnotation:temp] autorelease] animated:YES];
Basically I am just pushing a newly allocated and initialized view onto the stack. The init method of the ViewController is,
- (id)initWithTwitterAnnotation:(TwitterInfo *)aPOI {
if(self = [super init]) {
poi = aPOI;
}
return self;
}
As you can see I do not use any initialize with nib method and there is no nib file named TwitterDrilldownView in my project.
I did have a nib file before I created the TwitterDrilldownViewController called TwitterDrillDownView but I was using it to test a layout and, again, never used it. When I created TwitterDrilldownViewController the TwitterDrillDownView.nib was present in the project and it was after this stage that I deleted the nib.
The only cause for this problem that I can think of is that Xcode somehow created a dependency on the nib file because the nib file and view controller are named the same(TwitterDrilldownView.nib, TwitterDrilldownViewController.m), as if it was trying to be helpful but is ultimately messing up my project.
I have tried deleting and recreating the view controller in the hope that any references will be destroyed, and removed any reference to nib files in the project but to no avail.
Has anyone please got any experience with this problem or know a possible solution?
This also happened to me after deleting a XIB file out of my project. However, I did some messing around and was able to resolve the problem.
The key point is that Xcode seems to keep some kind of reference somewhere as you create XIBs and outlets/actions within them, and deleting a XIB file manually simply orphans these references. Removing these connections one-by-one, using the interface builder (UB) and the XIB seems to de-reference them properly.
The solution is then pretty clear:
Re-create a XIB file of the same name and similar construction (including the outlets and actions you had before). (Note: If you can't remember how to re-construct the XIB's outlets and actions, just re-create the XIB file with the same name and skip to my 'if it's still failing' note below.)
Manually, one-by-one, remove all of the outlets and actions in your XIB using interface builder (IB).
Re-build the app; if it works now, you can delete the XIB.
(Note: If it's still failing, you will probably have a different error. If the error refers to key-value compliance then it will list a method in the error - and that method is your problem. Make sure you recreate the named outlet/action in IB, and remove it manually using IB. That seems to de-reference the call in Xcode/your build environment.)
Happy hunting!
UIViewController should be initialized using initWithNibName:bundle: method. In its description stated:
This is the designated initializer for
this class.
If you specify nil for the nibName
parameter and do not override the
loadView method in your custom
subclass, the default view controller
behavior is to look for a nib file
whose name (without the .nib
extension) matches the name of your
view controller class. If it finds
one, the class name becomes the value
of the nibName property, which results
in the corresponding nib file being
associated with this view controller.
So if you do not load you view controller from nib file make sure you override loadView method and set controller's view property in it.
Hope that will help.

What are the differences between Xcode generated .nib/.xib and interface builder .nib/.xib template?

I am new to iPhone development so I have been working through some tutorials. What I don't understand is how xib fit into the work flow.
In a tutorial, one of the instruction is to create a new UIViewController subclass with "XIB for User Interface" selected. On my first try, I neglected to check that option and I thought may be I can just create the xib in Interface Builder but that didn't work. ( I created the xib using Cocoa Touch View Template, with the same name as the UIViewController and saved it the into project directory so it was added to the project.) I even changed the Class Identify for the File's Owner and hooked up the view outlet (the two differences I noticed when I inspected the xib generated from Xcode.)
So what are the differences between Xcode generated .xib (from UIViewController Template) and the IB .xib template?
XIB files created as part of the New File flow in Xcode have their File's Owner class pre-set, as well as certain outlets (view) already connected. Otherwise, there's not much difference.
The XIB File is basicly an uncompile NIB File, XIBs can always be edited in Xcode (unless they are outdated or corrupt) but most NIBs are compressed (flat) and are unopenable. However the older NIBs are bundles containing some source/archived including designable.nib which is often just the renamed XIB File and a keyedobjects.nib which is an other compiled NIB
NIB = Nxt Interface Builder
XIB = Xml Interface Builder
Although the new archived NIB files are unopenable to most applications including Xcode, they can still potentially be unarchived. I found this freeware application called NibUnlocker On The CharlesSoft Website which can potentially disassemble a compressed Nib file and exports it as an XIB document. This application is still fairly buggy but it is sometimes very accurate based on the Nibs contents.
(NibUnlocker is a very inaccurate name, Nibs are not locked they are archived)
Click to Download Nib Unlocker
If You wish to know a bit more you can read some additional information I have provided below in regards to the NIB and XIB Formats:
Nxt Interface Builder Anatomy:
Archived NIBs
A Compressed NIB file is complicated file to analyse but this is not impossible. The structure of these files are based off of a compacted property list (begins with "bplist00") and some of its contents are archived through NSKeyedArchiver. Since a NIB is formatted as a property list, This allows a small hack: if you actually change the extension of a Nib to .plist, eg. ArchivedNib.nib to ArchivedNib.plist You will actually be able to open it in Xcode viewing it as a Property List. When you view a Nib as a property list you will probably get a few base properties such as $version, $objects, $archiver and $top.
Useful Notes
A CFKeyedArchiverUID object is actually a redirector, in the {value = xx}, the value is an offset for a item in the $objects array from the start of the array. eg. <CFKeyedArchiverUID 0x60800002bc20 [0x7fffef6b8c30]>{value = 29}, value = 29, the result would be the 29th item in the $object's array. In Objective C you can retrieve this value from an NSArray with this method :
+ (NSUInteger)valueForKeyedArchiverUID:(id)keyedArchiverUID {
void *uid = (__bridge void*)keyedArchiverUID;
NSUInteger *valuePtr = uid+16;
return *valuePtr;}
like if this helped ;-)
I'm not sure I'm following your question. When you created a xib file in Xcode, attempting to edit the xib file will bring up IB. So effectively you are using IB to edit the xib file in Xcode. I never tried creating a "stand-alone" xib file in IB and then hook it up to a project in xcode.
The only reason such an approach may not work is that when you create the xib file within the context of a project, there are associations created (such as "mainnib file base name" attribute in the plist) which will not be automatically generated when you attempt to use a standalone xib file with the xcode project.
It sounds like you configured the view xib properly, by setting the View outlet and configuring the custom class for File's Owner, but perhaps the problem was with the UIViewController subclass.
If your view controller subclass had implemented the -[UIViewController loadView] method directly, it'd prevent the NIB from loading. In the default implementation, the UIViewController will load the NIB file with the same name as the view controller. If you override this method to initialize the view a different way (e.g. completely programmatically), the default implementation that loads the NIB won't run.
Deleting an override of the -[UIViewController loadView] method in your subclass, or ensuring the names match, might resolve any discrepancies.
XIBs are XML. Diff them and find out for yourself.

How can I make an view-based application that does not use a nib file?

I've choosen the "view-based" application template in Xcode. The myProjectViewController.m has the following code:
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/
That sounds good. But: The template generated a myProjectViewController.xib file. What I dont get is: How does Xcode connect the ViewController with that nib? Where's the part in the template code that says: "Hey, load that myProjectViewController.xib now!"? I mean... can I just delete that not-wanted nib file without setting anything else up appropriately?
You may wish to refer to my answer to this question, where I describe the specific files that need to be altered to do completely programmatic generation of your view hierarchy.
Also, some of the references linked to in the answers to this question may be of use to you.
yep you can just delete the nib and implement that method
IB connects using the name of the class in the NIb, in IB you actually set a view as the file owner of the view. so when you call initwithnib:"nibfilename" it knows what you are talking about.
The elements are wired up using IBOutlets and IBActions