Naming pattern for Objective-C category property getters? - objective-c

When creating a class, a BOOL property declaration often looks like this:
#property (nonatomic, getter=isActive) BOOL active;
For normal classes and subclasses, naming the getter is<#Key#> makes sense, looks sharp, and is nice to use in if statements.
What about when naming properties in a category though?
I was just implementing some helper methods on NSView, when all of the sudden, things took a hideous turn:
#property (nonatomic, readonly, getter=bsd_isFieldEditorDelegate) BOOL bsd_fieldEditorDelegate;
After adding the recommended prefix (bsd_ in my case), the semantic value of the getter variation seems to get lost. In this case, should I just remove the getter name altogether or what?
I looked throughout the documentation, but I couldn't find a definitive answer. Is there one, or am I just overthinking it?

You CANNOT use property in Category of Objective-C. Instead of, you should use Associated object of Objective-C Runtime. Because of that, attribute of property is may not work with Associated object.
Reference: Objective-C: Property / instance variable in category

Related

Safe mutation and usage of readonly property value in Objective-C APIs

Consider a C++ API like const T* foo(). This clearly documents the supported mutability and use of the API: OK, we'll let you look at T, but please don't change it. You can still mutate it, but you have to explicitly use const_cast to indicate your intention to not follow the API.
A good portion of Objective-C API's are comprised of property declarations. How is a user of an API supposed to interpret: #property (readonly) T foo ? (Assume T isn't an immutable type)
Since the setter isn't synthesized, clearly foo isn't mean to be replaced.
However, the getter still gives me a pointer to foo. Is it safe to mutate foo? (Clearly I can)
NOTE: I'm not asking about the language specs. I'm asking about what the conventional interpretation of an API like this is within the Objective-C community.
As matt said, the fact that you've got a pointer to the object does not mean that the object itself is mutable. Objective-C uses the behavior of the class, not the pointer, to enforce immutability. So in general you should be seeing read-only properties that return, e.g., NSString rather than NSMutableString.
I took a look through Apple's iOS framework headers to verify this:
grep -rn "#property.*readonly.*Mutable" /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/*.h
(The pattern for class names in Cocoa is to call the mutable "version" of the class $PREFIXMutable$CLASSNAME: NSString/NSMutableString, NSDictionary/NSMutableDictionary.)
./System/Library/Frameworks/AVFoundation.framework/Headers/AVComposition.h:133:#property
(nonatomic, readonly) NSArray<AVMutableCompositionTrack *> *tracks;
./System/Library/Frameworks/CoreData.framework/Headers/NSManagedObjectContext.h:149:#property
(nonatomic, readonly, strong) NSMutableDictionary *userInfo
NS_AVAILABLE(10_7, 5_0);
./System/Library/Frameworks/Foundation.framework/Headers/NSAttributedString.h:54:#property
(readonly, retain) NSMutableString *mutableString;
./System/Library/Frameworks/Foundation.framework/Headers/NSExpression.h:127:#property
(readonly, copy) id (^expressionBlock)(id __nullable, NSArray *,
NSMutableDictionary * __nullable) NS_AVAILABLE(10_6, 4_0);
./System/Library/Frameworks/Foundation.framework/Headers/NSThread.h:24:#property
(readonly, retain) NSMutableDictionary *threadDictionary;
./System/Library/Frameworks/GameplayKit.framework/Headers/GKRuleSystem.h:54:#property
(nonatomic, retain, readonly) NSMutableDictionary *state;
./System/Library/Frameworks/ModelIO.framework/Headers/MDLMesh.h:137:#property
(nonatomic, readonly, retain) NSMutableArray *submeshes;
Only seven results, and the one in NSExpression doesn't count because the "Mutable" that the search found is an argument to the Block that is actually the property's value.
For the others, I think you'll find that the appropriate class reference doc tells you what you can and can't do with the values.
For example, the documentation for threadDictionary has this to say:
You can use the returned dictionary to store thread-specific data.[...]You may define your own keys for the dictionary.
A mutable dictionary is returned precisely so that you can mutate it. The thread object doesn't let you set it, however, so that it can also store things there.
The hit in NSAttributedString.h is actually in the NSMutableAttributedString class, and those docs note:
The receiver tracks changes to this string and keeps its attribute mappings up to date.
Since NSAttributedString is pretty explicitly* just an NSString packaged up with a bunch of attributes, the design of the class exposes the wrapped string directly; the mutable version follows suit.
UIButton was mentioned in the comments, because there you have a read-only label whose own properties are modifiable. And there again, the docs are explicit:
Although this property is read-only, its own properties are read/write. Use these properties primarily to configure the text of the button.
and
Do not use the label object to set the text color or the shadow color.
In summary, there's no way in Objective-C at the language level to create or enforce mutability restrictions. As you've noted, a property marked readonly simply means there's no way for you to set the value to something else.** And there's no equivalent of const_casting the value to be mutable so that you can change it: you will end up with a new value that the vendor object knows nothing about.
The Cocoa convention, then, is to secondarily enforce the property's status by using immutable classes. (In some cases you might even be getting an immutable copy of data that the class internally retains as mutable.) If the API gives you a mutable object, you can assume that you may mutate it, but the documentation should tell you exactly how you can use it.
*Its class description says: "An NSAttributedString object manages character strings and associated sets of attributes (for example, font and kerning) that apply to individual characters or ranges of characters in the string."
**There is KVC, but that's again at the framework level, and framework convention would indicate that you're asking for trouble doing that.

How does Objective-C handle subclasses and superclasses with the same property name?

In iOS 8 NSManagedObject was given a new property:
#property (nonatomic, getter=isDeleted, readonly) BOOL deleted;
Unfortunately, I have already been using a property of the same name in my subclasses of NSManagedObject to mark objects as soft deleted.
#property (nonatomic, retain) NSNumber *deleted; // BOOL in CoreData model
This results in a ton of compiler warnings:
'getter' attribute on property 'deleted' does not match the property inherited from 'NSManagedObject'
How does Objective-C handle a superclass and subclass having the same property? I obviously plan on renaming this property across the board but there is already multiple versions of this app in the wild and I am curious of the implications.
#property accessors are just regular methods, so they're handled exactly the same way as other methods. In this case, I believe you luck out because the framework (NSManagedObject) getter is -isDeleted rather than -deleted. Since your subclass implements -deleted, there's technically no conflict with the getter.
Now, the real issue will be, if NSManagedObject internally implements the corresponding -setDeleted: setter, your subclasses implementation of that method will be called instead of NSManagedObject's implementation. A quick check using -instancesRespondToSelector: seems to reveal that NSManagedObject does not actually implement -setDeleted: (on OS X, anyway). So, you might be OK.
The actual implications of a conflict like this for your app (assuming a case where you weren't lucky as described above) are not clear to me, not knowing exactly what your app is doing or why. For what it's worth, the -isDeleted method on NSManagedObject is not at all new. It was simply promoted to a declared #property in iOS 8 (presumably to ease Swift interoperability). It was probably always a bad idea to have your own deleted property...

Why do I declare properties twice? or do I?

Sorry for the kind of useless post title, but since I'm not really sure what I am doing, that was the best i could come up with.
In my header file it looks like this
#interface RootViewController : UITableViewController {
NSMutableArray *eventsArray;
}
#property (nonatomic, retain) NSMutableArray *eventsArray;
#end
This is not all the properties but i removed all but one for simplicity.
I'm doing this by following a guide from apple developer. It seems as though the guide is not totally updated since it tells me to synthesize properties, wich i should not have to anymore right?
Anyways, why is it like this? To me, a beginner at this, it seems as though I declare the property twice? Or do I do something else at the first row there?
It's like this for historical reasons, with the older compiler.
You can do this nowadays:
#interface RootViewController : UITableViewController
#property (nonatomic, retain) NSMutableArray *eventsArray;
#end
The way you have it, you are declaring an instance attribute, and then you are saying you want to automatically generate getters and setters.
Nowadays, you can just say you have a property and the compiler will automatically generate the instance attribute at compile time. It removes the apparent redundancy.
To me, a beginner at this, it seems as though I declare the property
twice? Or do I do something else at the first row there?
A property and the instance variable that backs it up (if there is one) are two different things. A property is really just a promise that the class provides certain accessor methods. So the fact that you had to declare the property and ivar separately isn't strange. However, most properties are, in fact, backed by an ivar with a related name, and writing and maintaining the two separately got to be a chore. So Apple added ivar synthesis to the compiler, so that the compiler generates an ivar for any synthesized properties for which an ivar doesn't already exist. Also, because synthesized accessors are by far the most common, and because the compiler will use any accessors that you provide even if a property is marked #synthesize, that became the default so that you no longer need the compiler directive.

Question regarding #property

I'm kinda new in Obj-C and I would like to ask why everything need to write something like this?
#property (_something, _something) NSString* name;
What is the #property indicates for?
Why we need to put _something in the bracket?
PS: I know there is no _something, it should be nonatomic, retain, copy and so on. Since it has so many options, that's why I simply put a word to indicate the content inside the bracket.
(Where can I get all the list of available options?)
Thanks :D
#property indicates that you are defining a property, which is at the basic level just syntactic sugar that allows you to do variable = object.property and object.property = value instead of variable = [object property] and [object setProperty:value]. If you really wanted, you could skip declaring any properties and just declare the getter and setter methods directly and the runtime would hardly notice the difference.
The things inside the parentheses modify the property. Many are only useful for properties whose getter and/or setter implementations are created for you using #synthesize in the #implementation block. For example, assign (the default) says that the value set is just set; retain says that the object set will automatically have its retain method called (and the previous object, if any, will have release called); and copy says that the object will have its copy called.
A list of possible attributes is in the documentation.
The #property directive is simply a promise that the class provides accessors for the given identifier. Options given after the directive (copy, nonatomic, etc.) specify how the accessors behave. That's really all there is to it.
Related syntax includes the directives #dynamic and #synthesize and dot notation. The two directives are mutually exclusive and tell the compiler that you'll supply the accessors or that the compiler should supply the accessors, respectively. Dot notation is the syntactic sugar that Anomie mentioned -- it's meant for accessing properties, but you're not required to formally declare a property to use it.

why to declare some instance variables as properties

Though this is somewhat a very basic question but I have some doubts still left after reading so many documents and questions on stackoverflow.com.
I want to know why to declare some instance variables as properties.
MYViewController.h
#interface MyViewController : UIViewController {
UIButton *btn;
NSString *name;
}
#property (nonatomic, retain) UIButton *btn;
#property (nonatomic, retain) NSString *name;
MyViewController.m
#implementation MyViewController
#synthesize btn;
-(void) viewDidLoad()
{
[btn setTitle:#"Hello" forState:UIControlstaeNormal]; //this is first way where there is no need to declare btn as property
[self.btn setTitle:#"Hello" forState:UIControlstaeNormal]; //this is second way where we do need to decalre btn as property as we are accessing it through self
//Setting value of name
name = #"abc"; //this is first way where there is no need to declare name as property
[self setName:#"abc"; //this is second way where we do need to declare name as property as we are accessing its aetter method through self
}
Now in the above code I wanna know when we can use the getter/setter methods of btn variable without declaring it as property then what is the need to declare it as property and which is the better way to set the value of "name".
Somewhere I read that when you want your instance variables to be accessed my other class objects then you should declare them as instance variables. Is it the only situation where we should declare them as properties.
Basically I am a little confused about in which situations to declare the instance variables as properties.
Please suggest.
Thanks in advance.
In short, you don't have to declare instance variables as properties unless you want to.
You declare a variable as a property in order to auto-generate getter and setter methods. In your property declaration you can specify how you want them set up (retain vs assign, atomic vs nonatomic). Then, the getter and setter are generated with the #synthesize directive.
So, again, there is no right or wrong way to use properties. Some people never use them, some people make every variable a property. It's really up to you.
typically, you'll use them because:
1) the property belongs in the public interface of the class
used when the class needs to expose a given method. the downside is that clients and subclasses may abuse the public interface (all objc methods are public, where visible), unless you're careful to hide these details (which is also a pain at times). sometimes you're forced to go well out of your way in order to achieve the class interface you need (with the proper levels of visibility).
2) you want auto-generated accessors
implementing nonspecialized accessors is tedious, and error prone. it's better to save the time and let the compiler generate them for you.
3) to document behavior
sometimes it's better to write #property (copy) NSString * title; instead of over-documenting the expected result.
4) stricter selector matching with dot-syntax
the compiler performs stricter selector matching. prefer to catch the errors/issues at compilation, if possible.
5) to force the subclasses to use them instead of handling the ivars directly
objc ivars are protected by default. you'll often want them to be private (depending on how the class is used and distributed, or just to ensure the subclass uses the base class correctly).
there are a ton of reasons for this. threading and maintenance are the big ones.
if you declare the ivar as private and provide a property for the subclass to use, then the subclass is forced to use the property in their implementation (although there are ways they could cheat) rather than giving them direct access to the ivar.
so... it ultimately depends on your preference, and the implementation details of your class, paired with the interfaces you're using. i don't think there's a hard and fast rule here - lesser evils and convenience are key motivations.