I'm struggling to get an existing ARC-enabled control to run under Xcode 4.2 (OSX Snow Leopard), in a non-ARC-enabled project, and I'm facing various issues :
How should I fix the following issues ?
Use of (strong) in properties
Use of (nonatomic) in properties
Instance methods not found (not having being declared in the interface)
Enable new-style Objective-C
Also, it seems to be complaining about NSScrollerKnobStyle not being defined. Is it a 10.8-to-10.6 SDK-specific issue?
P.S. The control I'm using is ITSidebar
You're going to have to change those strong properties to retain or copy, as appropriate. There's nothing wrong with nonatomic in non-ARC code.
You may have to add #synthesize directives for your properties to get the compiler to add accessor methods. #synthesize is the default in the latest compiler.
There ae a number of other changes to the language, such as object literals. They're all well documented; you just need to apply them in reverse.
I'm not sure about NSScrollerKnobStyle, but if you look it up the documentation will tell you when it was introduced.
Related
I have imported an Objective-C library with its entire source code in my Xcode project. The recommended way of using this library is to subclass its main object and customise its behaviour. The problem is that this superclass has many properties declared in the .m through the well known mechanism:
#interface BGRichTextEditorViewController ()
#property (strong) NSString *theString;
#end
This way, they are invisible by my subclass, and all I can do is either change the code of the library and move the properties to the .h or use valueForKey to access the superclass properties from the subclass. Is there a more elegant way to solve this ? Many thanks
That is a class Extension. The public interface is in the header file, and the private properties are hidden from you. It is by design by whoever wrote the library.
If you work around this with valueForKey you might very well find your code breaking on a new release of the library (They are usually private for a reason).
If you have the source code and don't need to be on the bleeding edge release, I would simply fork the library and make your own changes.
I'm playing around with Julius Guzy's sample code for creating a document based application that can save text files. I ran his code and it works perfectly and the app runs/save files (All in the latest version of Xcode. Though Guzy's sample code compiles using the 10.6 SDK). I'm trying to learn from it and rewrite the code. I have everything in order to compile the app but for the strangest thing in MyDocument.m. I am unable to run it.
#synthesize nsTextViewObj;
Xcode is giving me this error, which I don't really understand it.
Existing ivar 'nsTextViewObj' for property 'nsTextViewObj' with
assign attribute must be __unsafe_unretained
nsTextViewObj; is suppose to be linked to the "File Owners" in IB. I did that in the first place. It beats me why I'm getting that error. SDK conflicts maybe? How can I fix this?
ARC requires some changes to the code. Xcode provides a tool to automatically convert non-ARC code to ARC: Edit / Refactor / Convert to Objective-C ARC…
The Xcode tool is a good start, still I would recommend you to read Transitioning to ARC Release Notes.
I don't know Julius Guzy's code, but probably you should change it to something like:
#interface ifc_name : NSWindowController {
NSTextView *__unsafe_unretained nsTextViewObject;
}
#property (unsafe_unretained) NSTextView *nsTextViewObject;
As the name implies, unsafe_unretained is not safe: when the object is deallocated, your reference is invalid. If you are deploying only to iOS 5 or higher, and OS-X 10.7 or higher, you can use weak instead. With weak your reference will become zero when the object is deallocated.
I setup a phonegap 2.0.1 project and noticed that it is using ARC. However im wondering if the MainViewController.m which is automatically created for you, that inherits CDVViewController is also run under ARC.
I have added a few properties to the MainViewController like:
#property (nonatomic, readwrite, copy) NSString* errorJS;
And i am wondering If I need to use dealloc to release it, or weather this is already handeld as CDVViewController is run under ARC :S
Can anyone tell me if I still need to release my properties in MainViewController or not?
ARC basically means that you don't have to add release calls because the compiler adds them for you - the binary output from an ARC enabled project (eg libcordova.a) isn't any different from one where the release calls were added manually.
The answer depends on whether or not your project is set to use ARC. I believe the template has ARC turned off by default.
If ARC is enabled, calling release will produce a compiler error. If ARC is disabled, not calling release will usually produce a warning when you run static analysis.
My project is ARC enabled (the build settings have Objective-C Reference Counting set to YES). There are no file exceptions to this, it is enabled project wide. (Latest stable version of Xcode).
When I create an NSManagedObject subclass via File > New for a Core Data entity, the generated header uses the following in its property declarations:
#property (nonatomic, retain)
But 'retain' is not ARC!! Is this a bug, or is there something I'm missing or not understanding? There are no build warnings - if this is a bug though, how can I remedy it?
retain is a synonym for strong. So it is perfectly valid to use retain or strong in this case.
For more detail check out this question.
retain is a valid property declaration in ARC: See the clang documentation on it
I'm writing an Universal App that will run natively on both iPad and iPhone. I also need it to be targeted to older devices (those that cannot run 4.0) so 3.1 is a must.
I have already set up the Base SDK to the latest available version (4.2), and the Deployment Target to 3.1. I am making lots of runtime checks in order to call the corresponding methods only on the right device/version.
One of the things I am making use of in the iPad is an UISplitViewController. When assigning the splitViewController delegate, the compiler throws a warning because the class interface isn't explicitly adopting the UISplitViewControllerDelegate protocol and I'm afraid that if I declare it to make it so, the App will crash on older devices where there is no UISplitViewController/UISplitViewControllerDelegate.
What is the best way to supress the compiler warning? Should I declare an 'empty' UISplitViewControllerDelegate? If so, can I make it conditionally at runtime? Or should I just make the corresponding class interface conform to the protocol and not worry about older devices?
Best,
You can suppress the warning with a simple C cast:
foo.delegate = (id<UISplitViewControllerDelegate>)self;
I haven't tried this, but I'm pretty sure you can just go ahead and adopt the protocol unconditionally, even if the class may be used on an older runtime that does not have the protocol. And here's why:
All the information for defining a protocol is contained in the .h file that declares the #protocol. When you adopt a protocol, that protocol declaration is imported at some point in your .h file (presumably by #import <UIKit/UIKit.h>).
When the runtime needs to know something about a protocol, it references a "Protocol Object", which you would normally reference in source code by doing #protocol(MyProtocolName). And the compiler creates this protocol object (at compile time) when such a protocol reference is encountered, according to the section titled Protocol Objects in The Objective-C Programming Language documentation.
So knowing all that, if you adopt a protocol and you write any code that references the protocol object, that protocol object will be created by the compiler. Even if you're running on an older device, the compiler should've created that protocol object for you, so I don't think it'll cause a crash.
Hope that makes sense. If I have some time I can try this out to see if it holds in practice because I have devices running a range of iOS versions from 3.1 to 4.2.
Same problem if you want to use printing and stil have the app runnig before 4.2. Basically it works with this
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40200
// code for iOS 4.2++
#interface PersonDetailViewController : UITableViewController <EditViewControllerDelegate, EditPickerViewControllerDelegate, UITextFieldDelegate, UIActionSheetDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UIPrintInteractionControllerDelegate>{
#else
// code for iOS til 4.1
#interface PersonDetailViewController : UITableViewController <EditViewControllerDelegate, EditPickerViewControllerDelegate, UITextFieldDelegate, UIActionSheetDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate>{
#endif
But... It looks like the InterfaceBuilder can't handle this. All outlets defines after this conditional definition ar gone in IB.
So any better solution?
Regards
Gerd