I have an old project in Xcode and I want to change the RootViewController files (.m, .h, .xib - a TableViewController) with a normal ViewController!
Is it possible or I must restart a new project and import the old files?
Depends on how your project is set up. But you may just need to include and change the controller linked to by the window and app delegate in your MainWindow.xib file.
Related
I'm new to macOS programming and recently I started working on this project. Because I needed to share my ViewController and view with my Safari extension target, I ended up setting the view controller manually in AppDelegate:
let application = NSApplication.shared()
let initVC = ViewController.viewControllerWithNib()
let window = application.windows.first!
window.windowController?.contentViewController = initVC
window.contentViewController = initVC
window.makeKeyAndOrderFront(nil)
I just left Main.storyboard to include the application portion since I couldn't figure out how to remove the storyboard and just use a xib as a startup for my application. Curently, I'm getting the following warning:
Window Controller requires a content view controller, main.storyboard
I'm trying to figure out why the app is giving that warning and what's the way to get rid of it.
You should see the info.plist, I remember there is a need to delete the name NSMainxxxx.
As Diven mentioned, there's also an entry in plist file, UIMainStoryboardFile which tells which storyboard needs to be used. The equivalent of it for nibs is NSMainNibFile. But in addition to that, there were several other steps that I needed to do for replacing the storyboard fully with a nib which are mentioned in this post. Generally, what you need is following steps:
Add a new nib to your project and choose a name, e.i. MainNib. You can choose an Application nib template
Go to project, under target -> General -> Deployment Info -> choose the nib you created as Main interface
Go to your nib, as mentioned in here, add a blue object and assign its class to AppDelegate and then ctrl+drag/drop from File owner to that object and choose that one to be the delegate.
I updated the project with these changes.
There's no more Info.plist you can easily select the target and check the Info tab. And there's Main nib file base name there.
I have created a blank project using the single view option on Xcode templates.
WHen this project loads, the rootViewController class is loaded, but I don't see on the app's delegate any line loading the rootViewController.
As I generally don't use interface builder and I create my controllers programmatically I ask: where is the rootViewController loaded and how do I change the app to load another viewController instead?
thanks.
Probably in your MainWindow.xib, you define the first controller that you want to load, in your case it is rootViewController.
didFinishLaunchingWithOptions:. This method is always known to be the first to be called when launching an application. Try to check here. The Main NIB File is set in Info.plist ( located in the target settings) so that you will already have a NIB loaded when your application delegate is invoked.
It's loaded from the main interface builder file.
See your projects settings on what interface builder file is loaded, and then check what root controller it will load.
iOS loads your app -> then the Interface Builder (NIB) file specified in the settings for that app -> The nib loads a bunch of views/viewcontrollers etc
I hope you find it!
I am experimenting with Interface Builder in Xcode 4.2 and iOS 5 on a old Mac.
In Xcode 3.2 there was always a MainWindow.xib file and it contained not only the File's Owner which was UIApplication IMHO, but also an App Delegate placeholder object.
I created a MainWindow.xib file using the Window xib template. The AppDelegate placeholder is missing, so I can't hook the window up to my actual app delegate object.
I suppose that I will need to add a placeholder object with it's class identity set to "AppDelegate" but couldn't figure out how.
Just drag out one of the blue cubes (called "Object") from the objects library and change its class to the class of your app delegate.
I have a view that I created using default buttons and background in Interface Builder. The app runs properly. I added .png background images to the view and to the buttons. Build the app and run it and the updates do not show.
I've also tried something simple like changing the text of the button or add another button and the changes are not propagating.
I've cleaned targets, manually deleted builds in Finder, and have shutdown the computer. What else am I missing?
I had the same experience. It turned out that I'd renamed my class and my xib file, but in another class I was creating the view with:
MyNewViewController *myNewViewController = [[MyNewViewController alloc]
initWithNibName:#"MyOLDViewController" bundle:nil];
An oversight, but the surprising part to me is that when this Nib file didn't exist in my project, it managed to build successfully using a (presumably cached?) old Nib file... and the application happily ran, though showing an out of date interface.
Correcting what was passed to initWithNibName immediately corrected the issue for me.
This might sounds easy - but are you sure you linked up the view to the view controller in Interface Builder? I've done it before where I just forget to link them
I also had the same experience. For me the fix was to reset all content on the simulator.
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.