Key-value coding allows setters to allow Mutable objects

I previously added the code on p.292 (copy prevents changing lastName) to main.m. It worked as expected(logging myObj shows “Ono”, not “OnoLennon”). I then tried the code on p 298 (use key-value coding), then had to modify the accessors back to using _productName = [pn copy], instead of [self setProductName:pn]; (mentioned on p.285), built and ran, and the code from p.292 logs “OnoLennon: 120 volts”.

So it appears KV coding doesn’t copy, but sets a pointer to the new object when you [x appendString:myObj]. Very interesting, or I’m thinking about this wrong. My code is below.

BNRAppliance.h

@interface BNRAppliance : NSObject

//ch35 need for KV coding
{
NSString *_productName;
}

//comment next line to use KV coding
//@property (nonatomic, copy)NSString *productName;
@property (nonatomic) int voltage;

//the designated initializer
-(instancetype)initWithProductName:(NSString *)pn;

@end

BNRAppliance.m

#import “BNRAppliance.h”

@implementation BNRAppliance

-(instancetype)init {
return [self initWithProductName:@“Unknown”];
}

-(instancetype)initWithProductName:(NSString *)pn {
//call NSObject’s init method
self = [super init];

//did it return something non-nil?
if (self){
    //set the product name
    _productName = [pn copy];
    //[self setProductName:pn];
    
    //give voltage a starting value
    _voltage = 120;
    //[self setVoltage:120];
}

//return a pointer to the new object
return self;

}

-(NSString )description{
return [NSString stringWithFormat:@"<%@: %d volts>", _productName, self.voltage];
}
/

-(void)setVoltage:(int)voltage {
NSLog(@“setting voltage to %d”, voltage);
_voltage = voltage;
}
*/
@end

main.m

int main(int argc, const char * argv[]) {
@autoreleasepool {
BNRAppliance *a = [[BNRAppliance alloc] init];
NSLog(@“a is %@”, a);
//[a setProductName:@“Washing Machine”];
//for key-value coding
[a setValue:@“Washing Machine1” forKey:@“productName”];
//[a setVoltage:240];
[a setValue:[NSNumber numberWithInt:240] forKey:@“voltage”];
NSLog(@“a is %@”, a);

    NSLog(@"the product name is %@", [a valueForKey:@"productName"]);
    
    //ch34 on properties
    NSMutableString *x = [[NSMutableString alloc] initWithString:@"Ono"];
    BNRAppliance *myObj = [[BNRAppliance alloc] init];
    
    //[myObj setProductName:x];
    [myObj setValue:x forKey:@"productName"];
    //if you use key-value coding, you don't copy, so you can append the productName in myObj
    [x appendString:@"Lennon"];
    NSLog(@"%@", myObj);
    
    
}
return 0;

}