Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>First, a small bug...</p> <p><code>liveTimer = [NSString stringWithFormat:@"%@:%@.%@", minutesString, secondsString, hundredthsString];</code></p> <p>This is probably why it was crashing when you called reload tableView.</p> <p>You actually want:</p> <p>either: </p> <pre><code>self.liveTimer = [NSString stringWithFormat:@"%@:%@.%@", minutesString, secondsString, hundredthsString]; </code></pre> <p>(if you've configured liveTimer to be a property and not just a member variable)</p> <p>or</p> <pre><code>[liveTimer release]; liveTimer = [[NSString stringWithFormat:@"%@:%@.%@", minutesString, secondsString, hundredthsString] retain]; </code></pre> <p>or </p> <pre><code>[liveTimer release]; liveTimer = [[NSString alloc] initWithFormat:@"%@:%@.%@", minutesString, secondsString, hundredthsString]; </code></pre> <p><code>stringWithFormat:...</code> returns an auto-released string, which means that it gets released as at the end of the current spin through the run loop. This will result in liveTimer pointing at undefined memory essentially after your function finishes. Using self.liveTimer instead of liveTimer causes your synthesized setter method to be called instead of just setting the variable directly, which causes your object to retain the string as it's being set (assuming you've setup the live timer property to retain, like so: <code>@property (nonatomic, retain) NSString *liveTimer;</code> The other two alternatives listed above both release the old version of the string and then retain the new string and set then set the variable directly. Which one you prefer between the first and the last is more or less a matter of taste, the second one is kind of silly (it roundaboutly creates the string, autoreleases it, and then retains it again.)</p> <p>Now, on to your question.</p> <p>At the end of <code>- (void)targetMethod: (NSTimer *)theTimer</code>, you'll want to actually update the current table cell, if it exisits. Assume the tableCell exists at row 0 of section 0:</p> <pre><code>-(void)targetMethod: (NSTimer *)theTimer { // Everything you already had here, then... NSIndexPath *cellIndexPath = [NSIndexPath indexPathForRow:0 inSection:0]; UITableViewCell *currentCell = [tableView cellForRowAtIndexPath:cellIndexPath]; // Returns the cell that's currently in the tableview at this location currentCell.detailTextLabel.text = self.liveTimer; } </code></pre> <p>That should do it... if the current cell doesn't exist (because it's scrolled off the screen) <code>cellForRowAtIndexPath:</code> will return nil, and <code>currentCell.detailTextLabel.text = self.liveTimer;</code> will do nothing (i.e. no error, just literally nothing).</p> <p>Edit:</p> <p>I just noticed that tableView is not one of your object member variables...</p> <p>Do you have a <code>UITableViewController</code> hanging around that you can get to? If so, just use <code>tableViewControllerVariableName.tableView</code> everywhere you presently use tableView. Is your RootViewController (which all this code is in) a UITableViewController? If so call <code>self.tableView</code> wherever you currently call tableView. If not, where is your tableView/tableViewController being allocated? Posting your header file might help clear things up...</p> <p><strong>Edit 2:</strong></p> <p>The issue with liveTimer vs. self.liveTimer is all about the retain count on the object.</p> <pre><code>liveTimer = [NSString stringWithFormat:@"%@:%@.%@", minutesString, secondsString, hundredthsString]; </code></pre> <p>does just what it looks like--it sets your liveTimer variable to the new string. Whereas</p> <pre><code>self.liveTimer = [NSString stringWithFormat:@"%@:%@.%@", minutesString, secondsString, hundredthsString]; </code></pre> <p>is a little bit magic. Using the <code>self.</code> prefix (or, for that matter <code>anyObject.</code>) tells the compiler "what I really want to do here is call the accessor method for the liveTimer property". The compiler essentially replaces the above line with:</p> <pre><code>[self setLiveTimer:[NSString stringWithFormat:@"%@:%@.%@", minutesString, secondsString, hundredthsString]]; </code></pre> <p>Because you presumably have <code>@synthesize liveTimer;</code> somewhere in your class file, the compiler also creates the <code>-(void)setLiveTimer:(NSTimer *)timer</code> and <code>-(NSTimer *)liveTimer</code> methods for you automatically. They looks something like this:</p> <pre><code>-(void)setLiveTimer:(NSTimer *)newLiveTimer { [liveTimer release]; // This is the old value. It may be nil, which is fine. Calling methods on nil objects in objective-c is just be a noop, not a crash. liveTimer = [newLiveTimer retain]; } -(NSTimer *)liveTimer { return liveTimer; } </code></pre> <p>(This is a bit of an over-simplification, but that's the important stuff.)</p> <p>So, when you call <code>self.liveTimer</code>, the <code>setLiveTimer:</code> method gets called with the object, the old object, if any, gets released, and the new object gets retained.</p> <p><code>[NSString stringWithFormat:...]</code> returns an autoreleased object. Autoreleased objects get released after control returns from the program's code to the apple-supplied run-loop code. They are more or less a convenience so we don't have to <code>release</code> all the little objects that we use once or twice here and there. (For example, imagine how tedious it would be if you had to release every string you created with the @"" syntax...)</p> <p>We can tell <code>stringWithFormat:</code> returns an autoreleased object because, by convention, methods who's names don't start with <code>alloc</code> or <code>copy</code> always return auto-released objects. Methods like this are said to "vend" an object. We can use these objects in the immediate future, but we don't "own" it (i.e. we can't count on it being there after we return control to the system.) If we want to take ownership of a vended object, we have to call <code>[object retain]</code> on it, and then it will be there until we explicitly call <code>[object release]</code> or <code>[object autorelease]</code>, and if we don't call <code>release</code> or <code>autorelease</code> on it before we lose our reference to it by changing the variable to something else, we will leak it.</p> <p>Contrast with <code>[[NSString alloc] initWithFormat:</code>. This method "creates" an object. We own it. Again, it will be there until we explicitly call <code>[object release]</code>.</p> <p>So, you were setting the member variable <code>liveTimer</code> to a new string, but that string was auto-released, and as soon as your <code>- (void)targetMethod: (NSTimer *)theTimer</code> returned, control returned to the system's run-loop code, and that string was getting released. That meant that liveTimer pointed to some random spot in memory that at one point had contained your string object, but now contained something else--something undefined. When you called a method on that random spot in memory it, it crashed.</p> <p>(To confuse things further, <code>[NSTimer scheduledTimerWithTimeInterval:target:selector:]</code> is a special case. The timer retains itself until it fires, which is why that part of your code works. Nobody really knows why NSTimer gets an exception; it's confusing as hell. It's left over from the NExT days--code written in the early 90s when it seemed like a good idea to someone.)</p> <p>So, do you want to use <code>self.liveTimer</code> or <code>self.timer</code>, or <code>self.whatever</code> everywhere? More or less. You normally want to retain the new object and release the old. <strike>The only</strike> One of the many exceptions is that if you "create" an object with <code>[[Object alloc] init]</code>, that object comes to you with a retain count of 1 already, in that case, using the <code>self.</code> syntax will retain the object a second time, which is probably not what you want. (Although, if you've set <code>self.liveTimer =</code> before and you then use <code>liveTimer =</code> later in your code, the first string will be leaked, because nothing ever released it. It's not always trivial, deciding which way to do it.)</p> <p>Hope that clears things up a little. This dotted notation stuff in objective-c is the least intuitive part of the language, I think. Be sure to read apple's document on memory management:</p> <p><a href="http://developer.apple.com/library/ios/#documentation/general/conceptual/DevPedia-CocoaCore/MemoryManagement.html" rel="nofollow">http://developer.apple.com/library/ios/#documentation/general/conceptual/DevPedia-CocoaCore/MemoryManagement.html</a></p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload