Custom class NSObject not key value coding compliant [duplicate] - objective-c

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why is my object not key value coding-compliant?
I'm having a dictionary and I want to add keys/values to a custom class, but i always get the error, that the class is not KVC compliant, but the Apple documents state that it should be.
My code:
ContactObject.h:
#interface ContactObject : NSObject
+ (ContactObject *)testAdding;
#end
ContactObject.m:
#implementation ContactObject
- (id)init {
self = [super init];
if (self) {
// customize
}
return self;
}
+ (ContactObject *)testAdding
{
// create object
ContactObject *theReturnObject = [[ContactObject alloc] init];
[theReturnObject setValue:#"Berlin" forKey:#"city"];
[theReturnObject setValue:#"Germany" forKey:#"state"];
return theReturnObject;
}
#end
I think I'm missing something very stupid :)
Please, any help appreciated ...
Greetings,
matthias

Actually to be KVC compliant:
How you make a property KVC compliant depends on whether that property is an attribute, a to-one relationship, or a to-many relationship. For attributes and to-one relationships, a class must implement at least one of the following in the given order of preference (key refers to the property key):
The class has a declared property with the name key.
It implements accessor methods named key and, if the property is mutable, setKey:. (If the property is a Boolean attribute, the getter accessor method has the form isKey.)
It declares an instance variable of the form key or _key.
I don't see any of these three implemented. You need to have at least properties that you are trying to set through KVC, the default NSObject implementation is able to set properties through setValue:forKey: but you must declare them.

You need to declare every property that will be used:
#interface ContactObject : NSObject
#property (nonatomic,copy, readwrite) NSString* city;
#property (nonatomic, copy, readwrite) NSString* state;
+ (ContactObject *)testAdding;
#end
Or use a NSMutableDictionary object.
For example:
NSMutableDictionary* dict= [NSMutableDictionary new];
[dict setObject: #"Berlin" forKey: #"city"];
[dict setObject: #"Germany" forKey: #"state"];

You need to actually declare/implement properties. Key-Value Coding doesn't mean that every NSObject is automatically a key/value dictionary.
In this case you would need to declare:
#property (nonatomic, readwrite, copy) NSString* city;
#property (nonatomic, readwrite, copy) NSString* state;
in your #interface declaration.

ObjC is dynamic in some ways, but it's not really dynamic as far as storage in classes. If you want ContactObject to be KVC-compliant for certain keys, those keys need to exist in the class. The KVC Guide has this to say:
For properties that are an attribute or a to-one relationship, this
requires that your class:
Implement a method named -<key>, -is<Key>, or have an instance
variable <key> or _<key>. Although key names frequently begin with a
lowercase letter, KVC also supports key names that begin with an
uppercase letter, such as URL.
If the property is mutable, then it should also implement -set<Key>:.
Your implementation of the -set<Key>: method should not perform
validation.
The easiest way to accomplish that is to declare the keys you want as properties:
#property (copy, nonatomic) NSString * city;
#property (copy, nonatomic) NSString * state;
You can also declare an ivar and implement accessors yourself, but there's usually no good reason to do it that way -- declared properties will take good care of you.

Related

How to persist objects between classes

I have 6 categories that contain unique data; I have defined a class that looks like this:
#interface ExportBookData : NSObject {
}
#property (strong, nonatomic) NSArray *booksArray;
#property (nonatomic, retain) NSMutableDictionary *builtFileList;
#property (nonatomic, retain) NSMutableArray *exportData;
#end
What I want to do is be able to instantiate the class ExportBookData, once for each category, and use that instantiated class throughout another class, having the data persist and be accessible between classes.
I have tried this code, but it doesn't do what I need:
ExportBookData *abe = [ExportBookData new];
abe.abeBuiltFileList = [NSMutableDictionary dictionary];
abe.abeExportData = [NSMutableArray arrayWithCapacity:abe.abeBooksArray.count];
UPDATE The problem is in the addressing of the objects; I have categories named Abe, Balls, Comp, Caller, Hut, and House. I want the class to have properties that can be addressed as Abe, Balls, etc. I can't figure out how to do that with what I have defined.
I have looked through Google, but found nothing that answers my specific question.
Encapsulate, encapsulate, encapsulate! Put the special knowledge inside the class itself.
Let's say you have an ExportBookData object that behaves differently depending which bookseller it uses. Then provide an initializer that takes a bookseller type:
ExportBookData *abe = [[ExportBookData alloc] initWithCategory:#"Abe"];
Okay, so now this instance of ExportBookData knows that its behavior should be Abe-type behavior. But no matter how an ExportBookData is initialized, its public property names will all be the same, e.g. builtFileList and exportData, so you'll then be able to refer to abe.builtFileList and this will be the right kind of list for an Abe.

In ObjectiveC, is it necessary to declare strong vs copy for a readonly property?

In Objective-C, it's common to declare NSString/NSArray/NSDictionary as copy, is it necessary to do that for a readonly property or there is no difference? If an NSString is readonly, it will never be set, so declaring it strong or copy will have the same effect right?
//use strong rather copy here and it will work the same since it will
never be copied?
#property (nonatomic, readonly) NSString *string;
If it really is read-only then you don't need to specify it. If you're going to redeclare it privately to be readwrite then you do want to specify it. For readonly properties it has no effect as no setter will be created.
You're right, but there're some things to consider. That's okay as long, as your property is immutable object. However, it is not always true.
First example, which I run into frequently, is when you have actually mutable object inside of your implementation. Like property declared NSArray in implementation can actually be NSMutableArray. Strong reference property getter for it will return pointer to that NSMutableArray. And, at some point, you'll run into situation when you request NSArray from object, work with it some time and than - boom!!! - your NSArray have different elements of number of it? What the hell? In that case, it's better idea to copy your inner implementation used NSMutableArray in getter.
Another example is some model object
#interface Person : NSObject <NSCopying>
#property NSString *name;
#property NSDate *birthdate;
#end
And you have some other interface with property
#property (strong, readonly) Person *person;
Yeah, you will not assign different object to this property. However, you'll be able to modify its fields, so it will represent some completely different Person. If you don't want such behaviour - make it copy property. Or make it private with access methods to get its fields
- (id) getHiddenPersonPropertyValueForKey:(NSString *)personPropertyKey;
Or any other way
If property represents really immutable value (NSArray, NSIndexSet, etc), then just readonly is fine, as it will be returned immutable as-is.
But in case of your private ivar being mutable (NSMutableArray ivar vs property's NSArray type), you should return a copy to prevent leaks of future internal changes into caller's state.
#interface MyObject : NSObject {
NSMutableArray *_array;
}
#property(nonatomic, readonly) NSArray *array;
// -or-
- (NSArray *)array;
#end
and
#implementation
#dynamic array; // only if #property was declared in interface
- (NSArray *)array
{
return [_array copy];
}
#end
The caller is safe then to store property's value and expect that it will not change even without making explicit copy itself:
self.array = [myObject array]; // e.g. 1 element
[myObject addElementToArray:#(42)];
NSLog(#"%#", self.array); // still 1 element

The Field between Objective-c and Java, and I don't understand the #property and instance variable

From the developer that started to learn objective-c two days ago, I don't understand the difference between the following two methods :
1.
#interface Person : NSObject
#property NSString *firstName;
#property NSString *lastName;
#end
2.
#interface Person : NSObject{
NSString *firstName;
NSString *lastName;
}
#end
Using Java-Language,we define two String Field:
class Person extends Object{
(public/private/protected) String firstName;
(public/private/protected) String lastName;
}
I want to know which one(between 1 and 2) has same meaning with the Java code above.
Very thanks for #iamyogish #Popeye,if my answer is right i will correct both of you.
After read the eBook: Objective-C 2.0 Essentials,I learned that(if it is not right,you tell me. ):
#interface Person : NSObject
#property NSString *firstName;
#property NSString *lastName;
#end
this is equivalent to the Java Code:
class Person extends Object{
private String firstName;
private String lastName;//In fact:private should be protected
//setter and getter.
//you can use ecplise tool to generate setter/getter method automaticly
}
As you can probably imagine, having to write these methods for large numbers(1000 or more.)of complex classes will ultimately prove to be time consuming. Objective-C provides synthesized accessor methods,so what you should is use of the #property and #synthesize directives.if you write your code like this:
#interface Person : NSObject
NSString *firstName;//note that the default access level is protected.
NSString *lastName;
#end
Unfortunatly, you need to provide methods that can access instance variables,such as(you can define the name of the function by yourself)
-(NSString ) getFirstName;
-(NSString ) getLastName;
-(void) setFirstName:(NSString * name);
-(void) setLastName:(NSString * name);
In addition to this,if the #property and #synthesize directives are used,you can access instance variables like C++/JAVA syntax dot notationsuch as:
NSString * firstName= [[Person alloc] init].firstName;
Note that: A key point to understand about dot notation is that it only works for instance variables for which synthesized accessor methods have been declared.
The access level for instance variables is specified in the #interface section of the class declaration using the #protected, #private and #public directives.
#interface Person : NSObject
#public
NSString *firstName;//note that the default access level is protected.
NSString *lastName;
#end
When accessing a public instance variable from another class or any other code in a methods or function, the -> pointer operator notation is used. So you can access the Public Filed in C++/C like:
[[Person alloc] init]->firstName = "your first name";
Another question is:
#interface Person : NSObject
#property NSString *firstName;
#property NSString *lastName;
#end
is is equivalent to:
#interface Person : NSObject{
NSString *firstName;
NSString *lastName;
}
#property NSString *firstName;
#property NSString *lastName;
#end
or not? and ivar is equivalent to instance variable or not?
Lets start with (2)
#interface Person : NSObject
{
NSString *firstName;
NSString *lastName;
}
#end
In this case firstName and lastName are know as ivars or Instance Variables for me I don't generally declare ivars. Some developers now say that you shouldn't put these in the #interface declaration for two reason.
It exposes details about the implementation to users of the class, this will lead other developers who or using and in some cases yourself to rely on implementation details that should be available to them.
Some developers believe that putting these in the #interface can make compile times significantly longer.
Most developers believe that the best way to implement an ivar is within the #implementation where braces are being used like:
#implementation Person {
NSString *firstName;
NSString *lastName;
}
The theory behind why we put them here is because theoretically they are declared private, preventing anyone from knowing about them except the developer who created the class. This will resolve all other developers from messing around with things they shouldn't.
The equivalent to this in Java is just as simple as private String firstName;
Now lets take a look at (1)
#interface Person : NSObject
#property NSString *firstName;
#property NSString *lastName;
#end
Technically #properties need only be used when the property needs to be accessible from other classes, but many developers prefer to use these over ivars as it makes them easier to use, and in new versions of xcode the ivars for these properties are declared automatically in the background.
By declaring a property you are basically automatically generating the getters and setters for these properties. In earlier versions of xcode you did have to #synthesize but there is no need for this anymore. So declaring the two properties firstName and lastName this will generate in the background
- (void)setFirstName:(NSString *)aFirstName
{
self.firstName = aFirstName;
}
- (NSString *)firstName
{
// Note in objective-c we don't generally use `get`
return self.firstName;
}
- (void)setLastName:(NSString *)aLastName
{
self.lastName= aLastName;
}
- (NSString *)lastName
{
// Note in objective-c we don't generally use `get`
return self.lastName;
}
When it comes to comparing this to Java this is near enough the same as
private String firstName;
public void setFirstName(String aFirstName) {
this.firstName = aFirstName;
}
public String getFirstName() {
return this.firstName;
}
We create out instance variable the same way we would do it as if it was a normal ivar but there is nothing to say create my setters and getters in java so we have to do that ourselves. Note that the ivar here in java is still private it is the getters and setters that we are opening up to others.
There is a sort of third option that you have missed as well. Due to the conventions in objective-c what would happen with a #property for a bool?
We have it declared like
#property (nonatomic) BOOL personForObject;
in objective-c when it comes to bools the getter is slightly different in name. Whilst we are happy with the synthesized setter of
- (void)setPersonForObject:(BOOL)aPersonForObject
{
self.personForObject = aPersonForObject;
}
we aren't happy though with the getter, when it comes to bools the getters should start with is so personForObjects getter should be isPersonForObject but the synthesize doesn't know this so will automatically generate the getter the other way. So we need to tell it in the property declaration like
#property (nonatomic, getter=isPersonForObject) BOOL personForObject;
You will now have to implement this method yourself though like
- (BOOL)isPersonForObject
{
return self.personForObject;
}
Note this only need be done if you choice to ignore convention which I wouldn't recommend.
Any questions just ask.
The code number two is equivalent to the Java version.
A #property in the most complete version defines the getter, setter and instance variable. You can also modify the declaration to specify only a getter, only a setter or to specify a different instance variable.
#property is shorthand for defining an instance variable and its corresponding accessors.
If you just define instance variables in the interface, you will not get the accessor methods.
See whenever you declare members in objective-C you should provide getters and setters for those members(Variables). But Objective-C supports something called synthesized accessors using the directives #property and #synthesize.
Now lets see program with synthesized accessors :
#import<Foundation/Foundation.h>
#interface Person : NSObject{
NSString * firstName;// declaring that Person class as variable firstName
NSString * lastName;// // declaring that Person class as variable lastName
}
#property NSString *firstName; // says to compiler that we want to define synthesized accesor for the firstName
#property NSString *lastName;// says to compiler that we want to define synthesized accesor for the lastName
#end
#implementation Person
#synthesize firstName, lastName;// synthesized accessor to be defined for firstName and lastName
#end;
int main(){
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]init];
Person * p = [[Person alloc]init] ;
[p setFirstName:#"Yogish"]; // method setFirstName is implicitly defined by compiler
[p setLastName:#"Gowda"];// method setLastName is implicitly defined by compiler
NSLog(#"%#",p.firstName);
NSLog(#"%#",p.lastName);
[pool drain];
return 0;
}
Now coming back if u haven't used the #property and #synthesize you should have to write your own setters and getters method to set and get the members firstName and lastName. Since you're using #property and #synthesize the compiler will write getters and setter methods .
Hope this helps :)

Is dot syntax or bracket syntax correct for property access?

Suppose I have
#interface A : NSObject
#property (nonatomic, strong) NSMutableArray *array;
#end
Later on in another class B, I want to access that array, to check how many items are in it. I can do one of two things in B (a is an instance of A):
Option 1
[a.array count]
Option 2
[[a array] count];
Which option is the best way to do this? Is option 2 the right way to access the array when using [a array] as the getter method?
both are the same if you have synthesized the array. in first one you just call the property and in 2nd one you are calling the getter method which was generated by #synthesize action.
and sure the 2nd option is the right way as #synthesize makes two methods
1- getter that is same as the property name
2- setter that is add set with property name at start with first letter captial like setArray.
There is no difference between the two if you have synthesized the array, as The Saad said. However, I recommend bracket syntax as to remain consistent in all your method calling as all other Objective-C methods (aside from functions from C) use bracket syntax to be called.
There's no difference until you decide to rename the generated getter/setter methods and the message is likely to become invalid.
For the public instance variables you can skip the accessor methods (both property and method styles) and use the structure dereference operator:
#interface A : NSObject
{
NSMutableArray *array;
}
#property (nonatomic, strong) NSMutableArray *array;
#end
classA.m
[self->array count];
classB.m
[a->array count];
Doing this, you waive the convenience of both operation and memory management optimizations which you have using properties (in both access styles) with the different attributes, see more.
As example for the NSString property
#property (readwrite, copy) NSString *sVar;
the generated setter looks like this:
-(void)setSVar:(NSString*)inSVar
{
if (self->sVar != inSVar)
{
[self->sVar release];
self->sVar = [inSVar copy];
}
}

Memory semantics of a computed array property?

This is for an app that allows users to tag things. Tags are just strings.
An array of TagHolder objects holds a list of all tags in use in the app, with a boolean telling if the tag is selected, but this is an implementation detail.
The external interface calls for two methods, selectedTags, and setSelectedTags: which return and accept an arrays of strings.
I would like these two methods to work as accessors for a declared property selectedTags.
Now, my question is:
What would be the correct memory management semantics to declare for that property?
The code pattern that I have in mind is this (code not tested, so please bear with typos):
#interface TagInfo : NSObject
#property (strong, nonatomic) NSString *tag;
#property (nonatomic) BOOL selected;
#end
#interface SomeClass : NSObject
#property (memorytype, nonatomic) NSArray *selectedTags;
#end
#implementation TagHolder
- (NSArray *)selectedTags
{
// tagInfoArray is an array of all TagInfo objects
NSPredicate *selPred = [NSPredicate predicateWithFormat: #"selected == YES"];
NSArray *selectedTagInfoObjects = [[self tagInfoArray] filteredArrayUsingPredicate: selPred];
NSArray *selectedTags = [selectedTagInfoObjects valueForKey: #"tag"];
return selectedTags;
}
- (void)setSelectedTags: (NSArray *)selectedTags
{
for (TagInfo *tagInfo in [self tagInfoArray]) {
tagInfo.selected = [selectedTags containsObject: tagInfo.tag];
}
}
#end
What should memorytype be? Obviously not strong or weak, but I think it could be any one of assign, copy or even unsafe_unretained, but which one is the most correct for a computed property with an object value?
I normally use ARC, but I guess the question is the same in an environment with manual retain count.
memorytype is significant only when you #synthesize your property accessors. Since you are providing your own implementation for both the getter and the setter, the things you put in parentheses after #property are ignored; I usually put readonly or readwrite there, just to remind myself of what kind of access is available on these properties.
Your code is correct, it will work without creating memory issues with or without ARC.