CorePlot 1.0 + LLVM GCC 4.2 + ARC - How to? - iphone

I'm trying out CorePlot in a small personal project to draw some bar graphs. I started the project using Xcode 4.3.2 and ARC, thinking it'd make my life easier... The problem is, when using GCC 4.2 - the compiler doesn't recognise #autorelease. I got past that using:
int retVal = 0;
// #autoreleasepool {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([kerrAppDelegate class]));
[pool drain];
// }
return retVal;
However I get the error saying that NSAutoreleasePool isn't available in ARC... Does anyone have any recommendations?

This really has nothing to do with Core Plot.
Automatic reference counting is only supported when using the LLVM Compiler 3.0 or higher. LLVM GCC 4.2 doesn't support ARC, so you'll want to switch your project over to use the full LLVM Compiler.

Related

Objective c dictionary enumeration with blocks does not work on gcc with gnustep

I am just learning obj c. I am using GNUStep downloaded from gnustep.org/experience/Windows.html (there are 3 installers - msys system, core, devel) some time back.
Running the below code:
#import <Foundation/Foundation.h>
int main (int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSDictionary *m_Dict =
[NSDictionary dictionaryWithObjectsAndKeys:
#"ABC", #"One",
#"DEF", #"Two",
#"GHI", #"Three",
nil ];
// Print all key-value pairs from the dictionary
[m_Dict enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) {
NSLog(#"%# => %#", key, obj);
}];
[pool drain];
return 0;
}
is showing an error:
$ gcc -o c c.m -I /GNUstep/System/Library/Headers -L /GNUstep/System/Library/Li
``braries -lobjc -lgnustep-base -fconstant-string-class=NSConstantString
c.m: In function 'main':
c.m:16:44: error: expected expression before '^' token
c.m:18:1: warning: 'NSDictionary' may not respond to '-enumerateKeysAndObjectsUs
ingBlock:' [enabled by default]
c.m:18:1: warning: (Messages without a matching method signature [enabled by def
ault]
c.m:18:1: warning: will be assumed to return 'id' and accept [enabled by default
]
c.m:18:1: warning: '...' as arguments.) [enabled by default]c
Please suggest what I am doing wrong. searched here on Stackoverflow also but couldn't find much help.
Your compiler doesn't support blocks. You need to use a modern clang.
Really, if you're learning Objective-C for the purpose of writing code for the Mac or iPhone/iPad, your first step needs to be to purchase a Mac and install Xcode. If you learn using older compilers, you'll be missing out on language features and you'll need to relearn the patterns you use later.
Check Mountain Lion's requirements before purchasing a Mac. You can technically run the latest Xcode on Lion, but I don't think Apple will keep it compatible for long.
Alternately, if you're just trying to learn Objective-C, you'll need to figure out what subset of the language you can use. I suggest this isn't terribly useful outside of iOS/Mac development, though.

Converting separate iPhone and iPad projects into a Universal one

I have two complete projects. One works on iPhone and the other works on iPad. I want to merge these into a Universal app.
So far the only solution I have is to rename app the classes with '_iPhone' and '_iPad' suffixes and change all references to those in the code. Then I could merge the AppDelegates and load the correct controllers at launch.
These are two very big projects so this method is going to be very time consuming. Does anyone have a better solution?
well as far as i know the only solution to do that is to create a new universal project and put your files there .. since there is a lot of share code between iPhone and iPad you can check what the device is used to running your app by check if UI_USER_INTERFACE_IDIOM()is UIUserInterfaceIdiomPad or UIUserInterfaceIdiomPhone .. and for the rename the easy way to do that to highlight the class name and select Refactor>Rename and xCode will take care about rename class name in every where you used it.
Your drafted solution seems to be the only option I know of - curious to see other answers.
One thing though; you could actually keep two separate AppDelegates.
Within your main-implementation, you could check the device and launch either the iPad-AppDelegate or the iPhone-AppDelegate.
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = 0;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
retVal = UIApplicationMain(argc, argv, nil, #"XXXAppDelegate_iPad");
}
else
{
retVal = UIApplicationMain(argc, argv, nil, #"XXXAppDelegate_iPhone");
}
[pool release];
return retVal;
}
In most cases however, I would advice to rethink such solution - often enough this results into inconsistencies and/or code replication. Still, I thought I should point out the option.

Autoreleasepool memory leak?

I'm new to Xcode 4.2 and since my project is almost finished, I thought I'd try some of the Instruments Apple provides. So, I ran Leak, and apparently, it found a leak directly at the app start. I get a solid orange vertical bar in the "Leaks" section, and when I investigate, it appears that this is the culprit:
int main(int argc, char *argv[])
{
#autoreleasepool {
//problem appears on the line below in Orange
return UIApplicationMain(argc, argv, nil, NSStringFromClass([TestProjectAppDelegate class]));
}
}
Since I'm new to this, I have no idea what the problem is, how to solve it, or even if I'm finding the actual issue!
(Isn't there supposed to be a "drain" call somewhere?)
Any help would be greatly appreciated.
EDIT
Link to screenshot file: http://whoit.home.comcast.net/~whoit/combined.jpg
(too big to embed)
Click invert call tree in Leak's option pane.
And also, maybe you could add the screenshot for this view if possible:
Replace the entire #autoreleasepool block with this:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([TestProjectAppDelegate class]));
[pool release];
return retVal;
If you still see the same leak, then you've got an over-retain issue somewhere else in your code and this section is not the issue. If you don't still see it (unlikely), then there could be something wrong with this new language construct. Highly unlikely, but this IS a new construct so there could certainly be bugs.

EXC_BAD_ACCESS in main.m

Suddenly I got EXC_BAD_ACCESS on this line:
int retVal = UIApplicationMain(argc, argv, nil, nil);
Here is the code:
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
I do not even know where to start looking?
Can anyone please help?
For any EXC_BAD_ACCESS errors, you are usually trying to send a message to a released object. The BEST way to track these down is use NSZombieEnabled.
This works by never actually releasing an object, but by wrapping it up as a "zombie" and setting a flag inside it that says it normally would have been released. This way, if you try to access it again, it still know what it was before you made the error, and with this little bit of information, you can usually backtrack to see what the issue was.
It especially helps in background threads when the Debugger sometimes craps out on any useful information.
VERY IMPORTANT TO NOTE however, is that you need to 100% make sure this is only in your debug code and not your distribution code. Because nothing is ever release, your app will leak and leak and leak. To remind me to do this, I put this log in my appdelegate:
if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled"))
NSLog(#"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");
EXC_BAD_ACCESS is a signal indicating you're trying to access a variable in memory that has been deallocated or doesn't exist. Since it's showing up after your autorelease pool is released, it means you probably over-released a variable with a pending autorelease, so the variable no longer existed to release when the autorelease pool was drained.
There are plenty of existing questions addressing this, the foremost of which is this one.
EXC_BAD_ACCESS often indicates that you've over-released memory. You can use the "Build And Analyze" command in Xcode to help track this down. I'd also suggest putting breakpoints and logging statements throughout your code to isolate the bug.
I had this problem and it might be because you're using Apple's latest main.m which does:
NSString * appDelegateClassName;
#autoreleasepool {
// Setup code that might create autoreleased objects goes here.
appDelegateClassName = NSStringFromClass([AppDelegate class]); }
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
I don't use ARC and I changed it to the code they used to use:
#autoreleasepool
{
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
and that seems to work!

Why can't I see the main function implementation in my iPhone project templates in Xcode?

That's strange, since apple says that there is somewhere an main function. But I really can't find any.
It should look somehow like this:
#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;
}
What file is that where I can see it? Is it hidden?
It's always in the Other Sources group of your pregenerated project layout.
(source: lyndir.com)
If you can't find it, you can always just create a new code file and copy in this function. When the project compiles, it will only allow you to have one main function, so if it disappeared at some point, you can just re-add it.
Alternately, you might have picked a project type that does not compile down to an executable. Not sure if/what these might be for iphone, but normally a "library" project will not have a main function.
Expand "Other Sources" in the Groups and Files section and the file is named main.m .