Using NSMutableDictionary as backing store for properties - iphone

I am looking for a shorthand way of setting my properties directly to an NSMutableDictionary that is a instance variable. ie:
KVCModle.h:
#interface KVModel : NSObject {
NSMutableDictionary * data;
}
#property(nonatomic,assign)NSString * string1;
#property(nonatomic,assign)NSString * string2;
#end
KVCModel.m
#import "KVModel.h"
#implementation KVModel
-(id)init
{
self = [super init];
if(self)
{
data = [[NSMutableDictionary alloc] init];
}
return self;
}
-(NSString *)string1
{
return [data objectForKey:#"string1"];
}
-(NSString *)string2
{
return [data objectForKey:#"string2"];
}
-(void)setString1:(NSString *)_string1
{
[data setObject:_string1 forKey:#"string1"];
}
-(void)setString2:(NSString *)_string2
{
[data setObject:_string2 forKey:#"string2"];
}
-(void)dealloc
{
[data release];
[super dealloc];
}
#end
I have tried to override setValue:ForKey: and valueForKey:, but those aren't called, they allow you to directly set properties without using the property syntax.
I have made preprocessor macros to make this work in the past, but I am not interested in typing at all, and would like to avoid as much of it as I can in the future. Is there a way to make this work that I am not familiar with?
I have thought about using NSManagedObject, but I am not sure if I can get what I want out of that.
EDIT:
source

If you're trying to access the properties with code like foo = obj.foo and obj.foo = foo, that's why it doesn't work.
Property-access syntax is synonymous with message syntax; the former is exactly the same as foo = [obj foo], and the latter is exactly the same as [obj setFoo:foo]. There is no KVC code to intercept. Properties are at the language level; KVC is at the framework level.
You'll need to intercept the accessor messages instead. Consider implementing the resolveInstanceMethod: class method, in which you “resolve” the selector by adding a method implementation to the class using the Objective-C runtime API. You can add the same implementation(s) for many different selectors.
For your purpose, have a function or method that examines the selector (using NSStringForSelector and regular NSString-examining techniques) and returns two facts: (1) the property name, and (2) whether it's a getter (foo, isFoo) or setter (setFoo:). Then, have two more methods, one a dynamic getter and the other a dynamic setter. When the selector names a getter, add it with your dynamic-getter method; when the selector names a setter, add it with your dynamic-setter method.
So how do the dynamic-getter and -setter methods work? They'll need to know what property to dynamically get and set, but they also need to take no arguments (getter) or one argument (setter, which takes the value), in order to match the original property-access message. You might be wondering how these generic implementations can know what property to get or set. The answer is: It's in the selector! The selector used to send the message is passed to the implementation as the hidden argument _cmd, so examine that selector the same way as before to extract the name of the property you should dynamically get or set. Then, the dynamic getter should send [data objectForKey:keyExtractedFromSelector] and the dynamic setter should send [data setObject:newValue forKey:keyExtractedFromSelector].
Two caveats:
You may still get complaints from the compiler when you use the property-access syntax to access a “property” that you have not declared in the class's #interface. This is normal and intentional; you're really only supposed to use property-access syntax to access known formal properties. What you're doing, while I found it fun to solve, is technically an abuse of the property-access syntax.
This will only work for object values. KVC does the boxing and unboxing for primitive values, such as integers; since KVC is not involved, no free boxing and unboxing. If you have declared formal properties (see 1), you'll need to introspect them using the Objective-C runtime API, and do the boxing and unboxing yourself with your findings.

This piqued my curiosity, so I went ahead and used Peter Hosey's suggestion of overriding +resolveInstanceMethod: to generate the getters and setters. I posted the resulting object (DDDynamicStorageObject) to a github repository:
https://github.com/davedelong/Demos

What you basically want is your own implementation of the NSManagedObject machinery. I have done something similar. Look here: https://gist.github.com/954035 HTH
(Updated the code to remove the dependency on the non-existant NSString+Utilities.h)
(Added missing ReleaseAndZero() macro)

For the love of all that is sacred - do not use an NSDictionary as a place to stuff every conceivable property of a model object. Ivars are easier to debug, and much much clearer to other developers (including your future self).
If you want to use a dictionary, use a dictionary and some statically defined keys - but if you want a model object, use some ivars

I come to the same problem today just like you. So I find your question posted here.
The answers above used the +resolveInstanceMethod: is a little bit hard for me. :)
My understanding is that as long as we setup the property, we would have getter and setter method, so I use the setter method to implement it.
BDLink.h
#property (nonatomic, strong) NSString *type;
#property (nonatomic, strong) NSString *displayName;
#property (nonatomic, strong) NSString *linkURI;
BDLink.m
- (id)initWithLinkInfoDictionary:(NSDictionary *)linkInfoDict {
for (NSString *key in linkInfoDict) {
const char *rawName = [key UTF8String];
NSString *setMethodString = [NSString stringWithFormat:#"set%c%s:", toupper(rawName[0]), (rawName+1)];
SEL setMethod = NSSelectorFromString(setMethodString);
if ([self respondsToSelector:setMethod]) {
[self performSelector:setMethod withObject:linkInfoDict[key]];
}
}
return self;
}
Hope it would be helpful. My first answer, :)

Related

How to use variables created outside of viewDidLoad

Hey I'm very new to Objective C programming and I'm stuck. How come when I create I function, it can't use the variables I created for the labels or textviews, etc. And whenever I call them in the viewDidLoad function, I have to do either self.(variableName) or _(variableName) and it won't let me do that outside of the viewDidLoad function. Is there a way to access them outside of it?
How come when I create I function, it can't use the variables I
created for the labels or textviews, etc.
For one thing, you need to differentiate between a function and an instance method. In Objective-C, classes can have instance variables (variables that are part of an instance of that class) and instance methods (similar to functions that are associated with an instance of that class). Classes can also have properties, which are used rather like instance variables in that they're values associated with an object, but they're accessed through accessor methods. Functions, on the other hand, aren't part of any class. So, a class has an interface where instance variables and methods are declared, like this:
#interface Person : NSObject
{
NSString *firstName;
NSString *lastName;
}
#property (readonly) NSString *fullName;
#property (strong) NSArray *friends;
#property (assign) int age;
- (id)initWithFirstName:(NSString*)first lastName:(NSString*)last;
- (void)addFriend:(Person*)friend;
#end
And also an implementation, like this:
#implementation Person
- (id)initWithFirstName:(NSString*)first lastName:(NSString*)last
{ /* code goes here */ }
- (void)addFriend:(Person*)friend
{ /* code goes here */ }
- (NSString *)fullName
{ return [NSString stringWithFormat:#"%# %#", firstName, lastName; }
#end
Those things in the implementation are instance methods, as denoted by the - at the beginning and the fact that they're defined in an #implementation block. (If they had + instead of -, they'd be class methods instead of instance methods -- I'll let you read about that in the docs.) Properties are accessed by calling an appropriate accessor methods using either normal method calls or dot notation, so if you have:
Person *george = [[Person alloc] initWithFirstName:#"George" lastName:#"Bailey"]
all of these are valid:
NSString *name1 = george.fullName;
NSString *name2 = [george fullName];
george.age = 45;
[george setAge:45];
int years1 = george.age;
int years2 = [george age];
Also, self is a pointer to "the current object". You can use it in instance methods so that objects can call their own methods and access their own properties. For example, the Person class could contain a method like this:
(NSString *)nameAndAge
{
NSString *nameAndAge = [NSString stringWithFormat:#"%#: %d", self.fullName, self.age];
}
Functions, on the other hand, aren't part of any class, use C function syntax rather than Objective-C method syntax, and aren't defined in an #implementation block:
BOOL isMiddleAged(Person* person)
{
return (person.age > 30) && (person.age < 60);
}
You can't use self in function because a function isn't associated with an object, so there's nothing for self to point to. You can, however, use properties of other objects you know about, such as person.age in the example above.
And whenever I call them in the viewDidLoad function, I have to do
either self.(variableName) or _(variableName) and it won't let me do
that outside of the viewDidLoad function.
You must be accessing properties of your view controller. As explained above, self.(variableName) is the way to access properties. _(variableName) refers to a variable (often generated by the compiler) that stores the value of the property. (You shouldn't normally access those variables directly outside initialization methods and -dealloc -- use the property accessors instead.) You can use those properties in any instance method of the class, not just -viewDidLoad. You can also access properties of other objects by replacing self with the name of a pointer to the object, just as I did with person in isMiddleAged().
Seems like your are using autosythesized property. Using Auto Synthesized property you need not to #syhtesize objects.
#sythesize object = _object; will be implicitly implement in this case.
So you can access object using self.object or _object.
You can #synthesize to avoid using objects via self.varName or _varName .You can directly use it using varName.

Objective C: Which is changed, property or ivar?

Worrying about duplicates but can not seem to find and answer I can understand in any of the other posts, I just have to ask:
When I have in my .h:
#interface SecondViewController : UIViewController{
NSString *changeName;
}
#property (readwrite, retain) NSString *changeName;
then in my .m
#synthesize changeName;
-(IBAction)changeButton:(id)sender{
changeName = #"changed";
}
Is it the synthesized property or the instance variable that get changed when I press "changeButton" ?
You (and it seems some of the others that answered) are confusing properties with actual variables.
The way properties work is, they create METHODS (called setter and getter) that set or get/return ivars. And the do notation (self.string) actually INVOKES these methods. So a property can't be CHANGED, only the declared iVar is.
When you declare a property like so:
#property (nonatomic, retain) NSString *string;
And #synthesize it the following happens:
An iVar called string (of type NString*) is created
(if you do
#synthesize string = whateverYouWant
the iVar created
is called whateverYouWant - a convention is to name the iVars
the same as the property with preceding underscore (_string))
an accessor method is created like this
-(NSString*) string;
a setter is created like this
-(void) setString: (NSString*) newString;
Now what self.xxxx does is, it actually sends the message xxxx to self
(like [self xxxx]).
It works with ANY method, not just properties, though it should only
Be used with properties.
So when you do self.string = #"hello" it actually comes down to
[self setString: #"hello"];
(Note that the compiler actually knows you are trying to set and so the
setString message is sent instead of just string. If you accessed self.string
it would send [self string])
Thus you don't SET a property, you invoke the (synthesized) setter method that in
itself sets the iVar.
Accessing your iVar directly is ok, if you know what your doing.
Just calling
string = #"something else";
Will produce leaking code, since no memory management is done.
The synthesized accessors and setters actually do this for you, depending
on how you defined th property (retain,copy,assign).
Because the setter (for a retained property) doesn't just do
IVar = newValue
If you declared a retained property it actually looks something like this:
-(void) setString: (NSString*) newString {
if (string) [string release];
string = [newString retain];
}
So the property synthesize takes a bit of work off your hands.
EDIT
Since it still doesn't seem clear, the property that is declared is not to be thought
of like a variable. In the above example, when using
#synthesize string = _string;
there IS NO variable called "string". It's just the way you access the method structures
that set the iVar _string through the setter methods. Since string is no variable/object pointer, you cannot send messages to it ([string doSomething] won't work).
When you just synthesize the property using #synthesize string; the generated iVar gets
the same name as the property.
Calling [string doSomething] will then work, but it has nothing to do with the property. The "string" refers to the iVar. Hence th convention to name the iVars underscored, so
you don't accidentally access the iVar when you meant to use the getter/setter.
Both. Property uses instance variable as its storage. In your code you change the instance variable, but if you access the property (via self.changeName) you'd get the same value as instance variable.
Usually to distinguish between ivars and properties people use _ prefix for ivars. And then synthesizes properties like this:
#synthesize myProperty=_myProperty;
well, the var
it's always the var
in your case the property methods aren't used at all.
now, consider this case:
self.changeName = #"changed";
this way you are using the property, but that just means that you are using the methods "magically" created for you by the compiler, the setter and getter methods, where you, again, change the var (property doesn't exist, in reality, it's just a way to create the setter and getter methods for you)

Objective-C method to nullify object

i have some trouble writing a method in Objective-C to make an object nil. Here is some example :
#interface testA : NSObject
{
NSString *a;
}
#property (nonatomic, retain) NSString *a;
+(testA*)initWithA:(NSString *)aString;
-(void)displayA;
-(void)nillify;
#end
#implementation testA
#synthesize a;
+(testA*)initWithA:(NSString *)aString{
testA *tst=[[testA alloc] init];
tst.a=aString;
return [tst autorelease];
}
-(void)displayA{
NSLog(#"%#",self.a);
}
-(void)nillify{
self=nil;
}
- (void)dealloc {
[a release];
[super dealloc];
}
#end
int main(int argc, char **argv){
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
testA *test=[testA initWithA:#"some test"];
[test displayA];
test=nil;
//[test nillify];
NSLog(#"after setting to nil");
[test displayA];
[pool release];
return 0;
}
Apparently , when I set test object to nil and then call some method on it nothing happens , but if i call nillify instead of directly setting it to nil , displayA method works normally like test object is still there. Is there a workaround for nillify method to function properly ?
Your help is much appreciated !
You can't actually do something like this, because setting 'self' to nil only has any effect within the scope of that method (in your case, 'nilify'). You don't have any actual way to effect the values of pointers located on other parts of the stack or in random places in the heap, for example.
Basically any code that holds a reference to some object is responsible for maintaining and clearing those references itself. If you have some use case where random sections of code may need references to "live" objects of some kind, but where you'd want those object references to go away in response to some external event (maybe a user tracking system or something), you could do something with notifications, but the various modules tracking those "live" objects would still be responsible for listening for notifications and cleaning up references when they received them.
The 'nilify' thing, however, can't possibly work.
You cannot do what you're trying to do. self is just a local reference to an object that actually exists elsewhere. Setting it to nil doesn't mean anything. An object doesn't, in general, own itself, and it certainly doesn't control other objects' references to it. It's up to the owning objects to manage its lifetime.
There are a few things wrong with your code.
First, by convention, class names start with an uppercase letter. Please stick to these naming conventions as it will make it harder for other developers to work with your code (and even confuse you).
Next, your initWithName:... According to the naming conventions, a method with init in its name should be an instance method, not a class method. So either name it newWithName: or turn it into an instance method like this:
-(testA*)initWithA:(NSString *)aString{
self = [super init];
if (!self) return nil;
tst.a=aString;
return self;
}
If you keep it as class method (and name it newWithName:) you should not return a autoreleased object since according to the naming conventions method that start with init... or new... return a retained object. If you do not follow these conventions, the static analyzer will give you "false" warnings and it will become useless for you.
Now for the reason your nillify doesn't work: the self is in fact an argument to a method. Under the hood, your nillify method actually has two arguments that you do not see: the self pointer and the selector pointer. This means, self is actually a variable on the stack. And if you overwrite it, you only overwrite that stack variable but that doesn't influence your test variable which is somewhere else.
As an example, consider a method - (void)foo:(NSString *)bar;. The compiler turns it into the equivalent of the C function (void) foo(id self, SEL _cmd, NSString *bar).

When should I use the “self” keyword?

When should I be using the self expression in my iphone development applications? say i have 2 fields: UITextField *text1; and NSString *str1; retained and synthesized.
when i am accessing either of these 2 fields, when should i and when should i not use self.text1 and self.str1 ?
self is not a keyword, it is an expression. Additionally, you use it any time you want to refer to a method or property on yourself, or yourself directly. By "yourself" I am of course, referring to the instance of the class you are operating in.
There are certain circumstances where it's generally discouraged to use the self.-expression to access a property. Normally you always use self for any access of a property. It's the most secure and uncomplicated way. Especially if you used retain, then memory management will be done for you.
The two exceptions from this rule:
Any init method.
In dealloc.
In both cases you are dealing with an partially initialized object. There are some side effects that may occur when using setters or getters here -- because they are methods and hence may be overridden.
For example, take a class A with a property foo that has been subclassed by class B. The subclass B adds an property bar and overrode the setter for foo. Now your init-method calls setFoo:, because you used self.foo = ... with some initial value. The subclass, however, also accesses the value of bar in this setter. But in this case, it may happen that bar has never been initialized and points at some arbitrary data. Calling a setter in init my cause crashes, although the probability may not be too high in your own code.
In your example you aren't directly accessing instance variables when you use self, instead you're accessing the properties you've defined.
Consider this example:
#interface Foo : NSObject {
NSString *_bar;
}
#property (nonatomic, retain) NSString *bar;
#end
#implementation Foo
#synthesize bar = _bar;
-(void)baz {
_bar = #"ivar"; //accessing the ivar
self.bar = #"property"; //accessing the ivar via the property
}
#end
In general if you're using properties, there's little reason to utilize the ivar. This has the added benefit of automatically retaining & releasing values for you.
But other cases exist when your properties will have a readonly modifier. In these cases it's necessary to directly access your ivars in order to set their values.
It's also a good idea to use self within a method call sometimes if you have a custom getter. The managedContext object within a Core Data-using application is a good example. If you refer to it by self.managedContext, you can override and set the object to what it needs to be if it's nil. Refer to the code generated by XCode when creating an application that uses Core Data.
Here is an example of the code generated by XCode, actually:
#interface YourAppDelegate : NSObject <UIApplicationDelegate>
{
#private
NSManagedObjectContext *managedObjectContext_;
}
#property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
#implementation ContractionTimerAppDelegate
/**
Returns the managed object context for the application.
If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
*/
- (NSManagedObjectContext *)managedObjectContext {
if (managedObjectContext_ != nil) {
return managedObjectContext_;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext_ = [[NSManagedObjectContext alloc] init];
[managedObjectContext_ setPersistentStoreCoordinator:coordinator];
}
return managedObjectContext_;
}
#end
if you "synthesize" the variable, you should "self." the variable. little rule of thumb
I don't know anything about objective-c, but this looks a lot like this keyword from other languages (like C++, C#, Java, PHP, and others). If so, then my advice is to use it always. That way, if you ever (accidentally) define a local variable with the same name, your code won't break.
However, I must also add, that this is somewhat of a religious debate with a history of flamewars in programmer communities. So take this advice with a grain of salt and use whatever seems to make most sense to you. Just be consistent about it.

Property vs. instance variable

I'm trying to understand how strategies some folks use to distinguish instance vars vs. properties. A common pattern is the following:
#interface MyClass : NSObject {
NSString *_myVar;
}
#property (nonatomic, retain) NSString *myVar;
#end
#implementation MyClass
#synthesize myVar = _myVar;
Now, I thought the entire premise behind this strategy is so that one can easily distinguish the difference between an ivar and property. So, if I want to use the memory management inherited by a synthesized property, I'd use something such as:
myVar = #"Foo";
The other way would be referencing it via self.[ivar/property here].
The problem with using the #synthesize myVar = _myVar strategy, is I figured that writing code such as:
myVar = some_other_object; // doesn't work.
The compiler complains that myVar is undeclared. Why is that the case?
Thanks.
Properties are just setters and getters for ivars and should (almost) always be used instead of direct access.
#interface APerson : NSObject {
// NSString *_name; // necessary for legacy runtime
}
#property(readwrite) NSString *name;
#end
#implementation APerson
#synthesize name; // use name = _name for legacy runtime
#end
#synthesize creates in this case those two methods (not 100% accurate):
- (NSString *)name {
return [[_name copy] autorelease];
}
- (void)setName:(NSString *)value {
[value retain];
[_name release];
_name = value;
}
It's easy now to distinguish between ivars and getters/setters. The accessors have got the self. prefix. You shouldn't access the variables directly anyway.
Your sample code doesn't work as it should be:
_myVar = some_other_object; // _myVar is the ivar, not myVar.
self.myVar = some_other_object; // works too, uses the accessors
A synthesized property named prop is actually represented by two methods prop (returning the current value of the property) and setProp: (setting a new value for prop).
The self.prop syntax is syntactic sugar for calling one of these accessors. In your example, you can do any one of the following to set the property myVar:
self.myVar = #"foo"; // handles retain/release as specified by your property declaration
[self setMyVar: #"foo"]; // handle retain/release
_myVar = #"Foo"; // does not release old object and does not retain the new object
To access properties, use self.propname. To access instance variables use just the instance variable's name.
The problem with using the #synthesize myVar = _myVar strategy, is I figured that writing code such as:
myVar = some_other_object; // doesn't work.
The compiler complains that myVar is undeclared. Why is that the case?
Because the variable myVar is undeclared.
That statement uses the syntax to access a variable, be it an instance variable or some other kind. As rincewind told you, to access a property, you must use either the property-access syntax (self.myVar = someOtherObject) or an explicit message to the accessor method ([self setMyVar:someOtherObject]).
Otherwise, you're attempting to access a variable, and since you don't have a variable named myVar, you're attempting to access a variable that doesn't exist.
In general, I name my properties the same as my instance variables; this is the default assumption that the #property syntax makes. If you find you're fighting the defaults, you're doing it wrong (or your framework sux, which is not the case for Cocoa/Cocoa-touch in my opinion).
The compiler error you're getting is because property use always has to have an object reference, even inside your own class implementation:
self.stuff = #"foo"; // property setter
[stuff release]; // instance variable
stuff = #"bar"; // instance variable
return self.stuff; // property getter
I know that many Cocoa programmers disagree, but I think it's bad practice to use properties inside your class implementation. I'd rather see something like this:
-(void) someActionWithStuff: (NSString*) theStuff {
// do something
[stuff release];
stuff = [theStuff copy];
// do something else
}
than this:
-(void) someActionWithStuff: (NSString*) theStuff {
// do something
self.stuff = theStuff;
// do something else
}
I prefer to do memory management as explicitly as possible. But even if you disagree, using the self.stuff form will clue in any experienced Objective-C programmer that you're calling a property rather than accessing an instance variable. It's a subtle point that's easy for beginners to gloss over, but after you've worked with Objective-C 2.0 for a while, it's pretty clear.
Don,
According to the "rules", you should call Release for every Copy, Alloc, and Retain. So why are you calling Release on stuff? Is this assuming it was created using Alloc, Copy, or Retain?
This brings up another question: Is it harmful to call Release on a reference to an object if it's already been released?
Since Apple reserves the _ prefix for itself, and since I prefer to make it more obvious when I am using the setter and when I am using the ivar, I have adopted the practive of using a prefix of i_ on my ivars, so for example:
#interface MyClass : NSObject {
NSString *i_myVar;
}
#property (nonatomic, retain) NSString *myVar;
#synthesize myVar = i_myVar;
i_myVar = [input retain];
self.myVar = anotherInput;
[i_myVar release]
Since it is quite important to know when you are using the setter and when you are using the ivar, I find the explicitly different name is safer.
In your question, it should be:
self.myVar = #"Foo"; // with setter, equivalent to [self setMyVar:#"Foo"]
and
_myVar = some_other_object; // direct ivar access - no memory management!
Remember that you should not use setters/getters in init/dealloc, so you need to do your direct ivar access (and careful memory management) iin those methods.
what's wrong with simply using
#interface MyClass : NSObject
#property NSString *prop;
#end
nonatomic and retain are not required, retain is the default, and atomic/nonatomic isn\t important unless XCode tells you with a warning.
it is NOT necessary to declare the iVar, one will be created for you named _prop, if you really want to use one (i don't see why to be honest)
#synthesize is NOT required.
when (and you should) using ARC you don't have to bother with retain and release either.
keep it simple !
furthermore, if you have a method like this one
- (void)aMethod:(NSString*)string
{
self.prop = string;
// shows very clearly that we are setting the property of our object
_aName = string;
// what is _aName ? the _ is a convention, not a real visual help
}
i would always use properties, more flexible, easier to read.