In the old code of objective c
there are some .h file that have #property declare as follow:
#property (nonatomic, assign) __weak XXXObject *state
Since in later iOS version, this code is no longer valid and in XCode 8.3.3,
following exception thrown and the program can't build:
Unsafe_unretained property 'state' may not also be declared __weak
May i ask what is the behavior of the old code for declaring both assign and __Weak, and in order to solve the exception thrown, what's the best way to change the declaration of the property?
Related
I have to fix some existing code that builds just fine with LLVM (on iOS) so that it builds with llvm-gcc-4.2 too. I'm done with pretty much everything, except this pattern which is found at a few places:
#property (nonatomic, retain) __block id myProperty;
I suspect the intent here is to allow access to the property from inside a block without retaining self. How can I remove the __block attribute, which gcc doesn't support here, but still achieve the same effect?
I'll suggest you've found a compiler bug, the declaration:
#property (nonatomic, retain) __block id myProperty;
is meaningless. The __block qualifier is used on local (stack allocated) variables so they are passed by reference to blocks, so they can be updated, and are usually[*] stored on the heap rather than the stack.
Therefore the qualifier __block has no meaning on a property declaration which is concerned with object instances, which are heap allocated at all times in Obj-C.
Just drop the __block from the property declarations - for every compiler.
[*] If a block is never copied to the heap a compiler may optimize __block variables and not move those to the heap either.
just before you use the variable in a block, create a local pointer of type __block. Don't ever use __block in #property declarations.
EG: TypeOfVariable __block *bock_pointer = self.property;
^{ inside the block use bock_pointer }
I am trying TwitPic to post Image with Text over Twitter using GSTwitPicEngine class, which use YAJLiOS,
So i add YAJLiOS framework in my project and, i am getting this('assign' and 'weak' are mutually exclusive) error in the file "YAJLParser.h" that is in YAJLiOS framework.
showing Error in the following line-
#property (assign, nonatomic) __weak id <YAJLParserDelegate> delegate;
When i remove the __weak it becomes Apple Mach-O Linker (Id) Error.
Please help.How to handle this kinda errors.I am not getting the reason.
silly me ...
try
#property (unsafe_unretained, nonatomic) id <YAJLParserDelegate> delegate;
Probably you figured it out by now,
anyways here is how I got rid of this error:
#property (assign) __unsafe_unretained id<YAJLParserDelegate> delegate;
Make sure all other declarations of delegate in your .h code (if any) are __unsafe_unretained e.g. in #private section:
__unsafe_unretained id<YAJLParserDelegate> delegate;
As you probably already know, assign and weak are NOT the same thing ... functionally they're very close, but weak is much more sophisticated and rather cleverly nulls out references to disposed objects to avoid crashes ( amongst other things vis retain cycles ).
Regardless - what to do? My best guess is to try pulling out ARC's backward compatibility legacy fix ... replace _weak with _unsafe_unretained and see how that goes.
In XCode 4.3.2, when I run the ARC conversion refactor tool, all of my property options that were "retain" are NOT being changed into "strong". Is "strong" implied now or is this just a problem with XCode 4.3.2?
Example:
Before
#property (nonatomic, retain) NSString * someString;
After
#property (nonatomic) NSString * someString;
"strong" is the default when using ARC (LLVM 3.1), so the new code is correct.
(before ARC, the default was "assign")
See http://clang.llvm.org/docs/AutomaticReferenceCounting.html#ownership.spelling.property
Strong is the equivalent of the non-ARC retain. So when you shift from non-ARC to ARC XCode doesn't understand the word retain and hence removes it. Thereby causing an error or atleast a warning, as all the instance variables require atleast two properties declared.
Under what conditions is #synthesize automatic in Objective-c?
Perhaps when using LLVM 3.0 and up? From reading around the net it seems like #synthesize is unnecessary starting with Xcode 4. However I'm using Xcode 4 and receiving warnings when I don't #synthesize a property.
Some of the responses to Why don't properties get automatically synthesized seem to imply #synthesize can be omitted at some point under some circumstances.
Another (old) reference hinting that #synthesize might be automatic at some point in the future.
As of clang 3.2 (circa February 2012), "default synthesis" (or "auto property synthesis") of Objective-C properties is provided by default. It's essentially as described in the blog post you originally read: http://www.mcubedsw.com/blog/index.php/site/comments/new_objective-c_features/ (except that that post describes the feature as "enabled, then disabled"; I don't know if that's an issue with Xcode or if the clang developers themselves have gone back and forth on the question).
As far as I know, the only case in which properties will not be default-synthesized in clang 3.2 is when those properties have been inherited from a protocol. Here's an example:
#import <Foundation/Foundation.h>
#protocol P
#property int finicky;
#end
#interface A : NSObject <P>
#property int easygoing;
#end
#implementation A
#end
int main() { A *a = [A new]; a.easygoing = 0; a.finicky = 1; }
If you compile this example, you'll get a warning:
test.m:11:17: warning: auto property synthesis will not synthesize property
declared in a protocol [-Wobjc-protocol-property-synthesis]
#implementation A
^
test.m:4:15: note: property declared here
#property int finicky;
^
1 warning generated.
and if you run it, you'll get an error from the runtime:
objc[45820]: A: Does not recognize selector forward:: (while forwarding setFinicky:)
Illegal instruction: 4
As of Xcode 4.4, if you don't write #synthesize or #dynamic for a property. the compiler acts as though you had written #synthesize property = _property.
Prior to Xcode 4.4, you must do one of the following things for each property or else the compiler will issue a warning and you will get a runtime error. In Xcode 4.4 or later, you may do any of the following things instead of letting the compiler automatically synthesize the property accessors and instance variable.
Use the #synthesize directive.
Use the #dynamic directive and somehow provide the property getter and (if necessary) setter at runtime.
Explicitly write the property getter method and, if the property is readwrite, the property setter method.
Note that you can use the #synthesize directive (or the #dynamic directive) and also explicitly provide the getter and/or setter methods. But #synthesize provides them if you omit them.
From the New Features in Xcode 4.4 document:
Objective-C #properties are synthesized by default when not explicitly implemented.
So #synthesize is automatic by default starting from Xcode 4.4 with the LLVM 4.0 Compiler.
Also, synthesize will not be automatic if you have implemented the setter AND getter manually. So if you wonder why you can't access _someVariable, having declared #property (...) SomeType someVariable, then it is because you have implemented the setSomeVariable: and someVariable methods.
You can turn off the synthesize warnings by clicking on the project name in the Project Navigator on the left then click All Cobined in Build Settings and then search for synthesize. That should be set to No.
Do properties in Objective-C 2.0 require a corresponding instance variable to be declared? For example, I'm used to doing something like this:
MyObject.h
#interface MyObject : NSObject {
NSString *name;
}
#property (nonatomic, retain) NSString *name;
#end
MyObject.m
#implementation
#synthesize name;
#end
However, what if I did this instead:
MyObject.h
#interface MyObject : NSObject {
}
#property (nonatomic, retain) NSString *name;
#end
Is this still valid? And is it in any way different to my previous example?
If you are using the Modern Objective-C Runtime (that's either iOS 3.x or greater, or 64-bit Snow Leopard or greater) then you do not need to define ivars for your properties in cases like this.
When you #synthesize the property, the ivar will in effect be synthesized also for you. This gets around the "fragile-ivar" scenario. You can read more about it on Cocoa with Love
In your interface, you can formally declare an instance variable between the braces, or via #property outside the braces, or both. Either way, they become attributes of the class. The difference is that if you declare #property, then you can implement using #synthesize, which auto-codes your getter/setter for you. The auto-coder setter initializes integers and floats to zero, for example. IF you declare an instance variable, and DO NOT specify a corresponding #property, then you cannot use #synthesize and must write your own getter/setter.
You can always override the auto-coded getter/setter by specifying your own. This is commonly done with the managedObjectContext property which is lazily loaded. Thus, you declare your managedObjectContext as a property, but then also write a -(NSManagedObjectContext *)managedObjectContext method. Recall that a method, which has the same name as an instance variable/property is the "getter" method.
The #property declaration method also allows you other options, such as retain and readonly, which the instance variable declaration method does not. Basically, ivar is the old way, and #property extends it and makes it fancier/easier. You can refer to either using the self. prefix, or not, it doesn't matter as long as the name is unique to that class. Otherwise, if your superclass has the same name of a property as you, then you have to say either like self.name or super.name in order to specify which name you are talking about.
Thus, you will see fewer and fewer people declare ivars between the braces, and instead shift toward just specifying #property, and then doing #synthesize. You cannot do #synthesize in your implementation without a corresponding #property. The Synthesizer only knows what type of attribute it is from the #property specification. The synthesize statement also allows you to rename properties, so that you can refer to a property by one name (shorthand) inside your code, but outside in the .h file use the full name. However, with the really cool autocomplete that XCode now has, this is less of an advantage, but is still there.
Hope this helps clear up all the confusion and misinformation that is floating around out there.
it works both ways but if you don't declare them in the curly braces, you won't see their values in the debugger in xcode.
From the documentation:
In general the behavior of properties is identical on both modern and legacy runtimes (see “Runtime Versions and Platforms” in Objective-C Runtime Programming Guide). There is one key difference: the modern runtime supports instance variable synthesis whereas the legacy runtime does not.
For #synthesize to work in the legacy runtime, you must either provide an instance variable with the same name and compatible type of the property or specify another existing instance variable in the #synthesize statement. With the modern runtime, if you do not provide an instance variable, the compiler adds one for you.
If you are using XCode 4.4 or later it will generate instance variable synthesizing code for you.
You just have to declare properties like below; it will generate synthesizing code and instance variable declaring code for you.
#property (nonatomic, strong) NSString *name;
it will generate synthesizing code as
#synthesize name = _name;
and you can access instance variable using _name
it is similar to declare
NSString* _name
but if you declare read-only property it like
#property (nonatomic, strong, readonly) NSString *name;
it will generate code
#synthesize name;
or
#synthesize name = name;
So you should access instant variable name with out prefix "_"
any way you can write your own synthesizing code then compiler will generate code for you.
you can write
#synthesize name = _name;
The Objective-C Programming Language: Property Implementation Directives
There are differences in the behavior of accessor synthesis that depend on the runtime (see also “Runtime Difference”):
For the legacy runtimes, instance variables must already be declared in the #interface block of the current class. If an instance variable of the same name as the property exists, and if its type is compatible with the property’s type, it is used—otherwise, you get a compiler error.
For the modern runtimes (see “Runtime Versions and Platforms” in Objective-C Runtime Programming Guide), instance variables are synthesized as needed. If an instance variable of the same name already exists, it is used.