0

there are two properties like below

#import <Foundation/Foundation.h>

@interface Contact : NSObject

@property(nonatomic, strong)NSDate *birthDay;
@property(nonatomic, weak)NSDate *birthDay1;

- (void)testWeakProperty;

@end

on implementation file as:

- (void)testWeakProperty {
    self.birthDay = [NSDate dateWithTimeIntervalSinceNow:0];
    self.birthDay1 = self.birthDay;
    self.birthDay = nil;
    NSLog(@"_birthday1 is %@, %@", self.birthDay1 , self.birthDay);
}

why the result is not _birthday1 is (null), (null)?

I found that iOS ARC - weak and strong properties. if self.birthDay is constant, it will not be deallocated. but there is [NSDate dateWithTimeIntervalSinceNow:0],

now I want to know if the return value is constant and how to verify declare result is constant and a variable.

Community
  • 1
  • 1
maple
  • 101
  • 1
  • 13

2 Answers2

2

The key here is that you're dealing with an autorelease object. If a method name starts with init, copy, mutableCopy or new, you'll receive a non-autorelease object. This is not the case here (you are using dateWithTimeIntervalSinceNow) and as a result, you'll receive an autorelease object.

Thus, you are instantiating an autorelease object and therefore it will not be deallocated until the autorelease pool is drained. And your weak reference will not be nil-ed until the object is deallocated. The deallocation of autorelease objects happens when your app yields back to the run loop (or you explicitly create your own autorelease pool).

This not a question of the object being "a constant". And that other question you reference is discussing NSString which, being heavily optimized, does not conform to traditional object memory management rules.

You can change the behavior by explicitly adding your own autorelease pool, which will cause the object to be deallocated when the pool is drained at the end of the @autoreleasepool block, and you'll see your (null), (null) response:

@autoreleasepool {
    self.birthDay = [NSDate dateWithTimeIntervalSinceNow:0];
    self.birthDay1 = self.birthDay;
    self.birthDay = nil;
}
NSLog(@"_birthday1 is %@, %@", self.birthDay1 , self.birthDay);

You can also use a non-autorelease object (e.g. use a method whose name starts with init) and this non-autorelease object will be deallocated immediately after being set to nil:

self.birthDay = [[NSDate alloc] initWithTimeIntervalSinceNow:0];
self.birthDay1 = self.birthDay;
self.birthDay = nil;
NSLog(@"_birthday1 is %@, %@", self.birthDay1 , self.birthDay);

This will also show you (null), (null).

Rob
  • 415,655
  • 72
  • 787
  • 1,044
0

As Rob explaining, the important point is the fact you are using an auto-released object.

Just a small precision about his explanation, [NSDate date...] is in fact a short (convenience) version of :

[[[NSDate alloc] initWith...] autorelease]

Which behave differently than an non-autoreleased instance:

[[NSDate alloc] initWith...]
Vincent Guerci
  • 14,379
  • 4
  • 50
  • 56
  • Thanks your quickly reply. – maple Jun 28 '14 at 08:21
  • you're welcome, but on stackoverflow to thank someone, you upvote/approve their answer ;) – Vincent Guerci Jun 28 '14 at 08:31
  • sorry, i can' vote you answer, because of my reputation is below 15 .when i test use NSString like below: On .h file i declare a variable `@property(weak)NSString *address;` in implementation file i write below method `- (void)testWeakString { NSString *rawString = @"Hello, "; NSString *resultString = [rawString stringByAppendingString:@"World"]; self.address = resultString; resultString = nil; NSLog(@"what's is my address: %@", self.address); } ` the result is **what's is my address: (null)**, is there any different. – maple Jun 28 '14 at 08:43
  • Weird I would expect an error there, since self.address reference a deallocated address. – Vincent Guerci Jun 28 '14 at 08:57
  • yeah, because the property is weak, when address is deallocated, self.address will be nil. this is weak feature – maple Jun 28 '14 at 09:08