deploy to device results in frankenstein binary - objective-c

I'm unsure if this is relevant to my question, but I'll start at the beginning: In my project I have a view controller which is instantiated dynamically by class name, like this:
NSString* className;
...className is set to a valid class name, e.g. "someViewController"
Class c = NSClassFromString( className );
UIViewController* vc = [[c alloc] init];
In the current build of the project, someViewController is simply a specialized UIViewController. However, in an old build of the project (which was previously deployed to my device), the view controller of type someViewController was a specialized UITableViewController.
I spent a bunch of time this morning trying to understand why when I ran the build on the device (deploy from XCode), it would crash with an odd call stack and a console message:
[someViewController tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0xeb62a0
With much experimentation I found that if I swapped out the someViewController with any other view controller I couldn't repro the problem. And if I renamed someViewController to someViewController2 I couldn't repro the problem. The problem was with the symbol name someViewController. Then it dawned on me that someViewController USED to be a UITableViewController and would have had the tableView:numberOfRowsInSection: implemented.
In any event; deleting the app off of the device and having XCode deploy a clean copy fixed the issue.
What I want to know is, why? How? I guess I've known in the back of my mind for a while that XCode does funky stuff when deploying - I've had issues before where old resources stick around in the deployed bundle after they've been removed from the project. But I wouldn't have expected there to be issues with Objective-C types.

Simply renaming a .h and .m file and then introducing a new .h and .m with the same name will cause problems. Not to xcode, but to you. Best is to copy files to a directory like /tmp, delete them from the project, later add them to the project as new with a different name.

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.

Made a change in Interface Builder, Xcode is not showing it

So here is what my interface looks like at the moment:
Here is what I have changed it to in Interface Builder:
This is what is shown after I run it in Xcode:
Obviously the two programs are not communicating - if someone could point me in the right direction it would be great.
Thanks heaps!
If stuff isn't in sync, try cleaning your build. Product>Clean should do the trick.
The programs communicate through the NIB/XIB files. Make sure you have saved your changes from Interface Builder before rebuilding in XCode (this does not happen automatically). Also double check that the file Interface Builder is editing is the exact same file (not a copy) of the one in your XCode project.
Hope this helps.
This happens if you rename a nib but forget to change name of nib name passed in to a ViewController in its initWithNibName: bundle initialiser.
For example. If I have a nib named ViewOne.xib which I'm passing in to a ViewController like this:
ExampleViewController *exampleViewController = [[ExampleViewController alloc] initWithNibName:#"ViewOne" bundle:nil];
And I change the name of the nib to ViewTwo, Xcode isn't smart enough to amend this reference in the initialiser, so now a xib that noi longer exists is being passed in to the ViewController. For reasons that I cannot fathom, despite the fact there is no longer a nib called ViewOne.xib, Xcode maintains some sort of ghost of the file and you won't get an error because of the missing nib. Cleaning and deleting derived data did not get rid of this ghost reference, at least in my case.
The fix is easy - just amend the nib name in the initialiser to your new name:
ExampleViewController *exampleViewController = [[ExampleViewController alloc] initWithNibName:#"ViewTwo" bundle:nil];

presentModalViewControllerAnimated: gives white screen

Hey all. Something which has been bugging me quite a bit recently is this custom movie player I've put together. It's largely based on a working one, NGMoviePlayer.
The issue is this: I have the .xib in a UIKit-friendly resource bundle. When I call:
[MyMoviePlayerViewController initWithNibName:#"MyMoviePlayerViewController"
bundle:[NSBundle bundleWithPath:
[[NSBundle mainBundle] bundlePath]
stringByAppendingPathComponent:#"MyMoviePlayerViewController.bundle"]];
..on my custom class, and then access the view (thus calling loadView) it doesn't throw any errors, but nor does it actually load the outlets properly. I am presented with a white screen, and debugging shows that all visual elements are 0x0, but there was no error as would be expected.
EDIT: I've also now tried just loading the .xib outside of a resource bundle in my target app, and the same thing happens (white screen).
The particular ones I was looking for was either:
Could not load NIB <nibname>... if it wasn't found at all, or
...loaded the <nibname> NIB but the view outlet was not set if it was found but not connected properly
The xib is in the local app (I understand that static libs can't contain xibs). I've tried using this same resource bundle with the NGMoviePlayerDemo project provided by the author of NGMoviePlayer, and it does throw an error:
Could not load NIB in bundle:
'/Users/.../MyMoviePlayerViewController.bundle (not yet loaded)'
with name 'MyMoviePlayerViewController'
I have navigated to the path it displays for the bundle and there exists a MyMoviePlayerViewController.xib file at that location.
I've also tried using bundle:nil in case Xcode combined the resources of bundle directories with the main one for some reason. Both cases throw no error and display a white screen in my actual project. Both cases throw a Could not load NIB error in the NGMoviePlayerDemo project.
EDIT: I have tried the same .xib separate from a resource bundle in the NGMoviePlayerDemo app and it works fine.
All input is greatly appreciated.
Solution: Pay attention to Unknown class <classname> in Interface Builder file. messages.
I had the code for the movie player in a static lib, and the parent view controller for the movie player was being included in the project as an external header, but the subviews weren't included as headers, so they weren't being located properly. Because the only place they were being referenced in my target app was within the .xib file, there were no compile errors to do with those subclasses, but when it came time to load the .xib those classes could not be found, so none of their properties were set. And that just so happened to include all of the controls for the player, which probably then made the initialisation code silently fall over.
I merged all of the code and ivars from the subclasses into the parent movie player class, and it's working fine now :)

AppDelegate file missing in Xcode 3.1?

i am currently starting to learn Xcode and objective-c and i am reading three different books on that topic currently. All of these books refer to a file called "AppDelegate" (My_First_ProjectAppDelegate.m, My_First_ProjectAppDelegate.h) which are said to be "created with the Project" (i am creating a "Cocoa Application"). These files are not present when I create a new Project. I seem to be not the only one having this problem (see http://pragprog.com/titles/dscpq/errata ).
Is there any more information about AppDelegate? What is the current practice on how to deal with a missing Appdelegate? i am using Xcode Version 3.1.4 on Mac OSX Leopard.
AppDelegate is nothing more than a common NSObject class with needed connections in MainMenu.xib. You can easily recreate your own:
Create a class, name it AppDelegate
Open MainMenu.xib and add NSObject object to object palette
In object inspector's Identity tab (the last one) set object's class to AppDelegate (you should get autocomplete)
Ctrl+drag from Application object to your newly created AppDelegate object and choose "delegate" from opened panel.
As I recall, only the iPhone templates were providing delegate classes by default. This is not a huge deal, but I can see how you would be concerned if you are just learning. Are you sure what you are reading is relevant to MacOS applications and not Iphone?
You can always create your own delegate class manually. You just create a class as you normally do, then set it as the delegate for NSApplication in Interface Builder.
I think the confusion comes from the version of XCode you are using.
Xcode version 3.2 changed the default behavior when you create a new project: it now creates an AppDelegate for your project. I can't remember what the earlier versions did, but it was different.
As Eimantas says, if you want to use an AppDelegate then you can just create one following the steps he describes.