0

I have a problem with one property in one class. I am coding with iOS 6.1 if it makes any difference.

The class is UIViewController and the property is the declared in the header file like so:

// Keeps track of time in seconds
@property (nonatomic, strong) NSNumber *timeInSeconds;

In my implementation file I use the property during 3 occasions:

  • one is to add time with the method - (void)addTime

  • one is to subtract time with the method - (void)subtractTime

Those two methods use the property like so:

- (void)addTime
{
    CGFloat timeFloat = [self.timeInSeconds floatValue];

    // Here I set the value of the property timeInSeconds, but I can't access that value later on in the code!

    self.timeInSeconds = [NSNumber numberWithFloat:timeFloat +5];
    NSLog(@"Total Time:%@", self.timeInSeconds);
}

The two methods addTime and subtractTime do what they are supposed to do, and they keep a good track of the property timeInSeconds value as I add then subtract then add...

The problem is when I call in the same implementation file the third method which is:

- (void)updateLabelTime
{
   self.label.attributedText = [[NSAttributedString alloc]initWithString:[self.timeInSeconds stringValue]];


   [self.label setNeedsDisplay];

   [NSTimer scheduledTimerWithTimeInterval:0.8 target:self selector:@selector(updateLabelTime) userInfo:nil repeats:YES];
}

I also tried to create a the NSAttributedString with stringWithFormat instead of initWithString but the problem persists which is that instead of returning the value of the property timeInSeconds which i previously set using addTime and subtractTime, it calls the getter which creates a new instance of timeInSeconds since in my getter I have lazy instantiation.

I tried to not write the getter/setter for the property (since I am using iOS 6.1) but it makes no difference.

If I just set the label to some random string, it would work. The problem is that if I know the value of timeInSeconds is 55, it would still create a new _timeInSeconds.

I tried my best with my English since I am French, please don't answer if the question was already asked by a beginner iOS developer and just redirect me. I couldn't find an answer though, thanks!

EDIT: Here is the custom getter

- (float)timeInSeconds
{
if (!_timeInSeconds) {
    _timeInSeconds = 0;
}

return _timeInSeconds;
}

SECOND EDIT:

The stupid beginner mistake that I made was that addTime and subtractTime are actually implementing a protocol and they set the property which "lives" in another class which is why I could not access it! That other class that needs the protocol was creating a new instance of the class where addTime and subtractTime is written.

What needs to be done is to set the controller as the delegate for the protocol. I did this in the viewDidLoad method with something like:

self.view.delegate = self;

Thanks for all the help.

  • 2
    Do you have a custom getter? Please post the code for it. Why store the time as a NSNumber? it would be easier to just store it as a float (or double) `@property (assign) float timeInSeconds;` – progrmr Apr 16 '13 at 12:35
  • In addition to what @progrmr's said, I've had a similar experience before in an ARC project, and it was due to ARC releasing the property on memory warnings. Either way, I'd definitely go with the float suggestion. – mota Apr 16 '13 at 12:44
  • Are you sure ARC releases properties on memory warnings? That would be a shame... – Dario Apr 16 '13 at 13:18
  • I just updated to @property (assign) float timeInSeconds; Unfortunately it still tells me that timeInSeconds is 0.0000 – Bill Capelli Apr 16 '13 at 13:23
  • Thanks for the code formatting, I edited the question. – Bill Capelli Apr 16 '13 at 13:25
  • @Dario I'm sure it did in the past, but it's been a while since I worked on an ARC project, so it may have changed. And it may also happened due the particular configurations of the property it self. – mota Apr 16 '13 at 16:53
  • @Poumé You don't need the `if (!_timeInSeconds)` condition. In fact, you don't need the whole getter method. Just set the initial value of `_timeInSeconds` in `viewDidLoad` or `initWithNibName:` if you want to make sure it's a zero. The condition will always be true if `_timeInSeconds` is 0, which is the default value for float types, I guess. – mota Apr 16 '13 at 16:56
  • @Mota I got rid of the getter, still doesn't work. I think that when I add the two floats together, it doesn't "save". It might be that I am not really changing the value of the property or something like that, I might be getting confused with a lecture I watched about C++. I also added the _timeInSeconds = 0; in the viewDidLoad but I still have this issue. – Bill Capelli Apr 16 '13 at 17:14
  • @Mota ARC does not release properties on memory warnings. – progrmr Apr 18 '13 at 02:29
  • @progrmr I revisited the code base in which the problem's occurred, because I remember putting a hack to solve the problem with a comment. This is the line I've found: `self.popoverTVC.tableView.delegate = self; // ARC resets the delegate when getting a memory warning in iOS5`, so the problem seems to occur in iOS 5 only, and maybe previous versions. – mota Apr 18 '13 at 13:14
  • @Mota: delegate property became nil because it was a `weak` reference, `weak` properties automatically become nil when the delegate it pointed to is dealloc'd. [more here](http://stackoverflow.com/q/7246513/1693173) – progrmr Apr 18 '13 at 16:29
  • @progrmr I see. But the delegate is never dealloc'd in my case as it was the class itself that was set as the delegate. Anyway, thanks for the info! – mota Apr 18 '13 at 16:37

2 Answers2

1

In your header file, declare this property:

@property (assign) float timeInSeconds;

In the implementation file:

@synthesize timeInSeconds = _timeInSeconds;

- (void)viewDidLoad
{
    [super viewDidLoad];
    _timeInSeconds = 0.0f;
}

- (void)addTime
{
    _timeInSeconds += 5.0f;
}

This should initialize timeInSeconds to zero and then increment its value by 5 each time you call addTime. To use its value in the label:

- (void)updateLabelTime
{
   self.label.text = [NSString stringWithFormat:@"%f", _timeInSeconds];
}
mota
  • 5,275
  • 5
  • 34
  • 44
  • Thanks for the help. Unfortunately, there is still the same problem, I NSLoged the issue and I still have _timeInSeconds = 0.0000 in one of my method (updateLabelTime) – Bill Capelli Apr 16 '13 at 18:21
  • Actually Mota, instance variables are always initialised to zero when the object is instantiated. – TheBasicMind Apr 16 '13 at 19:08
  • Thanks a lot for the help!! I just realized that the big mistake that I made was that addTime and subtractTime are actually implementing a protocol and they set the property which "lives" in another class which is why I could not access it! Man, I feel extremely stupid, hopefully this thread might help a beginner who can't access his property value without knowing why. – Bill Capelli Apr 17 '13 at 12:48
0

In your custom getter you are assigning a scalar value to an object property. In fact assigning zero to an object property is the equivalent of setting the object to nil.

What you need to do is this:

- (float)timeInSeconds
{
    if (!_timeInSeconds) {
        _timeInSeconds = [NSNumber numberWithFloat:0.0f];
        // or alternatively with the latest version of objective c
        // you can more simply use:
        // _timeInSeconds = @(0.0f);
    }

    return _timeInSeconds;
}
TheBasicMind
  • 3,585
  • 1
  • 18
  • 20
  • Thanks a lot for the help!! I just realized that the big mistake that I made was that addTime and subtractTime are actually implementing a protocol and they set the property which "lives" in another class which is why I could not access it! Man, I feel extremely stupid, hopefully this thread might help a beginner who can't access his property value without knowing why. – Bill Capelli Apr 17 '13 at 12:49
  • Sorry I can't check both answers and I don't have enough reputation to upvote. – Bill Capelli Apr 17 '13 at 12:54