I am following "Programming in Objective-C" 3rd edition and I am having problems with the first example.
I keep getting this error:
Semantic Issue: 'NSAutoreleasePool' is unavailable: not available in
automatic reference counting mode
Here is my code:
//
// main.m
// prog1 //
// Created by Steve Kochan on 1/30/11.
// Copyright 2011 ClassroomM, Inc.. All rights reserved. //
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSLog (#"Programming is fun!");
[pool drain];
return 0;
}
Any insight will be greatly appreciated.
The compiler is being asked to compile the file with ARC (automatic reference counting) enabled. Turn that off or, better yet, modernize your example:
int main (int argc, const char * argv[]) {
#autoreleasepool {
NSLog (#"Programming is fun!");
}
return 0;
}
(No, I can't tell you how, specifically, to turn off ARC, if that was the route you were to go down due to the aforementioned NDA.)
Quick post just in case you still looking
You can disable ARC in build settings.
Click on you project, in the left hand organizer.
Select your target, in the next column over.
Select the Build Settings tab at the top.
Scroll down to "Objective-C Automatic Reference Counting" (it may be
listed as "CLANG_ENABLE_OBJC_ARC" under the User-Defined settings
group), (if you do not find ARC option under build settings, you might need
to toggle you compiler. You can find it under build settings)
and set it to NO.
In my case, I wanted ARC on, and wanted to update a sample project to work properly. Apple's NSAutoReleasePool docs are technically correct, but don't come straight out and explain this. Here's how:
Take your application main, which probably looks something like this:
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([DemoAppDelegate class]));
[pool release];
return retVal;
}
And change it to look like this:
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([DemoAppDelegate class]));
}
}
Here is a link to Apple's transition guide to ARC.
OK...check this out. Specific change to NSAutoreleasePool - this is how Xcode initializes itself when you create your first app. I don't know about you, but I love this idea!
No worries if you are following along w/ Kochan's book. When starting your project, just uncheck the "Use ARC" box. Everything will work.
ARC is enabled when you first create a new project. Right know the only way I know how to enable or not enable it is when you first create your program. It is one of the checkboxes you have to unselect.
Related
I've just installed GNUstep, libobjc2, and llvm on a ubuntu 14.04 box using this script. The installation works for most objective-c2.0 features but not for arc. If I run the following simple program, it crashes as soon as it executes #autoreleasepool with a segmentation fault.
#import <Foundation/Foundation.h>
int main(int argc, char * argv[])
{
#autoreleasepool{
NSLog(#"autoreleasepool works...\n");
}
return 0;
}
I'm compiling with the -fobjc-arc flag. Any suggestions? I've spent two days on this searching the internet. If I use NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init] the program runs.
Mark Allyn
So, think the classic beginner C programming right of passage: hello world. But written in Objective-C.
For reasons I prefer not to get into, I don't want to use XCode but rather my new love, Sublime Text.
Can it be done?
Paste the following into Sublime and save the file as main.m
#import <Foundation/Foundation.h>
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(#"Hello, World!");
[pool drain];
return 0;
}
Then in the terminal navigate to the file with cd and type:
gcc -framework Foundation main.m -o NAME_OF_YOUR_APP
And run the app by typing:
./NAME_OF_YOUR_APP
I did a bit of digging and found this which lets me build and run entirely within Sublime Text which is what I need. Still testing: https://gist.github.com/chendo/4398077
I'm trying to create a Cocoa application that displays SavePanel, and after user choose file, it prints it on stdout. I'm total beginer with Objective-C and Cocao. Problem is that it doesn't take keyboard input, it is only posible to choose file with mouse.
This is the code:
#import <Cocoa/Cocoa.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
NSSavePanel *sPanel = [NSSavePanel savePanel];
int result = [sPanel runModal];
if (result == NSOKButton) {
NSString * filename = [sPanel filename];
char * fileStr = [filename UTF8String];
printf("%s\n", fileStr);
}
return 0;
}
The AppKit/Cocoa classes require an NSApplication object to be initialized in order to handle user input (among other things). Adding this line to the top of your main function should do the trick:
int main(int argc, char *argv[])
{
[NSApplication sharedApplication]; // ** Add this **
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSSavePanel *sPanel = [NSSavePanel savePanel];
int result = [sPanel runModal];
if (result == NSOKButton) {
NSString * filename = [sPanel filename];
const char * fileStr = [filename UTF8String];
printf("%s\n", fileStr);
}
[pool drain];
return 0;
}
More information about this can be found in the documentation for NSApplication, particularly these points:
Every application must have exactly one instance of NSApplication (or
a subclass of NSApplication). Your program’s main() function should
create this instance by invoking the sharedApplication class method.
NSApplication performs the important task of receiving events from the
window server and distributing them to the proper NSResponder objects.
NSApp translates an event into an NSEvent object, then forwards the
NSEvent object to the affected NSWindow object.
Along the lines of bbum and danielpunkass's comments below, this isn't the way you'd really write a Cocoa application, and while it does make your immediate issue go away, it's not a complete or completely correct solution. To expand on Daniel's comment, and to get you started easily, create a new Cocoa application project. Open up the application delegate class (created for you), and put your code in the -applicationDidFinishLaunching: method. As implied by its name, that method is called after the application has finished launching, and everything is setup such that you can use the AppKit classes normally. As you gain more experience, you'll better understand the typical Cocoa application architecture and can move on to creating user interfaces, etc.
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.
I just want to quit as fast as possible, before the nibs are loaded. I tried [NSApp stop:self] but that didn't seem to work. Is there a better way than getting my process and killing it?
(I know it's a weird thing to do. It's for a good reason.)
Without knowing more, I'd say put the checking code into main() before invoking NSApplicationMain
int main(int argc, char **argv)
{
if(shouldExit() == YES)
{
exit(exitCode);
}
return NSApplicationMain(argc, (const char **) argv);
}
[[NSRunningApplication currentApplication] terminate];
Apple docs here. You can also use forceTerminate. You could also use nall's suggestion, but it will only work if you can do the work to check if the app needs to be terminated in main(). Otherwise, you'll need to do something more along the lines of what I suggested.
If you can detect that you want to quit easily, modifying the main() function of your app is the "fastest" place:
int main(int argc, char **argv)
{
id pool = [[NSAutoreleasePool alloc] init]; //needed if shouldExit() uses Cocoa frameworks
#try {
if(shouldExit()) {
exit(0); //appropriate exit code, depending on whether this "fast" exit is normal or exceptional
}
}
#finally {
[pool drain];
}
return NSApplicationMain(argc, (const char **) argv);;
}
This should work:
[[NSApplication sharedApplication] terminate: nil];
Reference