Does anybody have an experiencing with refactoring a project built with Xcode 4.3 down to build with 4.1? I get a black screen (not a crash) on load.
If I set a breakpoint on exception, I get an assembly breakpoint.
That leads me to believe that window or something is not getting loaded. I'm not using ARC, and the interface is built with IB. I'm using straight llvm. I have a feeling my problem is in main.
Okay, I got it.
4.1 doesn't like the way that a Universal app is built, apparently. So, here's what I did.
replace in main
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
with this
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
[pool release];
return retVal;
The important bit is to send the appDelegate to the 4th arg of UIApplicationMain. If it's nil, it'll look for the appDelegate in the main nib. Hope this helps someone.
I would suggest creating a blank project in XCode 4.1 and 4.3 and then compare the Info.plist file and the content of .xcodeproj folder. Your problem may be actually related to specifying the main window or some of the defaults values (that could have been set in the new project and don't work properly in the old one).
Related
I have an iPhone-app that was in appstore for some month (from Nov.2011 until now). On July, 17th I passed an update to itunes and today they rejected it. They sayed it displayes only a black screen when running on an iPad. I tested it, and really, the splash-screen-picture showes up and after few seconds it is replaced not by the apps 1st screen, but by a black screen. (iPad-Simulator as well as physical iPad). But there was no message in Xcodes console.
So, I started the app on my iPhone where I loaded it before July 17th and where I did test the app before releasing: It did run perfectly.
Then I did start it from Xcode on the iPhone-Simulator: Splash-Picture, then black screen but no message in console.
So I connected my iPhone and loaded the newly compiled Version to my iPhone: Black screen!!!
To find out more, I inserted this line into my code at several places in main.m and in appDelegate.m:
NSLog(#"%s Line %d",__PRETTY_FUNCTION__,__LINE__);
Content of main.m:
//(some comment-lines)
#import <UIKit/UIKit.h>
int main(int argc, char *argv[])
{
NSLog(#"%s Line %d",__PRETTY_FUNCTION__,__LINE__); //this is line 13
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(#"%s Line %d",__PRETTY_FUNCTION__,__LINE__); //this is line 15
int retVal = UIApplicationMain(argc, argv, nil, nil);
NSLog(#"%s Line %d",__PRETTY_FUNCTION__,__LINE__); //this is line 17
[pool release];
NSLog(#"%s Line %d",__PRETTY_FUNCTION__,__LINE__); //this is line 19
return retVal;
}
I also entered this line in appDelegate.m:
- (BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
NSLog(#"%s Line %d",__PRETTY_FUNCTION__,__LINE__);
// some more code
}
When I run the app, there are only those two lines displayed in Xcodes console:
2012-07-28 11:03:29.548 nulowi[4072:c07] int main(int, char **) Line 13
2012-07-28 11:03:29.553 nulowi[4072:c07] int main(int, char **) Line 15
So it looks, as if main in main.m was executed and the Autoreleasepool was created. But then, after calling UIApplicationMain in main.m and before calling application:didFinishLaunchingWithOptions: in the apps delegate, there must happened something, and I don't know what this could be.
Maybe it has something to do with the upgrade from Mac OS X 10.7 (Lion) to OS X 10.8 (Mountain Lion) on my MacBook Pro? When I released the ready-tested app on July 17th from my MacBook with version 10.7, everything was fine. Yesterday I installed the update from 10.7 to 10.8.
And now, when trying to run from version 10.8, application:didFinishLaunchingWithOptions: will not be called.
Would you try to make a complete clean of your project, down to deleting the content of your build folder? Then rebuilding and see what happens...
There could be some issues with what you mention, but only in the sense that something got "mixed-up" between versions of OS/Xcode...
You can find the location of your build files in Xcode preferences (see picture).
If that does not work, try and change the way UIApplicationMain is called to this:
int retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
specifying the real name for your app delegate.
today i tried to run my first iPhone app(the app is assignment in Stanford course).
in the assignment i ask to defining and instantiating class in interface builder, i defined the class run the simulator and everything work just fine. when i tried to connect the class(and the object) to the UI and then run the simulator xcode was crashed and show this message:
Thread 1:signal sigABRT
when i remove the connection between the class to the UI(i remove the connection between the outlets and the label in the app view) everything is again work fine.
i tried to understand where the problem came from with breakpoints and the crash is in this line of code(in the main file):
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
pls help me, it's make me crazy.
Xcode 4.x is not very good at telling you where the real error is and shows that line in main.m instead. Try replacing it with code that shows you more information:
#try {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
#catch (NSException *exception) {
NSLog(#"Exception %#\n%#", [exception description], [exception callStackSymbols]);
}
I had created a project using base sdk 5.0 in xcode 4.2. While creating the project, I had not checked all 3 options that are displayed, when we create the new project on iOS 5.0, namely. storyboard, use ARC and include unit tests. After writing my code, I want to run this on xcode 3.2.5/ iOS 4.2, but it gives an error because iOS 5 uses #autoreleasepool instead of NSAutoreleasePool. How will I run it on iOS4.2
How about using the old main.m?
#import <UIKit/UIKit.h>
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
Another thing. "storyboards" and "ARC" are only supported in iOS 5. So this will be a problem too if you want to run this in iOS4.
summary:
if u want backward compatibility write your program on the lowest version you want to support and it will be fine. use old main.m, retain instead of strong and no storyboards or ARC and it works on iOS >= 4.
So I was attempting to test a PhoneGap application I've been working on, and had some issues with the test on my iPad. I have the following as the main method for this application:
//
// main.m
// elog
//
// Created by Ben Potter on 9/08/11.
// Copyright Arden Anglican School 2011. All rights reserved.
//
#import <UIKit/UIKit.h>
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, #"AppDelegate");
[pool release];
return retVal;
}
It all works fine until you close the app completely and then reopen it, upon which it freezes. And I have no idea why.
I am running ios5 on my ipad with XCode 4.2
Finally, these are the errors which come up, thanks for the help!
Direct link here
Your application is using Automatic Reference Counting (which is new) and Phonegap doesn't support it yet. Go to your project's build settings and turn Automatic Reference Counting to off.
This is how I solved the "NSAutoReleasePool" error in XCode 4.3 and with PhoneGap 1.5.
Go to "YourApplicationName" in the Project Navigator.
Select "YourApplicationName" under Project.
Go to Build Settings.
Make sure to toggle "All" and "Combined".
Find the section "Apple LLVM compiler 3.1 - Language".
Scroll down and you will find "Objective-C Automatic Reference Counting".
Change it from Yes to No.
Try to build your project again and you should be fine!
So, just to clarify for the visually-inclined, it took me a few minutes to find the correct option since it's only mentioned in the comments of another answer. I had to find the CLANG_ENABLE_OBJC_ARC build flag and switch it to NO. You'll find it under the Build settings in the User-Defined section (very bottom for me):
I was also able to get past the runtime error by going into main.m and commenting out the NSAutoreleasePool setup code like so:
//NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, #"AppDelegate");
//[pool release];
return retVal;
However, I'm not sure what other effects that might have down the line. It seems that at present, while working with PhoneGap, it's probably best to stick with manual ref counting until PhoneGap properly supports ARC.
And just for Google, the error that led me here was "NSAutoreleasePool is unavailable" as I don't see that as text in the original post.
If you don't want to disable ARC, then the following will fix the errors in Xcode 4.2.
AppDelegate.m
// self.window = [[[UIWindow alloc] initWithFrame:screenBounds]autorelease];
self.window = [[UIWindow alloc] initWithFrame:screenBounds];
// self.viewController = [[[MainViewController alloc] init] autorelease];
self.viewController = [[MainViewController alloc] init];
(void) dealloc
{
// [super dealloc];
}
main.m
int main(int argc, char *argv[]) {
// NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// int retVal = UIApplicationMain(argc, argv, nil, #"AppDelegate");
// [pool release];
// return retVal;
#autoreleasepool {
NSLog (#"Programming is fun!");
}
return 0;
}
Disclaimer:
Not sure how this affects the rest of the PhoneGap lib an plugins though. However, after implementing these changes, the template PhoneGap project runs on the simulator, but terminates instantly. This was just a starting point.
Better Alternative:
I suggest you disable Automatic Reference Counting (ARC) under Build Settings until PhoneGap supports it. This thread on on PhoneGap forum hints that ARC may be supported in PhoneGap 1.6.
Prior to cordova 2.1.0 ARC is not supported, you are not supposed tick the box below (when you are still creating your project):
However, this is the exact code you need:
#import <UIKit/UIKit.h>
int main(int argc, char *argv[]) {
#autoreleasepool {
int retVal = UIApplicationMain(argc, argv, nil, #"AppDelegate");
return retVal;
}
}
If you upgrade to cordova 2.1.0 in Xcode 4.5.1 you can go to:
Edit
Refactor
The choose between Objective ARC and Modern Objective-C syntax.
Consider the following main() method which you would find most iPhone applications:
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
In every iPhone app that I've run in Simulator with these (including several sample projects provided by Apple), the thread never exits UIApplicationMain() and any remaining code in main() is never executed. Is this expected behavior?
I have verified that statements after UIApplicationMain() never run by stepping through the code with a debugger. When the user stops an application (by hitting the "Home" button, for example), the resulting stack trace shows that [UIApplication _terminateWithStatus:] is eventually called. This function calls your application delegate's applicationWillTerminate: method. Once that finishes, [UIApplication _terminateWithStatus:] seems to kill/exit the thread.
Can someone confirm that this is how main() is supposed to work, or at least confirm the same behavior on their machine?
The original question was: "Why doesn’t an iPhone app’s main() function ever get a chance to finish?"
Short Answer: Because UIApplicationMain() is coded such that it never returns.
After doing several tests in Simulator and on the device, and asking another developer to do the same tests, I have confirmed that UIApplicationMain never returns. When the user terminates an application normally by hitting the Home button, The program ultimately terminates inside an unpublished UIApplication method called _terminateWithStatus. This method calls exit(0).
This behavior matches that of the NSApplicationMain function (which is AppKit/Cocoa version of the UIApplicationMain function). The documentation for NSApplicationMain() clearly states that it will never return.
I have submitted a bug (6600198) to Apple requesting that the official documentation (and Xcode template for main.m) be corrected to state that UIApplicationMain() never returns. While this is not a functional problem, the current template and docs are misleading.
Thanks to everyone for all the input and brainstorming!
Try:
int main(int argc, char *argv[])
{
NSLog(#"Step 0");
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(#"Step 1");
int retVal = UIApplicationMain(argc, argv, nil, nil);
NSLog(#"Step 2");
[pool release];
NSLog(#"Step 3");
return retVal;
}
It may be that the release of the pool is preventing further logging in which case you'd get step 2 but not step 3.
If step 2 isn't being printed, then it's almost certainly something wrong with UIApplicationMain - there's a chance that it doesn't return so put NSLog statements (step 1.1, Step 1.2, ...) at various points within it and run to find the last message logged.
Keep drilling down (Step 1.7.1, 1.7.2, .... 1.7.6.3.2, ...) - eventually, you'll track down the exact line (however deep in the call hierarchy) when the log messages stop being logged and that line will be your culprit (either "turning off" logging or exiting without returning normally).
One further snippet I found on the web:
=====
When you use this line:
int retVal = UIApplicationMain(argc, argv, #"MyApp", #"MyApp");
The first MyApp is your main app delegate class. The second is the class to where SpringBoard sends touch notifications.
Also, if you are using the SDK, and have a main nib defined in the Info.plist, then you can leave the call as:
int retVal = UIApplicationMain(argc, argv, nil, nil);
as all that will be covered when you create your xibs.
=====
Now I don't know enough about iPhone development (specifically xibs) to know what that last bit even means (or if you've set it up correctly) but it sounds like another phase of compilation.
However, my first thought from reading that is that Springboard will call your delegate class when the buttons are pressed to ask you to do something (like shut down gracefully). If it can't ask you (i.e., no delegate), it's probably within its rights to shut you down as it sees fit, such as with [UIApplication _terminateWithStatus:].
In the Windows world, you would probably send off a quit message to the main window but, as I say, iPhone development may be different.
Still, it's an avenue to investigate. I'd be interested in seeing what calls were made to a delegate if you provided one. The code included with the snippet above had this:
#implementation MyApp
- (void) applicationDidFinishLaunching:(id)unused {
rect = [ UIHardware fullScreenApplicationContentRect ];
rect.origin.x = 0.0f;
rect.origin.y = 0.0f;
window = [ [ UIWindow alloc ] initWithContentRect: rect ];
[ window makeKeyAndVisible ];
view = [ [ MyAppView alloc ] initWithFrame: rect ];
[ window setContentView: view ];
}
- (void) dealloc {
[ window release ];
[ view release ];
[ super dealloc ];
}
So maybe a delegate with dealloc() is the secret to getting it to exit back to main(). Why don't you give that a shot? It may get you closer to your goal even if it doesn't solve the core problem.
After [pool release] there is nothing to log to?
trying using fprintf and see what happens
int main(int argc, char *argv[])
{
/*
...
same as above
...
*/
[pool release];
char file_name = "/tmp/log"
FILE *file = fopen(file_name, "w");
fprintf(file_name, "END\n");
}
and tell us what happens
I also thought the easiest way to check was to set a break point right at the return
in gdb do
b main.c:x
where x is the line number of the return statement
After calling the UIApplicationMain function your application launches (establishing a runloop, etc) and all work should then be done outside the context of main (if you need it to run in main, do it before that point). When quitting an application it is generally more efficient to allow the OS to do memory cleanup.
I have that not return experience too. And have set break points to verify exactly like Clint said.
wisequark has a good point.
great topic. makes me feel more comfortable that i am not the only one who has the question.