iPhone SDK

Deselecting a UITableViewCell within a SelectRowAtIndexPath

For quite a while I didn't quite understand how to deselect a UITableViewCell from a UITableView and yet indicate to the user a selection was made. It goes like this:

  1. A user shows a UITableView and selects a row.
  2. The Row highlights to indicate the user made the selection.
  3. The UITableView scrolls away.
  4. The user shows the same UITableView again, this time the same row is selected.
  5. Sad Face for me the programmer

Note: I believe this is only happening with UITableView that is created from a nib file.

So what is the big deal, just use deselectRowAtIndexPath: and it is deselect the row. Well there is a catch, or not if you are smarter than me. The catch is you need out use deselectRowAtIndexPath:indexPath animated:YES and heres why; If you set animated:NO then the row never get highlighted and the user may not really know which cell was selected. But if you use animated:YES then it deselects during the animation, right after it does the selection during the animation. Makes sense? Well not really, but the good part is that the next time the table view is shown the selection is gone, as I wanted.

Sad face gone.

Here is some code to ponder. This is a TableViewDelegate and I'm using the tableview as a modal view.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    
// do some stuff
    [
self.navigationController dismissModalViewControllerAnimated:YES];
    
    [tableView
deselectRowAtIndexPath:indexPath animated:YES];

}

|

iPhone Development: Beta 4

With my fist read through the release notes and API changes, they are still making significant changes but some areas seem to be locked down. There seem to be significant changes to Interface Builder, while not really adding may new Cocoa Touch objects. It seems they are still building the underlying IB infrastructure, before piling on new objects. That's fine I suspect.

Many of the API changes are of the properties type. That look like this:


Modified CLLocation.altitude


Declaration
Old

@property(readonly) CLLocationDistance altitude

New

@property(readonly, nonatomic) CLLocationDistance altitude



While there were a large number of these changes, I suspect they are starting to lock down their APIs in much of the SDK.

Without digging too much into this method, I think I'm going to like it: -[UIViewController initWithNibName:bundle:]

I also want an example of how to use the Proxy Object in IB.


My application didn't compile because they removed UIModalView. But added UIActionSheet and they updated their sample code so it will only take me a few minutes to get back online.
|

iPhone Development: Beta 3 and Interface Builder

I've been wanting to use Interface Builder for my iPhone development and started using it in Beta 2. Well, IB is not well integrated into iPhone development and bugs and/or incompleteness are the rule of the day for IB for iPhone. A Beta 3 bug compiling my xib file blew me out of the water, so I decided to stop using IB for my iPhone application. This was going to cause a great about of pain, because I intended to have a few complex screens where using IB would be the perfect solution. I was bummed.

But then, while looking at the updated examples, what did I find? But the use of xib files and IB. I was very excited because one example was exactly how I needed to use IB for my IPhone application.

The moral of the story? Don't get ahead of Apple's SDK engineers or you will endure much pain.
|

iPhone Development: UITableView nib Hell

I have seeminly come across some UITableView bugs when the table view is created by loading them from a nib file. Well, that is what I believe at the time of this writting. Since is this all new, I may have something wrong causing me the problems.

The gist of the problem is, once the UITableView has been displayed with some cells, when I try to change the state of the cell by using UITableViewDelegate protocols, implemented in my UIViewController for the table view, noting happens. If I try to deselect, reload the data in the view with new data, it just doesn't show up.

For example, making this call doesn't actually visually deselect, but does actually deselect internally, meaning there is not selection in the UITableView.

[(UITableView*)self.view deselectRowAtIndexPath:selectedRowPath animated:animated];

If I want to reload the view with a different set of cell data and I do the following.

- (
void)viewWillAppear:(BOOL)animated
{
      
self.title = [self categoryToShowInTable];
      [(
UITableView*)self.view reloadData];
}

All the table vie delegates get called such as cellForRowAtIndexPath, but the view as displayed doesn't show the new items.

It almost seems to me that I have something very wrong, and it is causing me this behavior. If that is the case I'll update this entry with the solution.
|

iPhone Development: The Whole Delegate Trickery

I'm not sure it is trickery, but it is useful. When a controller becomes a delegate for a view it sure makes things easy and hold together for the MVC pattern.

@interface CategoriesViewController : UIViewController

So, I declare my view controller and add in a few protocols and I'm in business. Well, have access to the "business" anyway. I don't know how this is done in the OO runtime world, where it came from, (Smalltalk?) but I sure do like it.
|

NSTreeController Development: Walking the Tree

Since I started developing for Mac OS X on brand new shinny Leopard, I was able to take advantage of the new API calls on NSTreeController to walk the tree, access the real objects and not the proxy objects and to insert items into the controller easier than folks have in the past.  That is what I've gathered from reading about NSTreeController on the Internet.

The method arrangedObjects is very useful, see here: – arrangedObjects Notice that it returns a proxy root tree node containing the receiver's sorted content object. Those are some very important words and hard to explain, so instead of trying to explain, I''ll show.

NSArray *treeNodes = [[self arrangedObjects] childNodes];

So, arrangedObjects returns a proxy root tree node, so just pass that into the childNodes of NSTreeController, another useful 10.5 method, and you get all the children of the treeNode. Since I used arrangedObject, I get the top of the tree so that I can with it as I please, mostly.

Anyway here are some category classes that allow you to walk the tree using any controller selector as a callback.  This example is not perfect, it  is a work in progress, but useful none the less.

The code below is defined as a catagory of NSTreeController, in a garbage collected environment, so there is no memory management.

//
// NSTreeController-Extensions.h
//
// Created by Joe Michels on 3/8/08.
// Copyright 2008 Software Ops LLC. All rights reserved.
//

#import Cocoa/Cocoa.h


@interface NSTreeController (NSTreeController_Extensions)

- (
void)visitAllNodesStartingWithNode: (NSArray* )treeNodes useSelector: (SEL)inSelector
                                                                 withObject: (
id)inObject;

@end


//
// NSTreeController-Extensions.m
// TeamPlayer
//
// Created by Joe Michels on 3/8/08.
// Copyright 2008 Software Ops LLC. All rights reserved.
//

#import "NSTreeController-Extensions.h"
#import
"ProjectsController.h"


@implementation NSTreeController (NSTreeController_Extensions)


- (
void)visitAllNodesStartingWithNode: (NSArray* )treeNodes
                                                                         useSelector: (
SEL)inSelector
                                                                         withObject: (
id)inObject
{
      
// This is a recursive decent routine. It will walk the tree visiting each node

      
for (id item in treeNodes)
      {
            
NSLog( @"Visiting tree node: %@", [[item representedObject] valueForKeyPath:@"name"] );

            [
self performSelector:inSelector withObject:item withObject:inObject];

            
//check for a decendent
            
NSArray *childNodes = [item childNodes];
            
if ([childNodes count] > 0)
                                                                             
// we are recursing
                  [
self visitAllNodesStartingWithNode:childNodes useSelector:inSelector withObject:inObject];
      }
}
@end


Let's make a call using the above code.

- (NSArray* )itemsForScripting
{
      
NSLog(@"Getting projects for scripting, returned in array.");
      
      
NSArray *treeNodes = [[self arrangedObjects] childNodes];
      
NSMutableArray *itemsArray = [[NSMutableArray alloc] initWithCapacity: 2]; << 2??, whatever!

      [
self visitAllNodesStartingWithNode:treeNodes
            
useSelector:@selector(getOrderedListOfProjects:withArray: )
            
withObject:itemsArray];
      
      
return itemsArray;
}


You can pass nil for the object as in this code snipet:

NSArray *treeNodes = [[self arrangedObjects] childNodes];
[
self visitAllNodesStartingWithNode:treeNodes
      
useSelector:@selector(findAllMatchesInNodes:withObject: )
      
withObject:nil];


|

NSTreeController Development: Inserting Objects for Scripting

I might as well make my first comments about the App Store even before my app hits the store. That way, I will be commenting using pure logic and not emotion from my own experiences.

First I want point out that I want constructive criticism from users who have actually purchased My Eyes Only™.

The Freetards


Where to start with this. The freetards have polluted the App Store. This is a disgrace to the wonderful App Store. Using the word disgrace is an emotional response and I said I would use logic. Well, there is just no logic to the freetards. It is a religion filled with emotion.

Report Your Problems to the Company


It theory, this should not be needed but if you run across repetitive problems that you did have in the first place, then reboot. Here is one comment that was fair but, put the blame in the wrong place. This was for an application that I’m interested in purchasing.

I was just about to post this great review about how the application is easy to use and turns you free time in great fun, when I started to have stability issues with it. At the moment the program does not run at all, clicking ok the icon does nothing but shows the splash screen (which it already annoyed me because it takes time from starting the application) the quits.



Well I had the same problem with my iPhone I was stumped. But, by happen stance I decided to re-download my apps from the store. Did you know you could do that? Well that cleared up my problem.

Reboot Your iPhone


I was testing MEO and I found a bug that I could reproduce. Those are the best! I did it 5 times while having lunch so I had it nailed. Well, I decided to reboot the iPhone, just to see what would happen. Well... I could not reproduce the problem. In fact, I spent an hour and a half trying to reproduce the issue and finally gave up. It most likely wasn’t my problem.

|

iPhone Development: Interface Builder -Read the Damn Release Notes!

I was glad that Interface Builder was included in the second drop of the iPhone SDK as I like the feedback of seeing the views as they are laid on the screen.  I dove into IB and started using it just like one might for Mac OS X, create a window, drop in a Table View add a Navigation View  set up the corresponding controllers and sure enough when I added a bit of code to my iPhone app, it saw the table view in the simulator.  But when I went to navigate to the next  view it didn't work.  Sigh.  "I must have something connected wrong in IB" I said to myself and spent many hours connecting outlets and trying everything that might make sense.  Nothing worked.

What to do?

Since there was no iPhone example application using IB, I was on my own and started digging around.  I first realized that the UINavigationController as setup by the nib loading process was missing a few initialized objects as compared to one initialized with initWithRootViewController.  Hmm...  OK, so I ditched the nib based UINavigationController with one I created and initWithRootViewController. "That should help", I thought. Ah... no.  I better try to find more about IB and iPhone.  So I reread the release notes and sure enough, right there in front of my face was the answer:

FAQ: How do I edit a Cocoa Touch view controller? ▪ Drag a view controller object from the library into the document window. ▪ In the document window, double-click the icon for the view controller object to open its editor. ▪ Drag and drop views, navigation items, and tab bar items from the Library onto the editor.


Well, OK.  To be fair to me, when I first read this I was not thinking that I defined the UI by dragging and dropping views onto a view controller UI thingy.  When I did, cha-ching! it worked.
|