So I'm trying to clean up my code and move all of one object's logic to it's own class.
I want to be able to do something like this:
#interface Habit : PFObject<PFSubclassing>
and then be able to call
[Habit calculateStreak].
How would I initialize Habit with an already created PFObject and all of its data? Something like [Habit * running = Habit initWithThis:someObjectWithData]? Or am I thinking of this all wrong?
Subclassing is pretty easy: Just inherit from PFObject and adopt the PFSubclassing protocol:
#interface Habit : PFObject <PFSubclassing>
- (id)calculateStreak;
#end
Then, make sure you override the parseClassName to return the Parse class name:
#implementation Habit
- (NSString *)parseClassName
{
return #"Habit";
}
#end
You also have to register your subclass, which should be done in +[Habit load]:
#implementation Habit
- (void)load
{
[self registerSubclass];
}
- (NSString *)parseClassName
{
return #"Habit";
}
#end
Then you can instantiate the class the way you would any other Parse class, using +[object] or the like:
Habit *habit = [Habit object];
Related
I'm having trouble finding out the way to implenent something similar to abstract class in Objective-C.
I don't actually care about restricting to use my base class without subclassing it, all I want is this:
I want to have class A (parent/base/abstract) which has method something like - (void)makeRequest and I want to subclass it in classes B,C,D etc and have methods like - (id)getCachedResult that are being called from class' A method. So basically I want class A to implement some base logic and I want it's subclasses to modify some details and parts of this base logic.
Sounds like a trivia, but I can't put my finger on the way to implement such pattern in Objective-C.
UPDATE:
Here's what I'm trying to do:
#interface A : NSObject
- (void)makeRequest;
- (NSString *)resultKey;
#property (strong) NSMutableDictionary * result;
#end
#implementation A
- (void)makeRequest
{
self.result[self.resultKey] = #"Result";
}
- (NSString *)resultKey
{
#throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:[NSString stringWithFormat:#"%# should be overrided in subclass", NSStringFromSelector(_cmd)]
userInfo:nil];
return nil;
}
#end
/////////////////////////////
#interface B : A
#end
#implementation B
- (NSString *)resultKey
{
return #"key";
}
#end
When I'm creating instance of class B and trying to call it's method - (void)makeRequest I'm getting exception, and that's pretty obvious. What I want is a way to correctly design my classes for the same purpose.
As requested: You should declare resultKey in B's interface. :-)
I've got an NSManagedObject class that I want to override a setter to but I've been told it's good practice to not modify the automatically generated class file and create categories to instead extend them (because if you change the model and regenerate the file, you lose all your additions).
If I make a method for the setter in a category, it definitely runs the method (tested with NSLog), but I don't know how to assign the actual property value. Normally, I'd synthesise the property using
#synthesize finished = _finished;
so that I can access the property in the setter using _finished, like so:
- (void)setFinished:(NSNumber *)finishedValue {
_finished = finishedValue;
self.end_time = [NSDate date];
}
but where the property is defined in the NSManagedObject this doesn't seem possible.
You can do with subclassing see the doc here
- (void)setName:(NSString *)newName
{
[self willChangeValueForKey:#"name"];
[self setPrimitiveName:newName];
[self didChangeValueForKey:#"name"];
}
In a category, you can't add property value, only methods. So you will need to subClass in order to perform what you want.
There is an easy way to do so, try the following:
Model.h
#interface Model
#property(nonatomic,copy) NSString * string;
#end
Model + Override.m
#interface Model ()
{
NSString *_string;
}
#end
#implementation Model (Override)
- (void)setString:(NSString *)string
{
return _string = string;
}
#end
I'm fighting with something and I don't find any satisfying solution.
I have a class with a "myMutableArray" member.
I would like the class to manage itself adding and removing items from the array, so I don't want any other class being able to access the member and call NSMutableArray methods on it.
In an ideal situation, I would like to have a private getter (to be able to call self.myMutableArray) and a public setter for this member.
Do you know how I may achieve this ?
In other words :
I would like other classes
be able to call
- [oneInstance setMyMutableArray:thisArray]; // set
- oneInstance.myMutableArray = thisArray; // set using setter
- thisArray = oneInstance.myMutableArray; // get
- [oneInstance addItem:anItem]; // add
not being able to call :
- [oneInstance.myMutableArray add:etc...] // add
I would like my class
be able to call
- self.myMytableArray = [NSMutableArray array]; // set
- thisArray = self.myMytableArray ; // get
Thank you.
Is there any reason you need the public setter? It sounds like the class itself owns the array. You'd probably be better off not providing any public property access to the field, and making a public method which copies the values into your private field.
// public interface, in the .h file
#interface MyClass : // superclass, protocols, etc.
- (void) setSomething:(NSArray *)values;
#end
// private interface, not in the .h
#interface MyClass ()
#property (/* attributes */) NSMutableArray *myMutableArray;
#end
#implementation MyClass
#synthesize myMutableArray = myMutableArray_;
- (void) setSomething:(NSArray *)values
{
[self.myMutableArray setArray:values];
}
#end
Foo.h
#interface Foo : NSObject
#property(readonly, retain) NSArray * myReadonlyArray;
- (void) addItem: (Item *) anItem;
- (BOOL) publiclyDoSomething;
#end
Foo.m
#interface Foo()
#property(readwrite, retain) NSMutableArray * myMutableArray;
- (void) doSomethingInPrivate;
#end
#implementation Foo
#synthesize myMutableArray = myMutableArray_;
- (void) addItem: (Item *) anItem
{
// assuming myMutableArray_ was already iniitialized
[self.myMutableArray addObject: anItem];
}
- (NSArray *)myReadonlyArray
{
return self.myMutableArray;
}
... rest of methods (including the public/private) implementations ...
#end
Some details:
Objective-C has "instance variables", not "member variables".
The above defines a public getter and private setter that is synthesized automatically. For clarity's sake, I also added a public method and a private method.
"Public" and "private" in Objective-C are defined entirely by visibility to the compiler. The setter for myMutableArray and the method doSomethingInPrivate are only private because their declarations in an #interface cannot be imported.
self.myMutableArray and [self myMutableArray] do the same thing; the . syntax is merely short hand for an equivalent method call (with a few edge case details beyond this question)
#property in the #interface is purely short hand for method declarations (with a bit of extra metadata).
#interface Foo() is a class extension and not a category. It exists for exactly the purpose demonstrated above; to extend the #interface of a class with additional declarative information whose scope should be limited. It can appear in a header file that, say, you only import in your library's implementation to create library-private functionality.
#dynamic is used when you neither #synthesize an #property nor provide a conventional method implementation. It is not needed otherwise!
I'm probably forgetting something.
I have an Objective-C class that has a method that is meant to be overridden, which is uses in a different method. Something like this:
#interface BaseClass
- (id)overrideMe;
- (void)doAwesomeThings;
#end
#implementation BaseClass
- (id)overrideMe {
[self doesNotRecognizeSelector:_cmd];
return nil;
}
- (void)doAwesomeThings {
id stuff = [self overrideMe];
/* do stuff */
}
#end
#interface SubClass : BaseClass
#end
#implementation SubClass
- (id)overrideMe {
/* Actually do things */
return <something>;
}
#end
However, when I create a SubClass and try to use it, it still calls overrideMe on the BaseClass and crashes due to doesNotRecognizeSelector:. (I'm not doing a [super overrideMe] or anything stupid like that).
Is there a way to get BaseClass to call the overridden overrideMe?
What you are describing here should work so your problem is likely elsewhere but we don't have enough information to help diagnose it.
From your description, I'd say either the instance you're messaging is not the class you think it is or you made some typo in your code when declaring the method names.
Run your application under gdb, add a symbolic breakpoint on objc_exception_throw, reproduce your problem. Once your process has stopped on the "doesNotRecognizeSelector" exception, print object description and it's class.
Or log it before calling -overrideMe:
NSLog(#"object: %# class: %#", obj, [obj class])
Write a category for BaseClass to override the method.
#interface BaseClass (MyCategory)
- (id) overrideMe;
#end
#implementation BaseClass (MyCategory)
- (id) overrideMe
{
/* Actually do things */
return <something>;
}
#end
Now all instances of BaseClass will respond to selector overrideMe with the new implementation.
relatively new programmer here.
Look at the two classes defined below. I'd like to be able to call the following:
[instanceOfSecondClass transitionToPage: [instanceOfFirstClass nextPage]];
However, that doesn't seem to work (because I'm trying to return a class, not an instance of a class.)
#implementation FirstClass
- (id)nextPage {
return SomeOtherClass;
}
#end
#implementation SecondClass
- (void)transitionToPage:(id)someOtherClass {
currentPageViewController = [[mySomeOtherClass alloc] init];
...
}
#end
Is there any way to accomplish what I am trying to do here?
Sometimes things that make sense to me totally don't make sense in the real world :).
Thanks for the help!
"Class" is the type you want to return
#implementation MyClass
- (Class)nextPage {
return [SomeOtherClass class];
}
#end
Hope it works,
ief2