How do I use a RootViewController when making an app without a ViewController? - objective-c

I am trying to make a simple app from a tutorial that does not have a viewController at all. All the code is in the AppDelegate. I am on xcode 4.2 and I am getting this error:
Applications are expected to have a root view controller at the end of application launch
I'm not sure how to deal with this. There are some blogs out there with fixes but none of them are working for me and I really would like to understand what is going on here. And, how to fix it.
I do have a view that contains some buttons and labels. But I have no "ViewController". The files contained in my project are: AppDelegate.h, AppDelegate.m, and Window.xib only. There is no ViewController.h, ViewController.m
** edit **
I ended up making the app from a 'view based application' instead and just moving all the logic from the app delegate to the view controller. So, I didn't really solve the problem per se. The app works now though. Thanks for the help

It's not possible to have an iOS app that doesn't have a view controller. You can always create a trivial view controller, i.e.,
[[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds].rootViewController =
[[[UIViewController alloc] init] autorelease];

It sounds like you're looking at an old tutorial. UIWindow got a rooViewController property in iOS4. I believe it became required in iOS5 to help keep controller hierarchies and view hierarchies in sync with the addition of custom container controllers (and to fix a corner case where replacing the "root controller" of a UIWindow could stop orientation changes from propagating). There was a WWDC presentation in 2011 that explained this in some detail. I think it was Session 102, Implementing UIViewController Containment.
At then end of the day, there's no good reason not to have a root view controller. Apple wants to be able to assume it's there in their APIs going forward. If the tutorial you're looking at doesn't account for that, it's broken.

While I agree that there may be workarounds, another question to address is: why do you want an app without a view? Even if it's designed to run in the background and present no visual interface, at least make a simple view showing the application name and version, a largeish icon and perhaps a status. This kind of idle screen uses very little system resources, especially when the app is backgrounded, but improves the overall experience of the app.

If you set your deployment target to 4.3 and run on the iPhone 4.3 simulator, you won't get the warning.
To install the iOS 4.3 simulator, go to Xcode > Preferences > Downloads.

Related

subclass of UIViewController is unable to call loadView method

i have a subclass of UIViewController, and when it is called from another class the app just freezes - i used the Xcode debugger and figured that when I'm trying to access the class's view property the app freeze. another weird thing is that when i type in the debugger control panel: "po objectOfTheProblematicClass.view" the debugger stops responding.
the code I used was similar to this:
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
WTStickyViewController *stickyVC = [sb instantiateViewControllerWithIdentifier:#"WTStickyViewController"];
stickyVC.sticky = sticky;
// Setup view controller containment:
[self.parentViewController addChildViewController:stickyVC];
self.containerView = self.parentViewController.view;
[self.containerView addSubview:stickyVC.view];
WTStickyViewController is the subclass of UIViewController. the app freezes when it reaches
[self.containerView addSubview:stickyVC.view];
but it's because this is the first time that stickyVC.view is called.
if for example i would put somewhere in the code
UIView *viewForExample = stickyVC.view;
the app would freeze there.
the exact same app works fine when compiled on a device with iOS 8 but has this problem with iOS 9.
if anyone knows why is this happening and if there is a solution it will be great. thank you.
I was having a similar issue and it was absolutely maddening. The CPU went to around 100% in the resource monitor during debug as the app deadlocked. Printing to console or just generally accessing the view controller's view property caused this behavior. Ultimately, what 'fixed' it for me was removing it from the base localization file. I know that doesn't make sense, but I'll elaborate as best as I can.
I'm maintaining a legacy universal app that has 2 'main' storyboards called Main_iPhone and Main_iPad, which as you can probably guess are the loaded dynamically based on what device you're launching on. I noticed that only the iPhone nib view was deadlocking as described, and iPad was loading fine. The only thing I could tell as that the iPhone storyboard had localization enabled while the iPad storyboard had not. So here's the steps I took loosely to remove it from base localization (you may want to do this in a separate branch/sandbox to make sure this works before deleting project references):
Right click the problematic view and/or storyboard in question, show in finder. For me it was inside the Base.lproj folder as expected.
[Re]move the file to a different directory so Xcode can not find the link the project (file goes red in file browser). Press delete to remove the file from the project file's reference from the project itself.
Add the file back at the new location in your repository/project structure so Xcode picks it up as a new file. Ensure all of your references to the file are updated to the new location.
Verify your storyboard/xib file is not localized anymore, clean project, re-run and see if the issue is still there (see image).
You can also just update the file location using the update location button in the file properties view on the right side (see other image).
Don't know if this will fix it, but I thought I'd share what helped me in the chance that it helps others as well.
A bug report was sent to apple and hopefully it will be fixed soon - the problem is indeed with Xcode 7.
If you are encountering a similar problem, it can be solved by doing one of the following:
1) Use Xcode 6.4, at least until apple fixes this bug.
2) Rebuild the problematic view in the storyboard.
I will post the radar link once I got a chance to speak with my manager about it...

Error loading .xib - application crash

I am banging my head against a brick wall. I am trying to push a view onto a UINavigationController in the usual manner:
[[self navigationController]pushViewController:vc animated:YES];
When I do this the app crashes with the following error:
__CFStringEncodeByteStream + 17
Thread 1: EXC_BAD_ACCESS (code=2,address=xxxxx)
Now, I have replaced the ViewController in question with a template provided by XCode and I do not get the error so the issue must be with my UIViewController class. Furthermore, if I replace the nib name with that of the template UIViewController class it works .i.e.
MyViewController *myVc = [[MyViewController alloc]initWithNibName:#"XCodeViewController" bundle:nil];
This leads me to think that the issue is actually with the nib and not the class itself. I have checked through all the connections and there are no errors or warnings.
Hopefully somebody can help.
Thanks
I was dealing with a very frustrating bug similar to yours, and everything was in place.
The newly created xib was added to the Bundle resources, no nil pointers or released pointer, NSZombieEnabled was set. The File's Owner was set to the correct ViewController as well
After sitting down with my senior for 30 minutes, we finally realized what was wrong -
In the newly created Xib, even after you assign the File's Owner to the ViewController there is an additional step which you need to take.
You need to have the main View's referencing Outlet set to the File's owner as well. The easiest way to do this is to Drag the "+" sign on the referencing outlet(From the Connections inspector) to the "File's Owner" in the Document Outline. After this you just need to click on "view" which pops up and you should be good.
Hope that helps you or anyone else facing the same problem
Need more info to answer, I can give few possibilities.
Check if the class name is mapped properly in your identity inspector.
And check your connections too. If your view is mapped in xib., etc.
If your running the app in OS below 6.0 & built with features such as Auto layout, it leads to crash.
There are multiple possibilities.
Hope this gives an insight.
Check if your nib is added to the application bundle. You can do that by selection you project file->Build Phases->Copy Bundle Resources.
If it is not there, add it.
I had the same issue yesterday and this was the problem.
I hope it helps.

Connecting App Delegate to Controller Class

I'm stuck on this step of developing an XCode application: https://developer.apple.com/library/mac/#documentation/General/Conceptual/Mac101/Articles/07_WhereNext.html
What I'm confused about is the role of the AppDelegate class that's created by default when creating a project initially in XCode 4. If I implement a custom controller, let's use the example link above and call it TrackController. Do I make that controller the app delegate? It seems any tutorial I read isn't very clear on this.
So, in AppDelegate, do I create a new instance of the controller class here? And if so, do I then hook up the outlet here? Or do I change the File's Owner to be the controller class? If that's the case, then how's that done in XCode 4?
Not a very well defined question I know, but I'm sure someone knows what I'm talking about.
EDIT
The following screenshot shows what I mean. The blue box is now "Track Controller". I've shown the AppDelegate class in this case though to make it clear. What do I use, AppDelegate.m, or TrackController.m? How should it be done?
EDIT 2
Going back to this, I've uploaded the code to GitHub here as I still haven't figured out how to hook everything up.
To re-explain, I need to figure out how AppDelegate and TrackController all relate and communicate with one another. The concepts are generally new to me and I've read the Apple documentation but they haven't really helped me. I've even had in-depth discussions with experts and I still fail to see how it should work.
My model is Track, then I have TrackController and of course AppDelegate. AppDelegate is instantiating TrackController and I was hoping that it'd be able to open up its window.
What am I doing wrong? Hopefully an expert can help me!
What it's describing is that the application delegate should focus on handling the delegate calls sent to the app.
You actually create a new class to act as the primary controller of the app, and then you add code to call it when the app is finished loading. From there on out, that app is (supposedly) your primary control point (except, of course, when it 'hands off' to another class).
I'm more familiar with how the process works on iOS than Macs, which have to worry about windows, but for an iOS app you'd add code to call your starting view controller from inside ApplicationDidFinishLaunching:WithOptions:. From there, the view controller takes off, and the easiest way to view the entire process is that you start at the view controller (that's how most tutorials handle it, in fact, letting XCode handle the fact that the app delegate creates that view controller).

Using -presentModalViewController:animated: with UITabBarController NOT animated

So the rootViewController for this application is a UITabBarController subclass. And we're having a bizarre issue where we cannot get a UITabBarController to -presentModalViewController:animated: if we're passing NO to animated. We've tried a variety of methods: -viewDidLoad, -viewWillAppear, -viewDidAppear and can only get it to work if we do it after a delay, which is hacky.
I decided to break this out into a test and found that if I have a UIViewController that calls -presentModalViewController:animated: in the -viewDidAppear method it works as expected with both YES and NO for the animated parameter. However if this VC is instead a UITabBarController, it works if animated is YES but not if it is NO.
Any ideas? Is this a bug? I've searched online and through documentation and can't find a reason that UITabBarController shouldn't be able to present a view this way.
This definitely sounds like a bug. I'd suggest you file a bugreport with Apple. If it's blocking your project, you could submit it through one of your support incidents with Apple, and if they find it really is a bug they'll refund that support incident (so you don't loose anything). If it isn't a bug, they'll be able to give you a solution.

iOS 3 - UITabBarItems disappear from UITabBar after a memory warning occurs

At a great number of requests from people using older iOS hardware, I'm currently refactoring and optimizing my app so it will work on iOS 3. That being said I've got a glitch with my UITabBar that I can replicate on all of the iPhone 3G units I've tested it on.
The glitch appears to have been fixed in iOS 4, but I was wondering if before that time, anyone else had this glitch as well and had figured out a (relatively elegant) workaround for it.
The problem is what you can see below; when a memory warning occurs and all of the views offscreen are released, when I bring a view controller with a tab bar back on screen, all of the UITabBarItems that are supposed to be in it are gone. As far as I can see, they're not being drawn at all; ie tapping the tab bar has no effect. After setting breakpoints and examining the UITabBar and its items in memory, they're all still there (ie not getting released), just that they're not getting redrawn when the UITabBar is re-created in the controller loadView method.
My app works similar to the official Twitter app in that I implemented my own version of UITabBarController so I could control the integration of it with a parent UINavigationController properly. I set it up as closely as possible to the original UITabBarController class though, with all of the child view controllers handling their own respective UITabBarItems and initializing them inside the class' init methods. Once the child view controllers are passed to my TabController object via an accessor method, the tabBarItems are accessed and added to the UITabBar view.
Has anyone seen this behaviour before and know of a way I can fix it? I'm hoping there's a really simple fix for this since it already works in iOS 4, so I don't want to hack it up too badly.
Thanks a lot!
After a bit of research, I think I found a solution to this. It's not the most elegant solution I was after, but it definitely works.
I'm guessing after a memory warning is triggered, something is happening to the UITabBarItem objects that basically renders them corrupt. I tried a lot of things (flushing out the UITabBar, re-creating the controllers array etc), but nothing worked.
I finally discovered that if you completely destroy the UITabBarItems and allocate new ones in their place, then those ones will work. :)
So my final solution to this was to add an extra condition in the viewDidLoad method of my controller that if the detected system was iOS 3, and there was already an array of UITabBarItems, it would go through each one, copy out all of the properties needed, destroy it, allocate a new one and then copy the old properties over to the new one.
I'm still going to keep an eye out for a better solution (I think there's a bit of overhead in this method), but thankfully at this stage, iOS 3 legacy support is becoming less and less of an issue. :)