NSUserDefaults KVO in iOS7

Though its not well documented, NSUserDefaults do support key-value observing in iOS7. The following code works:

- (void)viewDidLoad {
  [super viewDidLoad];
  NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
  [ud addObserver:self 
    forKeyPath:@"bar" 
    options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew 
    context:nil];
  [ud setObject:@"foo" forKey:@"bar"];
}

-(void)observeValueForKeyPath:(NSString *)keyPath 
  ofObject:(id)object 
  change:(NSDictionary *)change 
  context:(void *)context {
  NSLog(@"%@", change);
}

Its much more convenient then using NSUserDefaultsDidChangeNotification, since we do know exactly which key is changing.

As the hardware of mobile devices become more and more powerful, I hope the support of key binding could be actualised in near future 🙂

Objective C Property Attributes

Just read a post about Objective C property attributes. I wanna make some extra notes on this topic:

1. “weak” vs “assign”

We generally use weak for Objective-C objects that we don’t need to retain, e.g.

[sourcecode language=”objc”]
@property (weak) IBOutlet UIButton aButton;
[/sourcecode]

because its always good to nil an object if it has been deallocated.

On the other hand, we could use assign for C primitives, e.g.

[sourcecode language=”objc”]@property BOOL isGood;[/sourcecode]

because C primitives has nothing to do with retain count and deallocation, simply assign the value is good enough.

Note that assign is the default property attribute, we can skip it for C primitives for cleaner code.

2. The default attribute of property vs variable

There are 2 kinds of default: property and variable

For property, the default attribute is “assign”

For variable (ivar or local variable), the default ownership qualifier is “__strong”

Don’t mix up “strong” in property and “__strong” in variable. They are different things (see below).

Also remember the default property attribute is “assign”, not “strong”

3. Implicit attribute for the default

The explicit version of

[sourcecode language=”objc”]@property BOOL isGood;[/sourcecode]

should be:

[sourcecode language=”objc”]@property (atomic, assign, readwrite) BOOL isGood[/sourcecode]

so skipping the attributes by using the default is fine for C primitives in most cases.

However, we better explicitly state the attributes for Objective-C objects. Because we seldom want “assign” for objects.

For ivar and local variable,

[sourcecode language=”objc”]NSString *str;[/sourcecode]

is equivalent to

[sourcecode language=”objc”]__strong NSString *str;[/sourcecode]

so if you set it as an ivar, the compiler will automatically retain it for you when you assign a value for it. Which behave differently from not using ARC.

4. Relationship between property attributes and ownership qualifiers

Here listed their relationships according to the official documentation

  • assign implies __unsafe_unretained ownership.
  • copy implies __strong ownership, as well as the usual behavior of copy semantics on the setter.
  • retain implies __strong ownership.
  • strong implies __strong ownership.
  • unsafe_unretained implies __unsafe_unretained ownership.
  • weak implies __weak ownership.

So for property attributes in ARC, practically we can assume assign = unsafe_unretained, and strong = retain.