No 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed - ios

That line gives me a warning in the source code
#property (nonatomic) dispatch_queue_t queue;
No 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed
My project is non-ARC and I cannot change it at the moment.
How do I fix the warning? (nonatomic, assing)?

The system needs any of those 3 attributes, if none is present, it will assume it's assign the chosen one. If you write (nonatomic, assign) it will work exactly the same way it's working now so, if it's working o, go ahead and write assign.

Related

Property does not match property type in primary class

I have a problem with m file since iOS 8 (but works on iOS 7), I need this
#property (nonatomic, retain) UITextView *description;
But in NSObject.h I have this :
#property (readonly, copy) NSString *description;
And Xcode returns this error -> "Type of property 'UITextView *' in class extension does not match property type in primary class"
I think I must change the name of my UITextView but I'm not sure.
Can you give me some advices, please?
Yes, you need to change the name of your UITextView, I'd go for descriptionTextView or something similar.
What's happening here is that NSObject already has a property named description. Since the object you're setting this property on likely inherits from NSObject, the system apparently thinks that you're trying to extend NSObject. Since it's property type is NSString and you're trying to define a property of type UITextView, the compiler balks and decides that it can't work. So you get this error.
What probably happened is the compiler got smarter with iOS 8 than it was in iOS 7, and thus catches this error. Either way, it's in your best interest to change it!

Why Obj-C property default ownership "assign" instead of "strong"

I'm adding Swift classes to an old project. It went well, until I tried adding a property to the Swift class. The generated header doesn't compile.
I think the problem is, in the generated code, Swift omitted strong ownership and only declared it as nonatomic. This should normally be enough, because #property should default to strong ownership, right?
So basically these are equivalent:
#property (nonatomic) NSDate *aDate;
#property (nonatomic, strong) NSDate *aDate;
But, in my case, it seems like it is defaulting to assign instead of strong, according to the compiler message.
I'm using Xcode 6 GM, and the project has ARC turned on.
Any idea why it is not defaulting to strong? Can I change this somehow?
After numerous experiments, I've found out a subtlety that determines the default ownership behavior of a property:
If a header file is imported only into ARC-enabled classes, and there is no default ownership declared, then the ownership of the property within this header file is strong.
If a header file is imported into at least one non-ARC class, and there is no default ownership declared, then the ownership of the property is assign!
This means also, you must not import a -Swift.h header into any non-ARC classes, as it will change the behavior of all the properties and emit warnings (which in my case were converted to errors).
Pretty weird IMHO...
Example:
we have classes SourceClass, ARCClass(ARC-enabled) and MRCClass(ARC-disabled)
SourceClass.h has: #property (nonatomic) NSDate *date;
Subtlety:
If we add #import "SourceClass.h" only in ARCClass.h or ARCClass.m,
the property date has ownership strong.
the declaration is equivalent to #property (nonatomic, strong) NSDate *date;.
As soon as we add #import "SourceClass.h" to MRCClass.h or MRCClass.m,
the property date will have ownership assign instead.
the declaration is changed to #property (nonatomic, assign) NSDate *date;.
I'm sure that, at one time, "assign" was the default and this...
http://cagt.bu.edu/w/images/b/b6/Objective-C_Programming_Language.pdf
"assign -
Specifies that the setter uses simple assignment. This is the default."
...seems to confirm that (page 59).
However, I also see an Apple document ("Programming with Objective-C") that says, "By default, both Objective-C properties and variables maintain strong references to their objects". I believe the change was made with the introduction of ARC.
Although you say ARC is turned on, if this project is old enough it may be that something is still around to interfere with ARC settings.
I realize this isn't a definitive answer but perhaps checking project settings (or cleaning up the project) with this change in mind may help.

How do I disable property auto-synthesis of properties in Xcode 5?

I have written a library to automatically generate NSUserDefaults accessors based on #dynamic properties that you declare in a 'preferences' class (see PAPreferences). You write the property in a .m file like this:
#property (nonatomic, assign) BOOL hasSeenIntro;
and then add this to the .h file:
#dynamic hasSeenIntro;
This works fine but if the user accidentally forgets to put in the #dynamic line, then the compiler will automatically generate an equivalent #synthesize line instead. There will be no warnings but of course my code won't be invoked for that property.
I'd like to know if there's a way to disable automatic property synthesis just for this class.
Update:
Thanks to Nikolai's answer, I remembered that it's possible to promote LLVM warnings to errors and wrapping the declaration with that error achieves the effect I was looking for (an error will be raised if the user forgets to specify the #dynamic line):
// Ensure we get an error if we forget to add #dynamic for each property
#pragma clang diagnostic push
#pragma clang diagnostic error "-Wobjc-missing-property-synthesis"
#interface Preferences : PAPreferences
#property (nonatomic, assign) BOOL hasSeenIntro;
#property (nonatomic, assign) NSInteger pressCount;
#end
#pragma clang diagnostic pop
There's no way to do this via code.
There's a compiler warning (controlled via Xcode's build setting "Implicit Synthesized Properties", CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS) but you have to manually set this on the implementation file, so for your case that's not really helpful.
Here's another idea: Change your implementation to add the properties using a category on PAPreferences instead of a subclass. Then the compiler can't synthesize the accessors and will emit a warning if the #dynamic is missing.
#interface PAPreferences (SynthesizedProperties)
#property int foo;
#end
#implementation PAPreferences (SynthesizedProperties)
#end
Result:
> warning: property 'foo' requires method 'foo' to be defined - use #dynamic or provide a method implementation in this category
Additionally (or instead) you can introspect the property during runtime to detect accidentally synthesized accessors and emit a warning in this case.
AFAIK there is no way to do that, as in previous Xcode versions there was no way to flag wether you had forgotten to #synthesize a specific property. Only at runtime you'd have a Unrecognize selector error being raised.

ARC gives warning if I remove strong life time qualifier from property, it should not because Under ARC, strong is the default for object types

I have converted non-ARC project into ARC, but XCode5.0 is giving below warning for line
#property (nonatomic) NSNumber *latitude;
Warning: No 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed
When I add strong life time qualifier then Warning goes out.
#property (nonatomic, strong) NSNumber *latitude;
Under ARC, strong is the default for object types, so why XCode is giving warning if I dont mention its a strong property?
Did you through "Edit->Refactor->Convert to Objective-C ARC" to enable ARC? Or just change project setting? You can try first method to convert project to ARC.

Does #property copy in combination with readonly make sense?

If I understand this correctly, copy enforces the setter to create a copy of the object passed in. However, if I use it together with readonly, there won't be a setter. So is my assumption correct, that combining #property (copy, readonly) doesn't make any sense or am I missing something?
It does make sense. For instance, if you want to access a property's setter in your implementation only:
#interface MyClass : NSObject
#property (nonatomic, copy, readonly) NSData *data;
- (id)initWithData:(NSData *)data;
#end
and in the class continuation in the .m file:
#interface MyClass ()
#property (nonatomic, copy, readwrite) NSData *data;
#end
Note that the copy, readonly declaration in the public header is required in this case!
According to Apple's documentation (which I've linked here for you):
copy
Specifies that a copy of the object should be used for assignment.
The previous value is sent a release message.
The copy is made by invoking the copy method. This attribute is valid
only for object types, which must implement the NSCopying protocol.
So yes, you're correct... readonly creates a getter method and copy would be effectively ignored, since there's no setter method that does assignment.
You are correct, it does not make sense to have both.
I think, if I saw such a property, on read, I would expect to receive a distinct returned object to the ivar unless the returned object was advertised to be immutable.
If I have
#property (readonly, copy) NSMutableArray* foo;
and I do this:
NSMutableArray* myFoo = [theObject foo];
[myFoo addObject: #"string"];
NSMutableArray* myOtherFoo = [theObject foo];
I would expect myOtherFoo not to have the extra string in it that myFoo has.
Note: I haven't verified this yet.
I have checked it now and my expectation is incorrect. I think I would regard that as a bug.

Resources