Subclassing PFObject And Overriding Dynamically Added Accessors - dynamic

I understand how to subclass PFObject, but I am not certain how to perform additional custom code in an accessor, while still calling the generic implementation of that accessor as defined and #dynamic-ally added by Parse (which does the proper thing depending on the property's type, e.g. PFRelation, and so forth).
For instance...
// MyPFObjectSubclass.h
#import <Parse/Parse.h>
#interface MyPFObjectSubclass.h : PFObject<PFSubclassing>
#property (retain, nonatomic) id myProperty;
+ (NSString *)parseClassName;
#end
// MyPFObjectSubclass.m
#import "MyPFObjectSubclass.h"
#import <Parse/PFObject+Subclass.h>
#implementation MyPFObjectSubclass
#dynamic myProperty;
+ (NSString *)parseClassName {
return #"MyPFObjectSubclass";
}
- (void)setMyProperty:(id)someProperty {
// insert some custom code here, e.g. for validation...
// call the generic, dynamic implementation of setMyProperty, but how?
// obviously, you cannot call [super setMyProperty:someProperty];
}
#end
Any help is appreciated.

All you need to do is implement your own accessors and skip #dynamic

Related

add category property to a class confirming to a protocol

I have a generator which returns objects conforming to protocol A.
I would like to add a property, probably with categories, to these objects so i can do something to serve my purposes, which obviously isn't there in the protocol.
is this doable?
The more I've thought about this, the more I agree that it's not a duplicate, and in fact the answer is very straightforward as long as what you say you want is what you really want.
Given that you are returning values that conform to some protocol, create a type that conforms to that protocol, and forwards all protocol methods to a wrapped value. Then you can add whatever additional properties you'd like.
For example, given a protocol like:
#protocol Runnable <NSObject>
- (void)run;
#end
You can create a trivial wrapper like:
#interface AnyRunnable: NSObject <Runnable>
- (instancetype)initWithRunnable:(id<Runnable>)runnable;
#end
#interface AnyRunnable (Private)
#property (nonatomic, readwrite) id<Runnable> wrapped;
#end
#implementation AnyRunnable
- (instancetype)initWithRunnable:(id<Runnable>)wrapped
{
self = [super init];
if (self) {
self.wrapped = wrapped;
}
return self;
}
- (void)run {
[self.wrapped run];
}
#end
Now, AnyRunnable is a Runnable, so you can return that from your method. It's also a type you control, so you can add any properties you like to it. This scales to any protocol; you just need to implement the required methods.
It's not possible to do this via a category for the reasons given in Why can't categories have instance variables? (If it were possible to add properties based on protocols, but not classes, then you could just define a protocol that matched your class, and bypass that limitation.)
Here is possible approach (based on Objective-C associated objects). Tested & worked.
Assume we have some class, which we cannot touch
#interface SomeClass: NSObject
#end
#implementation SomeClass
#end
Then some new properties can inject in the following way
#interface SomeClass (VirtualProperty)
#property (atomic) NSInteger virtualProperty;
#property (nonatomic, readonly) NSInteger calculableProperty;
#end
static const char *kVirtualPropertyKey = "virtualProperty";
#implementation SomeClass (VirtualProperty)
#dynamic virtualProperty;
- (NSInteger)calculableProperty {
return self.virtualProperty * 2;
}
- (NSInteger)virtualProperty {
return [(NSNumber *)objc_getAssociatedObject(self,
kVirtualPropertyKey) integerValue];
}
- (void)setVirtualProperty:(NSInteger)newValue {
objc_setAssociatedObject(self, kVirtualPropertyKey,
#(newValue), OBJC_ASSOCIATION_RETAIN);
}
#end
Usage:
SomeClass *some = SomeClass.new;
some.virtualProperty = 5;
NSLog(#"Result: %lu", some.calculableProperty);

Can a category access instance variables defined in the class it extends?

I know it's not a great idea to try and place properties in a category. Can I access a class' instance variables from within a category that extends it? Or is it necessary to expose an accessor on the class being extended?
For example, let's say I have a class called "Person" and its implementation looks like this:
#import "Person.h"
#interface Person()
{
NSMutableArray *_friends;
}
#end
#implementation Person
- (instancetype)init
{
self = [super init];
if (self) {
_friends = [NSMutableArray array];
}
return self;
}
-(instancetype)initWithFirstname:(NSString *)firstName lastname:(NSString *)lastName
{
self = [self init];
if (self) {
_firstName = firstName;
_lastName = lastName;
}
return self;
}
-(NSString *)getFullName{
return [NSString stringWithFormat:#"%# %#", _firstName, _lastName];
}
#end
Notice the ivar _friends. Let's say (for some reason or other) I wanted to segregate all operations dealing with a person's friends into a category, like so:
#import "Person.h"
#interface Person (Friends)
-(NSArray *)getFriends;
-(void)addFriend:(Person *)person;
-(void)removeFriend:(Person *)person;
#end
In the category, Person(Friends), the compiler will not know about Person's ivar _friends.
i.e.
//Person.h
#interface Person
#property(nonatomic, strong) NSMutableArray *friends;
...
#end
It would be preferable to not expose this.
In general, categories can't access ivars; synthesized ivars and ivars from class extensions are private and invisible outside the main implementation.
You can, however, do what you want by declaring the ivar in an extension which is in its own private header, and importing that header into the category's implmentation file. Be sure to also import the private header into the class's main implementation file.
Who have told you that the compiler will not know about Person's _friends?
It knows. Just declare _friends in the class #interface, not in an extension.
#interface Person : NSObject
{
#protected
NSMutableArray *_friends;
}
#end
With #protected _friends will not be accessible for other objects.
If you've got a lot of protocols, delegates, dataSources etc. on your e.g. MainViewController and you wanna outsource their callbacks to separate files (categories) like
"MainViewController+DelegateCallbacks.h"
"MainViewController+DelegateCallbacks.m"
but at the same time still wanna be able to access all the controller's private #properties from these categories without having to expose them in the public interface
"MainViewController.h"
the most elegant solution is still to create a private interface (extension) in a separate header file like
"MainViewController_PrivateInterface.h"
BUT - instead of the ivars - like Josh Caswell's already explained above, put all the #properties (that these outsourced delegates need to access) in that extension, too. That way you keep them all quasi-private hidden and nobody else gets to see them. Above all not in your public interface! And you do even have the choice to access your #properties' backing store ivars directly in code (instead of the convenience dot notation) just by manually creating the corresponding backing store ivars in this private external interface file. Just don't forget to import your private's interface header everywhere you wanna access these ivars (including your MainViewController ;-)
//
// MainViewController.m
//
#import "MainViewController.h"
#import "MainViewController+DelegateCallbacks.h"
#import "MainViewController_PrivateInterface.h"
#interface MainViewController () <UICollectionViewDelegate,
UICollectionViewDataSource,
UICollectionViewDelegateFlowLayout,
UIGestureRecognizerDelegate>
#pragma mark - <UIGestureRecognizerDelegate>
#pragma mark - <UIContentContainer>
#pragma mark - <UITraitEnvironment>
// etc.
#end
------------------------------------------------------------------------
//
// MainViewController+DelegateCallbacks.h
//
#import "MainViewController.h"
#interface MainViewController (DelegateCallbacks)
#end
------------------------------------------------------------------------
//
// MainViewController+DelegateCallbacks.m
//
#import "MainViewController+DelegateCallbacks.h"
#import "MainViewController_PrivateInterface.h"
#implementation MainViewController (DelegateCallbacks)
#pragma mark <UICollectionViewDataSource>
#pragma mark <UICollectionViewDelegate>
#pragma mark <UICollectionViewDelegateFlowLayout>
// etc.
#end
------------------------------------------------------------------------
//
// MainViewController_PrivateInterface.h
//
#import "MainViewController.h"
#interface MainViewController () {
// NSMutableArray <NSArray *> *_myArray_1;
// NSMutableArray <UIBezierPath *> *_myArray_2;
}
#property (strong, nonatomic) NSMutableArray <NSArray *> *myArray_1;
#property (strong, nonatomic) NSMutableArray <UIBezierPath *> *myArray_2;
#property (weak, nonatomic) IBOutlet MyView *myView;
#property (weak, nonatomic) IBOutlet MyCollectionView *myCollectionView;
#property (nonatomic) CGFloat myFloat;
// etc.
#end

property as NSManagedObject in view controller for a "current NSManagedObject"

I am interested in setting a property as a subclass, say Person, of NSManagedObject in a view controller that will specify an instance of person so that I will be able to update with methods in the controller. can I do it like this?
// Viewcontroller.h
#implementation
#property (nonatomic, retain) Person* currentPerson;
#end
// ViewController.m
#implementation
#dynamic currentPerson;
-(void) doSomethingToCurrentPerson {
currentPerson.SomeAtrribute=somevalue;
}
#end
It seems like if this were not a valid way to go, it would also be possible to set a unique identifier and then store CurrentPersonUniqueID as a property and use KVC. Is there a way to get something along the lines of what I posted to work, or am I better off with something closer to the KVC approach, or something totally different?
This code won't work until you replace #dynamic by #synthesize. #dynamic tells the compiler that -setCurrentPerson: and -currentPerson are implemented somewhere else, which is not the case.
So #synthesize currentPerson will create the currentPerson's getter/setter automatically. It won't have anything to do with the fact that Person is a NSManagedObject.
Also, either you can't access to currentPerson directly with this name, you have to use its getter:
self.currentPerson.attribute = something;
// or
[self currentPerson].attribute = something;
Correct code:
// Viewcontroller.h
#implementation
#property (nonatomic, retain) Person* currentPerson;
#end
// ViewController.m
#implementation
#synthesize currentPerson;
-(void) doSomethingToCurrentPerson {
self.currentPerson.SomeAtrribute = somevalue;
}
#end

Can an inherited #property not satisfy a <protocol> #property?

I've got a protocol:
#protocol Gadget <NSObject>
#property (readonly) UIView *view;
- (void) attachViewToParent:(UIView *)parentView;
#end
And an "abstract" base class, with an implementation (as a getter, not shown) of -(UIView *)view:
// Base functionality
#interface AbstractGadget : NSObject {
UIView *view;
}
#property (readonly) UIView *view;
#end
But when I implement the Gadget protocol in a subclass of AbstractGadget, like so:
// Concrete
#interface BlueGadget : AbstractGadget <Gadget> {
}
- (void) attachViewToParent:(UIView *)parentView;
#end
#implementation BlueGadget
- (void) attachViewToParent:(UIView *)parentView {
//...
}
#end
I get a compiler error telling me "warning: property 'view' requires method '-view' to be defined." I can make this go away using #dynamic, or adding a stub method:
- (UIView *) view {
return [super view];
}
But I just want to know if I'm doing something that's not supported, something I shouldn't be doing, or if it's just a limitation / bug in the compiler?
By declaring the property as #dynamic you are telling the compiler that the property getter (and setter if required) are implemented elsewhere (potentially at runtime). This sounds like a perfectly reasonable use case to me.
See The Docs for more information.
I also came across this exact issue. This is one of situations that #dynamic is there for.
Here is the rule for variable, property and synthesize in objective-C:
If you have a property, you must have a #synthesize or you declare #dynamic and write the getter and setter method yourself.
So, because you have a property called view, you have to declare #synthesize. That should be it. Nothing to do with #protocol, inheritance

Hide instance variable from header file in Objective C

I came across a library written in Objective C (I only have the header file and the .a binary).
In the header file, it is like this:
#interface MyClass : MySuperClass
{
//nothing here
}
#property (nonatomic, retain) MyObject anObject;
- (void)someMethod;
How can I achieve the same thing? If I try to declare a property without its corresponding ivar inside the interface's {}, the compiler will give me an error. Ultimately, I want to hide the internal structure of my class inside the .a, and just expose the necessary methods to the header file. How do I declare instance variables inside the .m? Categories don't allow me to add ivar, just methods.
For 64 bit applications and iPhone applications (though not in the simulator), property synthesis is also capable of synthesizing the storage for an instance variable.
I.e. this works:
#interface MyClass : MySuperClass
{
//nothing here
}
#property (nonatomic, retain) MyObject *anObject;
#end
#implementation MyClass
#synthesize anObject;
#end
If you compile for 32 bit Mac OS X or the iPhone Simulator, the compiler will give an error.
You may use of the same idiom used in Cocoa classes. If you have a look to NSString class interface in NSString.h you'll see that there is no instance variable declared. Going deeper in GNUstep source code you'll find the trick.
Consider the following code.
MyClass.h
#interface MyClass : NSObject
// Your methods here
- (void) doSomething;
#end
MyClass.m
#interface MyClassImpl : MyClass {
// Your private and hidden instance variables here
}
#end
#implementation MyClass
+ (id) allocWithZone:(NSZone *)zone
{
return NSAllocateObject([MyClassImpl class], 0, zone);
}
// Your methods here
- (void) doSomething {
// This method is considered as pure virtual and cannot be invoked
[self doesNotRecognizeSelector: _cmd];
}
#end
#implementation MyClassImpl
// Your methods here
- (void) doSomething {
// A real implementation of doSomething
}
#end
As you can see, the trick consist in overloading allocWithZone: in your class. This code is invoked by default alloc provided by NSObject, so you don't have to worry about which allocating method should be used (both are valid). In such allocWithZone:, you may use the Foundation function NSAllocateObject() to allocate memory and initialize isa for a MyClassImpl object instead of MyClass. After that, the user is dealing with a MyClassImpl object transparently.
Of course, the real implementation of your class shall be provided by MyClassImpl. The methods for MyClass shall be implemented in a way that considers a message receiving as an error.
You can use a class extension. A class extension is similar as category but without any name. On the Apple documentation they just define private methods but in fact you can also declare your internal variables.
MyClass.h
#class PublicClass;
// Public interface
#interface MyClass : NSObject
#property (nonatomic, retain) PublicClass *publicVar;
#property (nonatomic, retain) PublicClass *publicVarDiffInternal;
- (void)publicMethod;
#end
MyClass.m
#import "PublicClass.h"
#import "InternalClass.h"
// Private interface
#interface MyClass ( /* class extension */ )
{
#private
// Internal variable only used internally
NSInteger defaultSize;
// Internal variable only used internally as private property
InternalClass *internalVar;
#private
// Internal variable exposed as public property
PublicClass *publicVar;
// Internal variable exposed as public property with an other name
PublicClass *myFooVar;
}
#property (nonatomic, retain) InternalClass *internalVar;
- (void)privateMethod;
#end
// Full implementation of MyClass
#implementation MyClass
#synthesize internalVar;
#synthesize publicVar;
#synthesize publicVarDiffInternal = myFooVar
- (void)privateMethod
{
}
- (void)publicMethod
{
}
- (id)init
{
if ((self = [super init]))
{
defaultSize = 512;
self.internalVar = nil;
self.publicVar = nil;
self.publicVarDiffInternal = nil; // initialize myFooVar
}
return self;
}
#end
You can give MyClass.h to anyone with just your public API and public properties. On MyClass.m you declare your member variable private and public, and your private methods, on your class extension.
Like this it's easy to expose public interfaces and hide detail implementation. I used on my project without any troubles.
According to the documentation I've been looking at there is no problem. All you have to do to hide instance variables is to declare them at the start of the #implementation section, inside { ... }. However, I'm a relative newcomer to Objective C and there's a chance I have misunderstood something - I suspect that the language has changed. I have actually tried this system, using XCode 4.2, building code for the iPad, and it seems to work fine.
One of my sources for this idea is the Apple developer documentation at http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocDefiningClasses.html, which gives this pattern:
#implementation ClassName
{
// Instance variable declarations.
}
// Method definitions.
#end
Two possibilities:
It could be taking advantage of the modern runtime's ability to synthesize instance variables, as bbum suggested.
The property might not have an underlying instance variable in that class. Properties do not necessarily have a one-to-one mapping with instance variables.
No you can't. But you can do this if you're not using #property:
.h
#interface X : Y {
struct X_Impl* impl;
}
-(int)getValue;
#end
.m
struct X_Impl {
int value;
};
...
#implementation X
-(void)getValue {
return impl->value * impl->value;
}
#end
How about a macro trick?
Have tested code below
have tested with dylibs - worked fine
have tested subclassing - Warning! will break, I agree this makes the trick not that useful, but still I think it tells some about how ObjC works...
MyClass.h
#interface MyClass : NSObject {
#ifdef MYCLASS_CONTENT
MYCLASS_CONTENT // Nothing revealed here
#endif
}
#property (nonatomic, retain) NSString *name;
#property (nonatomic, assign) int extra;
- (id)initWithString:(NSString*)str;
#end
MyClass.m
// Define the required Class content here before the #import "MyClass.h"
#define MYCLASS_CONTENT \
NSString *_name; \
int _extra; \
int _hiddenThing;
#import "MyClass.h"
#implementation MyClass
#synthesize name=_name;
#synthesize extra=_extra;
- (id)initWithString:(NSString*)str
{
self = [super init];
if (self) {
self.name = str;
self.extra = 17;
_hiddenThing = 19;
}
return self;
}
- (void)dealloc
{
[_name release];
[super dealloc];
}
#end
DON'T do this, but I feel it should be noted that the runtime has the ability to add ivars whenever you want with class_addIvar
I was able to do the following in my library:
myLib.h:
#interface MyClass : SomeSuperClass <SomeProtocol> {
// Nothing in here
}
- (void)someMethods;
#end
myLib.m
#interface MyClass ()
SomeClass *someVars;
#property (nonatomic, retain) SomeClass *someVars;
#end
#implementation MyClass
#synthesize someVar;
- (void)someMethods {
}
#end
The protocol is optional of course. I believe this also makes all your instance variables private though I'm not 100% certain. For me it's just an interface to my static library so it doesn't really matter.
Anyway, I hope this helps you out. To anyone else reading this, do let me know if this is bad in general or has any unforeseen consequences. I'm pretty new to Obj-C myself so I could always use the advice of the experienced.
I don't think the following code written in another answer is working as expected.
The "SomeClass *someVars" defined in the extension class is not an instance variable of MyClass. I think it is a C global variable. If you synthesize someVars, you will get compile error. And self.someVars won't work either.
myLib.h
#interface MyClass : SomeSuperClass <SomeProtocol> {
// Nothing in here
}
- (void)someMethods;
#end
myLib.m
#interface MyClass ()
SomeClass *someVars;
#property (nonatomic, retain) SomeClass *someVars;
#end
#implementation MyClass
#synthesize someVar;
- (void)someMethods {
}
#end