What do the null-related property attributes in Xcode do? - objective-c

With Xcode 6.3 I noticed some property attributes, namely:
nonnull
null_resettable
nullable
Could someone explain what they do when applied?

Apple has added two new type annotations:
A__nullable pointer may have a nil value,
while a __nonnull cannot have a nil value
As you should know in Swift you can use Ottionals, but in Objective-C you cannot. Those attributes let you create Objective-C code which is more understandable by Swift and compiler warn you when you break the rule, for example:
#property (copy, nullable) NSString *name;
#property (copy, nonnull) NSArray *allItems;
This will be 'translated' in swift to:
var name: String?
var allItems: [AnyObject]!
This is taken from NSHipster:
nonnull: Indicates that the pointer should/will never be nil. Pointers
annotated with nonnull are imported into Swift as their non-optional
base value (i.e., NSData).
nullable: Indicates that the pointer can be nil in general practice.
Imported into Swift as an optional value (NSURL?).
null_unspecified: Continues the current functionality of
importing into Swift as an implicitly unwrapped optional, ideally to
be used during this annotation process only.
null_resettable:
Indicates that while a property will always have a value, it can be
reset by assigning nil. Properties with a non-nil default value can be
annotated this way, like tintColor. Imported into Swift as a
(relatively safe) implicitly unwrapped optional. Document accordingly!

Related

Checking whether an ObjC property is nullable at runtime

I'm trying to figure out at runtime whether a property of a class is nullable. For example:
#interface A : NSObject
+ (NSSet<NSString *> *)nullableProperties;
#property (readonly, nonatomic) NSString *description;
#property (readonly, nonatomic, nullable) NSError *error;
#end
#implementation A
+ (NSSet<NSString *> *)nullableProperties {
// Code that identifies nullable properties.
}
#end
nullableProperties should in this case return an NSSet with #"error".
property_getAttributes function can provide information of some of the attributes (more info here). Unfortunately, it doesn't provide information on whether the property is declared as nullable.
I would like to avoid implementing nullableProperties for every class that I need to know the nullable properties for.
Every Objective-C pointer or object property is technically nullable at runtime. The nullability specifiers are simply compiler hints that don't affect the actual built binary [edit: by which I mean, since this is apparently unclear, the 1s and 0s that get written to the disk in either Mach-O or some other comparable binary format by the compiler and linker, and which contain the machine instructions that represent the program logic along with other information and metadata]. Therefore, there's no way to detect at runtime which properties are nullable and which are not.

Why is a ObjC 'NSString * _Nullable' is transformed to a 'String!' property in Swift

In my Objective C code I have the property:
#property (nonatomic, readonly) NSString * _Nullable myNullableString;
I wanna use it in my Swift code but in this case, Xcode / Sourcekit thinks that myNullableString has not the type String? but has the type String!.
Due to this fact a guarded unwrapping the property is incorrect but also a forced use is incorrect and will lead to a crash of Xcode / SourceKit or to an segfault if I wanna build it.
Any idea how to solve it?
Null is not the same as nil.
A string that is Null is a non initialized string but a string nonetheless while in swift you have something that's called 'optional' that doesn't exist in obj-c.
so String? means that the function will return eaither a full fledged string or nil which is something undefined(not non-initialized).
so in fact the closest thing in swift is String!" which is an
obligatory string(cannot return nil).
edit: As pointed out by Martin in the comments-the first part of the above mentioned statement is incorrect

Key-Value Coding with a key of 'description'

I am using Key-Value Coding to simplify updating instances of a model class:
#interface NewsItem : NSObject
{
}
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *description;
#property (nonatomic, copy) NSString *link;
#property (nonatomic, copy) NSString *date;
using:
SEL selectorName = NSSelectorFromString(elementName);
if ([self.newsItem respondsToSelector:selectorName])
{
NSString *sanitisedElement = [self sanitiseElement:self.currentElementData];
[self.newsItem setValue:sanitisedElement forKey:elementName];
}
This works well but the 'description' property doesn't 'smell' right to me as it has overridden the base NSObject description getter (+ (NSString *)description). If the description getter is invoked now it will return irrelevant information when the caller would be expecting a description of the class.
Is it possible to safely proceed with Key-Value Coding for this class (given that I am bound to these property names by the external data source)? Or would it be wise to change the property names and manually check keys/set values instead?
You could override description in your class. This method is usually used only for debugging
and no caller can expect a specific output of that method.
But I see more general problems in your code. It is only checked that a method with the
given name exists. This does not imply that this method corresponds to a property, and even then, it does not imply that there is a setter for that property.
For example, every NSObject responds to the selector "init", so if the external
data source sends that key as "elementName", your code would immediately crash.
Therefore, an explicit list of "known keys" is needed. But then you can as well
use a mapping (NSDictionary) from external element names to internal properties
to avoid any conflicts.
I think that you are confusing methods with properties, and you are making things more complicated that how they are.
Is enough that, given an elementName that contains directly the setter name (i.e.: setDate), you invoke the selector passing that argument the object argument:
SEL selectorName = NSSelectorFromString(elementName); // elementName something like "setDate"
if ([self.newsItem respondsToSelector:selectorName])
{
[self.newsItem performSelector: selectorName withObject: sanitisedElement];
}
As for the description method, it has overridden NSObject's description, so you have two choices: name it in another way, or leave it like it is, and invoke it on super when you need the object description, with the help of Objective-C runtime:
struct objc_super superclass= { self.newItem, [self.newItem superclass] };
NSString* desc= objc_msgSendSuper(&superclass, #selector(description));
You can always override inherited methods.
By creating a property whose getter is the same as the signature of An inherited method, you are overriding it.
Is it bad? Yes if your implementation is not useful for debugging.
As best practice for KVC and KVO purposes it is a good idea to avoid potentially clashing with common inherited methods properties and ivars.
The common approach to this is to make longer property and method names and to make them more likely to be unique. One common way is by prefixing all yours with an abbreviation common to your class or framework or code.
Using something commonly used by Apple is likely to bite you in a rare and hard to debug way.
It's especially a bad idea to do this when core data is involved.
Don't be reluctant to make things longer. Code completion will type for you. Plus, a nice side effect of class specific prefixing is pseudo not only the pseudo namespace but that your class specific properties, variables, constants and methods will bubble up first in code completion.

Semantic Issue: Property's synthesized getter follows Cocoa naming convention for returning 'owned' objects

I'm currently using the iOS 5 SDK trying to develop my app.
I'm trying to make an NSString a property, and then to synthesize it in the .m file (I have done this before with no issues). Now, I came across this: "Semantic Issue: Property's synthesized getter follows Cocoa naming convention for returning 'owned' objects."
This is my code:
.h
#interface ViewController : UIViewController {
NSString *newTitle;
}
#property (strong, nonatomic) NSString *newTitle;
.m
#synthesize newTitle;
Does anyone have a clue how I could fix this?
Thanks!!
My guess is that the compiler version you’re using follows the memory management rules for declared properties, too — more specifically, for declared properties’ accessors:
You take ownership of an object if you create it using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy”.
A property named newTitle, when synthesised, yields a method called -newTitle, hence the warning/error. -newTitle is supposed to be a getter method for the newTitle property, however naming conventions state that a method whose name begins with new returns an object that’s owned by the caller, which is not the case of getter methods.
You can solve this by:
Renaming that property:
#property (strong, nonatomic) NSString *theNewTitle;
Keeping the property name and specifying a getter name that doesn’t begin with one of the special method name prefixes:
#property (strong, nonatomic, getter=theNewTitle) NSString *newTitle;
Keeping both the property name and the getter name, and telling the compiler that, even though the getter name starts with new, it belongs to the none method family as opposed to the new method family:
#ifndef __has_attribute
#define __has_attribute(x) 0 // Compatibility with non-clang compilers
#endif
#if __has_attribute(objc_method_family)
#define BV_OBJC_METHOD_FAMILY_NONE __attribute__((objc_method_family(none)))
#else
#define BV_OBJC_METHOD_FAMILY_NONE
#endif
#interface ViewController : UIViewController
#property (strong, nonatomic) NSString *newTitle;
- (NSString *)newTitle BV_OBJC_METHOD_FAMILY_NONE;
#end
Note that even though this solution allows you to keep newTitle as both the property name and the getter name, having a method called -newTitle that doesn’t return an object owned by the caller can be confusing for other people reading your code.
For the record, Apple have published Transitioning to ARC Release Notes, in which they state:
You cannot give a property a name that begins with new or copy.
They’ve already been notified that their statement is not quite accurate: the culprit is the getter method name, not the property name.
Edit 17 Jan 2015: I’ve just noticed a recent commit to Clang that suggests option 3 above (using objc_method_family(none)), including a fix-it, for the general case where a property name matches one of the special method family prefixes. Xcode will likely incorporate this change eventually.
Unacceptable Object Names
newButton
copyLabel
allocTitle
Acceptable Object Names
neueButton
mCopyLabel
_allocTitle
#arc #auto-synthesized #xcode-4.6.1
** EDIT **
Apparently you can't use mutableCopy either.
The name of the member starting with new is what triggers the warning. Change the name to editedTitle and the warning will go away. I was unable to find documentation confirming this but through testing was able to determine that member variables that begin with 'new' aggravate the compiler.
ARC does not allow to use "New...." in property name. but you can use "newTitle" by changing getter name.
#property (nonatomic, strong, getter=theNewTitle) NSString *newTitle;
It doesn't look like what Bavarious was suggesting was what you wanted to do. All you want to do is declare an instance variable NewTitle and then synthesize the property. We used to have to declare the instance variable and property. No more.
Now, I believe the right way of doing this is the following:
.h
#interface ViewController : UIViewController
#property (nonatomic, strong) NSString *newTitle;
.m
#synthesize newTitle = _newTitle; // Use instance variable _newTitle for storage
The instance variable for the property newTitle is synthesized. You don't want your instance variable to be the same as your property - too easy to make mistakes.
See Example: Declaring Properties and Synthesizing Accessors
In CoreData if you use "new..." in attribute (compile normally) it will crash randomly with a "bad access" exception.
There is no crash log and the line shown with the "All Exceptions Breakpoint" will not help you at all.
Writing a setter manually with the name same as the property's removed this warning.
NS_RETURNS_NOT_RETAINED is used to solve the naming problem.
#property (nonatomic, copy) NSString *newTitle NS_RETURNS_NOT_RETAINED;
We can find its definition as follows:
#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
The 'ns_returns_not_retained' attribute is the complement of 'ns_returns_retained'. Where a function or method may appear to obey the Cocoa conventions and return a retained Cocoa object, this attribute can be used to indicate that the object reference returned should not be considered as an "owning" reference being returned to the caller. The Foundation framework defines a macro NS_RETURNS_NOT_RETAINED that is functionally equivalent to the one shown below.
Besides the issue that you should/can't use "new" in front of you property names, let say one more thing: Try to avoid "new" in front of names in general. "New" is dependent on time. Currently it is new for you, but some time later you maybe want to implement something new again. So using "new" in names is always bad. Try to think this way: In the programming world, "new" is always creating something: a new instance of something.
In your case when you want to assign a different title then the current name your property titleReplacement.
One more thing: Try to name functions and methods with the verb first, like setSomething or getSomething.
But in properties try to name the object first, like heightMinimum, heightMaximum, etc. -> when you use your inspector when you are coding, you always looking for objects. Try it out. ;-)
try this:-
#property (nonatomic,retain) NSString *newTitle;

How Apple manage #private var and #properties?

I take for example the UIButton interface.
Here the first rows of #private definition :
#private
CFMutableDictionaryRef _contentLookup;
UIEdgeInsets _contentEdgeInsets;
UIEdgeInsets _titleEdgeInsets;
And here 2 of these ivar, that are defined as properties:
#property(nonatomic) UIEdgeInsets contentEdgeInsets;
#property(nonatomic) UIEdgeInsetstitleEdgeInsets;
However these 2 properties are not defined on the ivars i found in private method (which have suffix _).
I'm not sure to understand how could be implemented setter and getter for these 2 properties to refer to the private ivars.
And a second question... i used to create properties for ivar, thus, if i have an ivar FOO i can create a #property for FOO. Is it a normal behavior create property for a non existing ivar ? (in this case contentEdgeInsets is not an attribute for this class... on the contrary _contentEdgeInset is defined in #interface and this's a valid ivar). Ok what i missed with this argument ?
When you #synthesize these properties you do so like
#synthesize contentEdgeInsets = _contentEdgeInsets;
^property name ^iVar name
Check out the Property Implementation Directives section in the documentation.
By default, a property will use the ivar whose name is the same as that of the property, but it's also possible to specify an ivar of a different name. Do this in your #synthesize statement in the class implementation.
In the modern runtime, used pretty much everywhere at this point, you don't actually have to declare the ivar at all -- if you synthesize accessors for a property and there's no matching ivar, the runtime will provide one.
Finally, properties with #dynamic rather than #synthesized accessors don't necessarily need an ivar at all -- you're providing the accessors in this case, so you're free to derive the value of the property however you like.