How can I declare a private property within a named category? - objective-c

I know about the possibility of declaring private properties on a class by putting them inside an unnamed category on that class declared in the implementation (.m) file of that class. That's not what I want to do.
I'm dealing with a named category on a class that adds some functionality to that class. For this functionality, it would help me very much to have a private property to use in my category - so the usual way of achieving this (described above) doesn't seem to work for me. Or does it? Please enlighten me!

Inside your category's implementation file, declare another category and call it something like MyCategoryName_Private, and declare your private properties there. Provide implementations of the -propertyName and -setPropertyName: methods using associated objects.
For example, your implementation file might look like this:
#import "SomeClass+MyCategory.h"
#import <objc/runtime.h>
#interface SomeClass (MyCategory_Private)
#property (nonatomic, strong) id somePrivateProperty;
#end
#implementation SomeClass (MyCategory_Private)
static void *AssociationKey;
- (id)somePrivateProperty
{
return objc_getAssociatedObject(self, AssociationKey);
}
- (void)setSomePrivateProperty:(id)arg
{
objc_setAssociatedObject(self, AssociationKey, arg, OBJC_ASSOCIATION_RETAIN);
}
#end
#implementation SomeClass (MyCategory)
// implement your publicly declared category methods
#end

Related

Better way to declare properties as protected

Following this blog post, I saw a way to solve the problem I was facing.
My problem, like his, was that I have a class that has a property which must be inherited and accessed in its subclass:
#interface A : NSObject
#property (nonatomic, readonly) NSUInteger prop;
#end
#implementation A
// Don't need to synthesize nowadays
#end
#interface B : A
// No new properties
#end
#implementation B
- (void)establishValueForProp
{
_prop = 1; // PROBLEM !!!
}
#end
The solution was this:
#interface A : NSObject {
#protected
NSUInteger _prop;
}
#property (nonatomic, readonly) NSUInteger prop;
#end
What I'm wondering is if there is another way to declare properties as protected?
The way I typically do this is to create a second header, called e.g. "ClassName_ForSubclasses.h". Inside that header file, add a class extension with the properties and methods you want subclasses to be able to call and override. Then, subclasses can import that header, while other users of the class(es) don't see it.
Another common way of doing it, is by creating a separate .h file (ASubclass.h, for example) and adding something like this:
#interface A (Protected)
#property (nonatomic, readonly) NSUInteger prop;
#end
Subclassers can then import this .h and will have access to this method. Note that since categories can't add properties, you'll have to redefine this property in A's private interface (class extension). The category will then provide public access to this property. Apple takes this exact approach with UIGestureRecognizer.h and UIGestureRecognizerSubclass.h (where UIGestureRecognizer.h exposes more methods, intended for subclassers to override).
The concept of protected (or private, for that matter) methods doesn't really exist, and this is only a way to somewhat achieve similar functionality.
Personally, I just create a category in the (only) .h file of the class that exposes an otherwise public property. This way it's separated from the main public interface, and since it's possible to get to private properties anyway, I think this approach is good enough.

Best way to define private variables in Objective-C

I want to define private instance variables in MyClass.m file. It seems to me there are two ways to do it:
use class extension
#interface HelloViewController ()
{
int value;
}
define in #implementation section
#implementation HelloViewController
{
int value;
}
Which is better?
I think recent Apple's coding style is to use class extension?
e.g. MasterViewController.m generated by 'Master-Detail Application Template'
#interface MasterViewController () {
NSMutableArray *_objects;
}
#end
The "Modern Objective-C" way to do this is to declare them in your implementation block, like this:
#implementation ClassName {
int privateInteger;
MyObject *privateObject;
}
// method implementations etc...
#end
See this earlier post of me with more details.
#interface HelloViewController ()
{
#private //optional, this is old style
int vale;
}
If you were making a library, though, theoretically no one would know about any methods you didn't declare in the header files.
Copied from: How to make a real private instance variable?
Declaring instance variables in the #implementation is a recent
feature of Obj-C, this is why you see a lot of code with them in the
#interface - there was no other choice.
If you are using a compiler which supports declaring instance
variables in the implementation declaring them there is probably the
best default - only put them in the interface if they need to be
accessed by others.
Instance variables declared in the implementation are implicitly
hidden (effectively private) and the visibility cannot be changed -
#public, #protected and #private do not produce compiler errors (with
the current Clang at least) but are ignored.
Copied from: Private ivar in #interface or #implementation
In my view the best is to define it like private properties that you can access as fields or properties just within your implementation, the advatage is that you can access them by self as well as by _fieldName syntax what is handy in some situations.
#interface SignUpController ()
#property ViewHeaderView*header; //private properties/fields
#property UITextField*activeField;
#property CGFloat keyboardHeight;
#end
#implementation SignUpController {
}
#end

Inheriting accessors in Objective-C

this is my first post; this site has been an invaluable resource.
I'm fairly new to objective-c so please bear with.
So I have a base class with a few properties which I want "private" so I made them readonly. To be clear, I don't want them mutable externally, but I DO wan't to use the 'set' accessor within this class. So...
// .h file
#interface Vehicle
#property (nonatomic, readonly) int speed;
#end
Also I repeated the property declaration within a category interface block to make the accessors writable in this class
// .m file
//Private properties and methods
#interface Vehicle()
#property (nonatomic, readwrite) int speed;
#end
#implementation
#synthesize speed = _speed;
- (void) someMethod {
[self setSpeed:10]; // Works fine
}
#end
But now if I inherit this class the derived class no longer has the set accessor method (setSpeed in my case). Do I need to synthesize again? Seems like that would defeat the purpose of inheritence. I know i can modify the instance variable directly (_speed = 10;) but would rather not. I'm sure there's something wrong with my understanding. Thanks!
// Example
#interface Ship : Vehicle
#end
#implementation
- (void) someOtherMethod {
[self setSpeed: 2]; // DOES NOT WORK, would like it to
}
#end
But now if I inherit this class the derived class no longer has the set accessor method (setSpeed in my case).
Actually, it does have the set accessor, it's just that the compiler doesn't know about it. You have a choice:
put the class extension (the #interface Vehicle() .... #end bit in a separate header file that gets imported into the .m for Vehicle and its subclasses (or use a category)
redeclare the read/write property in a class extension for the subclass. To avoid a warning, use #dynamic speed in the subclass's implementation.
Since there is no such thing as 'protected' methods, you need to create a private shared header where your anonymous category goes. Then both your original implementation and your derived classes include this header to get access to this 'private' stuff.

Public iVar; readonly from other classes

What is the best way to make an iVar writeable by its owning class, but readonly by other classes?
Is there more than one way?
The only way I can think of is to set a #property (readonly) for the iVar, but not use dot notation inside the owning class (which I'm guessing wouldn't work with readonly), and in the owning class just reference it directly, without dot notation, then in other class, reference it with dot notation.
But I'm curious if there are other methods.
You can make a property read/write just for the implementation. You do this using a class extension, or anonymous category, in your implementation. Easier to demonstrate so, for example, in your .h:
#interface MyClass
#property (readonly) NSInteger age;
...
#end
and in your .m:
#interface MyClass () // class extension/anonymous category for private methods & properties
// implementation of these go in main #implementation
#property (readwrite) NSInteger age;
...
#end
#implementation MyClass
#synthesize age;
...
#end
Now you can use the property within your class read/write and from outside as read-only.
You do the same for private methods.
[Note: This is Objective-C so the above isn't bullet proof - there are ways around it to call the properties setter - but the compiler will flag errors which assign to the property from outside the class.]
After comments:
[Note 2: an anonymous category/class extension is very similar to a named category. The former must be implemented in the main implementation, the latter may be implemented in an #implementation classname (categoryname) or in the main implementation. Furthermore only the main interface, the interface for a class extension/anonymous category, and the main implementation may declare instance variables; interfaces and implementations for named categories may not. Properties may be declared in both anonymous and named categories, however they may only be synthesized in the main implementation and not in named category implementations. This note is correct at press time, some of these features have changed as Objective-C/Xcode develops.]
Use the private specifier for ivars and a class extension to define the accessor - that way the ivar is private to the class.
// FooClass.h
#interface FooClass : NSObject {
#private int boo;
}
#end
// FooClass.m
#interface FooClass () {
}
#property (nonatomic,assign) int boo;
#end
#implementation FooClass
#synthesize boo;
// ....
#end

Add ivars in #implementation

For good encapsulation, decent Objective-C programmers put their private ivars in a private extension declared in the main implementation file, like this:
// MyClass.m
#interface MyClass () {
float value;
}
#end
#implementation MyClass
#end
But recently, I found a simpler way to hide private ivars: ivars can be declared in a {} block following #implementation, like this:
// MyClass.m
#implementation MyClass {
float value;
}
#end
It is really handy when no private methods but only private ivars need to be hidden.
However, I'm not sure about its syntax validity. Can anyone validate or invalidate it with some canonical references?
It's perfectly valid and here is a document by Apple talking about it:
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html#//apple_ref/doc/uid/TP40011210-CH5-SW6
I don't personally use it as I prefer the syntax of a class continuation category.
I was also curious about this. Here is the updated link from Apple:
You Can Define Instance Variables without Properties
It’s best practice to use a property on an object any time you need to keep track of a value or another object.
If you do need to define your own instance variables without declaring a property, you can add them inside braces at the top of the class interface or implementation, like this:
#interface SomeClass : NSObject {
NSString *_myNonPropertyInstanceVariable;
}
...
#end
#implementation SomeClass {
NSString *_anotherCustomInstanceVariable;
}
...
#end