No, there is no memory leak. The code in your second example is logically equivalent to
foo = [[NSObject alloc] init];
[nil retain];
[foo release];
foo = nil;
because the @synthesized setter is logicall equivalent to
- (void)setFoo:(id)newFoo {
[newFoo retain];
[foo release];
foo = newFoo;
}
It's worth noting that setting foo directly is probably not something you want to do outside of an init method. If you assign a value to foo directly, you bypass the automatic KVO notification (you would have to wrap your assignment in a willChangeValueForKey:/didChangeValueForKey: pair) and you break any subclass' behavior if it overrides the setFoo: method, expecting all modifications of foo to go through the setter.
You assign directly to foo in an init method because the setFoo: method or a subclass' overriden setFoo: method may have side-effects or depend on the instance's fully initialized.
Similarly, you would use [foo release] rather than self.foo = nil; in the -dealloc method for the same reasons.