UINavigationController and Duplication

Discussion in 'iOS Programming' started by Sarashinai, Oct 31, 2011.

  1. Sarashinai macrumors newbie

    Joined:
    Oct 31, 2011
    #1
    Hello all!

    I'm using a UINavigationController and I want to reuse a UITableView. To that end, I've made the data sources for the table properties. Here are the files for the view.

    WordList.h:
    Code:
        
    @interface WordList : UIViewController <UITableViewDelegate, UITableViewDataSource,   UISearchBarDelegate>{
        }
    
        @property (nonatomic, retain) IBOutlet UIViewController *selfRef;
        @property (assign) NSDictionary *wordList;
        @property (assign) NSArray *indexList;
        @property (assign) UINavigationController *useNC;
    
    
        - (void)setNavigationController:(UINavigationController *)nc;
        - (void)setSource:(NSString *)source;
        - (void)dealloc;
    
        @end
    
    WordList.m:
    Code:
        @implementation WordList
    
        @synthesize selfRef;
        @synthesize wordList;
        @synthesize indexList;
        @synthesize useNC;
    
        //static NSDictionary *wordList = nil;
        //static NSArray *indexList = nil;
        //static UINavigationController *useNC;
    
        - (void)awakeFromNib {
          self.title = @"English -> ASL";
        }
        
        - (void)viewDidLoad {
          if (!wordList){
            Database *db = [Database singleton];
          
            if (db) wordList = [db getWordList];
            
            indexList = [wordList allKeys];/*[NSArray arrayWithObjects:@"A", @"B", @"C", @"D", @"E", @"F", @"G", @"H", @"I", @"J", @"K", @"L", @"M", 
                                            @"N", @"O", @"P", @"Q", @"R", @"S", @"T", @"U", @"V", @"W", @"X", @"Y", @"Z", nil];*/
            
            [wordList retain];
            [indexList retain];
          }
        }
        
        - (void)setSource:(NSString *)source {
          Database *db = [Database singleton];
          
          NSLog(@"%@:setSource", self);
          
          if (db) wordList = [db runWordListQuery:source];
          
          NSLog(@"Word list: %@", wordList);
          
          indexList = [wordList allKeys];/*[NSArray arrayWithObjects:@"A", @"B", @"C", @"D", @"E", @"F", @"G", @"H", @"I", @"J", @"K", @"L", @"M", 
                                          @"N", @"O", @"P", @"Q", @"R", @"S", @"T", @"U", @"V", @"W", @"X", @"Y", @"Z", nil];*/
          
          NSLog(@"Index list: %@", indexList);
        
          [wordList retain];
          [indexList retain];
        }  
        
        - (void)setNavigationController:(UINavigationController *)nc {
          NSLog(@"%@:setNavigationController(%@)", self, nc);
          
          useNC = nc;
        }
        
        - (void)dealloc {
          NSLog(@"WordList:dealloc");
        
          if (wordList) [wordList release];
          if (indexList) [indexList release];
          
          [super dealloc];
        }
        
        - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
          EntryViewer *ev = [[EntryViewer alloc] initWithNibName:@"EntryViewer" bundle:nil];
          if (ev){
            [[tableView cellForRowAtIndexPath:indexPath] setSelected:NO animated:YES];
            
            [ev setEntry:[[[wordList objectForKey:[indexList objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row] ident]];
            
            if (useNC){
              [useNC pushViewController:ev animated:YES];
            }
            else {
              [APP_LISTNAV pushViewController:ev animated:YES];
            }
            
            [ev release];
          }
        }
        
        - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
          return indexList;
        }
        
        - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
          return [indexList objectAtIndex:section];
        }
        
        - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
          NSLog(@"%@:numberOfSectionInTableView(%u): %@", self, [indexList count], indexList);
          
          return [indexList count];
        }
        
        - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
          NSInteger section = -1;
          
          section = [indexList indexOfObject:title];
          
          return section;
        }
        
        - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
          // Return the number of rows in the section.
          
          return [[wordList objectForKey:[indexList objectAtIndex:section]] count];
        }
        
        
        // Customize the appearance of table view cells.
        - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
          NSString *CellIdentifier = [[[wordList objectForKey:[indexList objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row] description];
          
          UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
          if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
          }
          
          cell.textLabel.text = CellIdentifier;
          
          return cell;
        }
        
        @end
    
    I'm still finding my feet in regards to Objective-C properties so I may be misusing them. The problem is that, even though the assignments in setSource: work, the table shows no data. Please see the NSLog() output below.

    It's clear why the table shows no data, the call to `numberOfSectionsInTable:` returns 0. What I want to know is why. I'm pretty certain, as you can see from the log, that it's because the value of `self` is different from the previous two calls. Why is this? The third call comes after the call to `pushViewController:`. Is that the reason? Am I approaching this wrong or have I missed something simple?

    Thank you for your time.
     
  2. larswik macrumors 68000

    Joined:
    Sep 8, 2006
    #2
    I am still in the learning boat myself so I might get corrected with the response I give to you.

    But under interface I am not seeing that you are declaring your instance variables?

    under my @interface I would first have to declare them like this

    Code:
    NSDictionary *myDictionary;
    With the @property and @synthesize you are creating your setters and getters to these instance variables but you don't have any instance variables to set or get anything from. That might explain why nothing is being stored in your NSDictionary since none seems to exists.

    One thing I am very sure about is that it looks like you are OVER retaining your Arrays since I see the same [wordList retain]; twice in 2 different methods.

    From your code it looks like you are trying to do some more advanced stuff without really understanding the basic concepts of objective-c. But again I am also learning so take my advice with a grain of salt.
     
  3. Sarashinai thread starter macrumors newbie

    Joined:
    Oct 31, 2011
    #3
    It was my understanding that using the @property/@synthesize constructions automatically handled the creation of variables.

    If you're referring to the calls to [wordList retain] in viewDidLoad: and setSource: you'll notice that I only retain when I've created a new WordList. In viewDidLoad: I check to see if wordList has been created yet, if so, the retain call is never reached.

    The problem, I think, considering the contents of the debugging log, is the change of instance between the second-to-last and last calls. You can see that the first call:
    2011-10-17 10:58:22.396 ASL Dictionary[381:207] <WordList: 0x614f0b0> - WorldList:setNavigationController(<UINavigationController: 0x573e780>)

    is on a different instance from the second call:
    2011-10-17 10:58:22.402 ASL Dictionary[381:207] <WordList: 0x57806f0> - numberOfSectionInTableView(0): (null)
     
  4. larswik macrumors 68000

    Joined:
    Sep 8, 2006
    #4
    Code:
    @property/@synthesize constructions automatically handled the creation of variables. 
    That might be and I could be wrong. But if you are new to programming then I would try to follow the standard protocol that I was learning and declare your instance variables. I have never used a retain but I always alloc / init my arrays and instance variables I want to keep around.

    Yes I see that retain inside your if statement, I'm still learning and I just saw 2 retains without really looking at the code. My bad.

    Looking a little closer now it looks like you are / were trying to creating your instance variables but they are located in the implementation section and you commented them out //.

    This is a good little site that explains it http://blog.ablepear.com/2010/04/objective-c-tuesdays-instance-variables.html. Towards the bottom he is using the @properties and he has still declared his instance variables.

    It may be that you don't need to but I do know that in the last 5 months I have been working in object c I have never seen anyone not declare their instance variables and tried to do it with the @property /@synthesize. To the nest of my knowledge property and synth just make it easier to get access to set and get data from your instance variables. Otherwise you need to write setters and getters.

    I hope I am not to far off in my help.

    Good luck... Also just wondering are you coming from a different language or are you starting out?
     

Share This Page