1

I have a class that represents some data. I'm getting this data from a Web Service in the JSON format. The web service does not conform to the Objective - C naming convention. More specifically, all the attributes of an object starts with capital letter, for example Name.

I want to be able to utilize the built-in KVC but still build my objects with the Objective-C naming convention.

So in my public class declaration I'm declaring one property:

@interface TVPage : NSObject
@property (nonatomic, copy) NSString *name;
@end

And In my *.m file I'm declaring a category extension to conform to the Web Service naming convention:

@interface TVPage ()
@property (nonatomic, copy , getter = name , setter = setName:) NSString *Name;
@end

In the private property I'm specifying the getter and setter that I want to actually access the data.

All I want to achieve is just another method, called Name that will actually call name behind the scene. (setName: actually fits for both Name and name)

My question is, when I'm synthesizing the properties like that:

@implementation TVPage
@synthesize name;
@synthesize Name;
@end

Will it generate two different Instance Variables called Name and name or is it smart enough to understand not to do that and create only one named name?

Can I tell the compiler explicitly - "Do not generate IVar for this property"?

Thanks!

EDIT:

Why would I want to do that?

A lot of you asked me what exactly am I trying to achieve here. Well, what I'm trying to do is to make my life easier when it comes to parsing the data returned from the web service.

The data is returned as a JSON String. That means that when I'll parse it, I'll probably get back NSDictionaries to represent the data.

I want to easily create objects that I designed to hold this data, because it's not convenient, safe or readable to work with dictionaries as a data model.

Now, the Key-Value Coding features allow me to set the attributes of an object, directly from a dictionary using setValuesForKeysWithDictionary:

But this will work only if my object actually have accessor methods with the same names as the dictionary's keys. If there is a key that don't have a matching attribute in my object, I'll get an exception from setValue:forUndefinedKey:.

To avoid that I want to create Facade Interface that will conform to the Key-Value Coding methods implied by the attribute names from the server. At the same time I want that the implementation of that interface will access the same data that the "regular" interface access.

7
  • 2
    Did you try it or should we try it for you? Commented Apr 1, 2012 at 13:04
  • But how could I tell? In any case only one of them is going to actually being used. The question is not if it is reliable (because it is) but rather if it is going to allocate useless memory in every instance of this class. Commented Apr 1, 2012 at 13:08
  • What is the purpose of the capital letter Name property? Commented Apr 1, 2012 at 15:05
  • 2
    you could try that with a very very simple test: object.name = @"a"; object.Name = @"b"; NSLog(@"a:%@, b:%@", object.name, object.Name); Commented Apr 1, 2012 at 15:49
  • 1
    God help everybody who will mantain such a code! Commented Apr 1, 2012 at 16:21

2 Answers 2

3

As I said, write some test code and then don't continue with whatever you are doing.

@property (strong, nonatomic) NSString *name;
@property (nonatomic, copy , getter = name , setter = setName:) NSString *Name;

and @synthesize both. To see what happens we put some logging code into our s/getter, like this.

- (void)setName:(NSString *)aName {
    NSLog(@"setter called");
    name = aName;
}

- (NSString *)name {
    NSLog(@"getter called");
    return name;
}

and now have some testing fun.

NSLog(@"setValue:forKey: with Key name");
[self setValue:@"Name" forKey:@"name"];
NSLog(@"setValue:forKey: with Key Name");
[self setValue:@"Name" forKey:@"Name"];

NSLog(@"valueForKey: with Key name");
NSLog(@"ptr: %p", [self valueForKey:@"name"]);
NSLog(@"valueForKey: with Key Name");
NSLog(@"ptr: %p", [self valueForKey:@"Name"]);

NSLog(@"\n");

NSLog(@"calling setter via dot-notation for name");
self.name = @"foo";
NSLog(@"calling setter via dot-notation for Name");
self.Name = @"foo";

NSLog(@"calling getter via dot-notation for name");
NSLog(@"ptr: %p", self.name);
NSLog(@"calling getter via dot-notation for Name");
NSLog(@"ptr: %p", self.Name);

let's run it. et voila.

[4115:f803] setValue:forKey: with Key name
[4115:f803] setter called
[4115:f803] setValue:forKey: with Key Name
[4115:f803] setter called
[4115:f803] valueForKey: with Key name
[4115:f803] getter called
[4115:f803] ptr: 0x36d8
[4115:f803] valueForKey: with Key Name          <-----
[4115:f803] ptr: 0x0                            <-----
[4115:f803] 
[4115:f803] calling setter via dot-notation for name
[4115:f803] setter called
[4115:f803] calling setter via dot-notation for Name
[4115:f803] setter called
[4115:f803] calling getter via dot-notation for name
[4115:f803] getter called
[4115:f803] ptr: 0x3758
[4115:f803] calling getter via dot-notation for Name
[4115:f803] getter called
[4115:f803] ptr: 0x3758

You see? The custom getter name is not called for valueForKey:@"Name". However the custom setter is called. But probably only because you can't capitalize a capital letter.

I hope you don't just blindly use setValuesForKeysWithDictionary: with a bunch of values. You have to validate those keys anyway, because you don't want to call that method for keys like self, description and so on. So while you validate the keys just "decapitalize" the names of the keys.
Removing the capital letter is IMHO a much cleaner way because it doesn't fail for half of the accessor methods like it happened with those strange shadow variables.

Sign up to request clarification or add additional context in comments.

1 Comment

Alright, Alright... Code readability is more important to me than efficiency. Thank you for you efforts.
1

Yes you can tell the compiler. You need to not use @synthesize but @dynamic which just tells the compiler to trust you that there is an implementation of that somewhere, and don't throw warnings etc.

6 Comments

Would this still create the setters / getters?
as is said, it tells the compiler "the getter and setter for this do exist, you don't need to worry", so no, the compiler would not generate setter and getter. in your case, you'd want to use @synthesize for name and @dynamic for Name.
Ok. It looks like he still wants to be able to use -Name though so when using @dynamic he'd still have to write the getter manually, correct?
@Tim no, because of the getter = name , setter = setName: when declaring the property. that makes all accesses to that property use the getters and setters specified
@Ahti - Matthias was right, I can't assure that the right getter will be called, so I'm abandoning the idea. Sory, but thank you for your effort.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.