TableView in a UIViewController

Discussion in 'iOS Programming' started by larswik, Jan 13, 2012.

  1. macrumors 68000

    Joined:
    Sep 8, 2006
    #1
    I have a UITableView in my UIViewController and implemented the delegates in my header file.

    Code:
    @interface JobViewController : UIViewController <UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource>{
    Since the UIViewController does not come with the methods I copied over the these delegate methods in my @implimentation
    Code:
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    
    
    I was ready to test the whole thing out and added my last line of code to refresh the tableview
    Code:
    [self.tableView reloadData];
    and it gave me an error
    Even though I added the delegates and created the delegate methods. Is it giving me this error because my custom view is of type UIViewController and not UITableView? I have see tableviews in other viewControllers so I must be missing part of this puzzle to make it work?
     

    Attached Files:

  2. macrumors 6502

    dantastic

    Joined:
    Jan 21, 2011
    #2
    A UITableViewController comes with the property 'tableView' linked up already for free. As you are using a UIViewController you must create your own 'tableView' IBOutlet property and link that in IB as well. After that it should all work.
     
  3. thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #3
    For this whole project I decided not to use IB and code everything from buttons to TablesViews. This is the code for my tableView which is pretty straight forward and set the delegates. How would I proceed with this IB link, or work around since the TableView is created progamtically?

    It seems as simple as just making a method call to the cellForRowAtIndex [self tableView]; which I believe [self.tableView reloadData]; is kind of doing, but not working.

    Code:
        CGRect tableViewFrame = CGRectMake(5, 200, 310, 170);
        incomeAndExpenseTableView = [[UITableView alloc] initWithFrame:tableViewFrame style:UITableViewStylePlain];
        incomeAndExpenseTableView.layer.cornerRadius = 5;
        incomeAndExpenseTableView.clipsToBounds = YES;
        incomeAndExpenseTableView.dataSource = self;
        incomeAndExpenseTableView.delegate = self;
        incomeAndExpenseTableView.rowHeight = 30.0;
        [self.view addSubview:incomeAndExpenseTableView];
    
     
  4. ChOas, Jan 14, 2012
    Last edited: Jan 14, 2012

    macrumors regular

    Joined:
    Nov 24, 2006
    Location:
    The Netherlands
    #4
    The problem is that your UIViewController does not have a UITableView property
    called tableView.

    Add a UITableView property called eeeeh 'something' to your UIViewController. Assign your incomeAndExpenseTableView to that property before you add it as a subview.

    Then you will be able to call [self.something reloadData]
     
  5. macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #5
    Call your table view tableView. Don't call it anything else. Create a property with that name. Create the table view however you like, code, IB, etc. Assign the value of the table view to your property. Then things will work.

    Since UITableView uses a property with the name tableView and there is lots of sample code that uses that name I recommend that you also use that name for your table view property.
     
  6. thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #6
    I see what is happening but I am getting trumped up in the terminology I think. In the header I changed it to UITableView *tableView;

    I am getting lost as to how to assign a UITableView property to my UIViewController. Then I need to assign the 'value' of my tableView to the property. Those values would not be the dataSourse or delegate properties of the tableView.

    Just by changing the name of the UITableView to tableView I get a warning for the method cellForRowAtUndexPath saying "Local declaration of 'tableView' hides instance variable".

    Sorry for the consistent question and it seems this is like 2 lines of code to solve this problem. I am sure after I get it I will bang my head against the table seeing how easy it was to fix.

    Thanks.
     
  7. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #7
    Where do you instantiate your UITableView? That would be a good place to also assign your property.

    Also, how is your tableView property defined?
     
  8. thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #8
    I declared it in the header file but I instantiated it in the Method. I then added it as a subview to the view.

    I am reading the tableView doc's right now. I don't know what you mean by "Also, how is your tableView property defined? ". It's a tableView that is added as a subview. It's delegate and dataSource are set to self.

    I am sure I know the answer to this, and that I have done it but learning from home i'm getting stuck on the wording.
     
  9. macrumors 6502

    dantastic

    Joined:
    Jan 21, 2011
    #9
    Code:
    // ...h
    
    @property (nonatomic, retain) UITableView *tableView;
    
    
    // ...m
    
    @synthesize tableView = _tableView;
    
    // ...
    // in viewDidLoad
    
    UITableView *tv = [[UITableView alloc] initWithFrame:myFrame];
    //...
    self.tableView = tv;
    [tv release];
    
    
    After this you'll be able to call self.tableView.
     
  10. thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #10
    It didn't work. This is so frustrating. I am working on other parts of my app right now till I can figure it out. Following your advice here is my .h now and everything that leads to the cellForRowAtIndex which fails to get called.
    Code:
    #import <UIKit/UIKit.h>
    #import <QuartzCore/QuartzCore.h>
    #import "PDFCreator.h"
    
    @interface JobViewController : UIViewController <UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource>{
        
        int rowSelection, clientSelection, entryAmount;
        BOOL writeIfChanges;
        
        UIBarButtonItem  *addNewRowButton;
        UITextField *jobTextField;
        UITextField *invoiceTextField;
        [COLOR="Red"]UITableView *tableView;[/COLOR]
        UILabel *startDateLabel;
        UILabel *total;
        UILabel *expense;
        
        NSMutableDictionary *clientJob;
        NSMutableArray *clientJobsStorageArray;
        NSMutableArray *clientContentArray;
        NSMutableDictionary *client;
        
        NSMutableArray *tableViewArray;
        
        UITextField *amountTextField;
        UITextField *workTypeTextField;
        UIView *enteryView;
        NSString *entryString;
    }
    
    @property (retain) NSString *entryString;
    [COLOR="Red"]@property (nonatomic, retain) UITableView *tableView;[/COLOR]
    
    -(void)pageSetUp;
    - (void)writePlist;
    - (void)readPlist;
    -(void)newTableEntry;
    -(void)newInvoice;
    
    @end
    
    Now my .m
    Code:
    #import "JobViewController.h"
    
    @implementation JobViewController
    @synthesize entryString;
    [COLOR="Red"]@synthesize tableView = _tableView;[/COLOR]
    
    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
            // Custom initialization
        }
        return self;
    }
    
    - (void)didReceiveMemoryWarning
    {
        // Releases the view if it doesn't have a superview.
        [super didReceiveMemoryWarning];
        
        // Release any cached data, images, etc that aren't in use.
    }
    
    #pragma mark - View lifecycle
    
    - (void)viewDidLoad
    {
       [COLOR="Red"] CGRect tableViewFrame = CGRectMake(5, 200, 310, 170);
        UITableView *tv = [[UITableView alloc] initWithFrame:tableViewFrame];
        self.tableView = tv;
        
        tv.layer.cornerRadius = 5;
        tv.clipsToBounds = YES;
        tv.dataSource = self;
        tv.delegate = self;
        tv.rowHeight = 30.0;
        [self.view addSubview:tv];[/COLOR]
        
        writeIfChanges = NO;
        addNewRowButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(newTableEntry)];
        self.navigationItem.rightBarButtonItem = addNewRowButton;
        [self pageSetUp];
        [self readPlist];
        [super viewDidLoad];
        // Do any additional setup after loading the view from its nib.
    }
    
    In another method I create a UIButton and the action fires the closeEntry method

    Code:
    UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [doneButton addTarget:self action:@selector[COLOR="Red"](closeEntry)[/COLOR]forControlEvents:UIControlEventTouchDown];
        doneButton.frame = CGRectMake(10.0, 140.0, 90.0, 30.0);
        [doneButton setTitle:@"Done" forState:UIControlStateNormal];
        [enteryView addSubview:doneButton];    
        [self.view addSubview:enteryView];
    
    The last part and when I look at the console I can see the NSLog but it ends there
    Code:
    -(void)closeEntry{
       [COLOR="Red"] NSLog(@"Close Entery Method was exicuted");[/COLOR]
        entryAmount = [amountTextField.text intValue];
        entryString = workTypeTextField.text;
        
        NSDictionary *tempDict = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithInt:entryAmount],@"entryAmount",entryString,@"entryDiscription", nil];
        [tableViewArray addObject:tempDict];
       [COLOR="Red"] [self.tableView reloadData];[/COLOR]
        [enteryView removeFromSuperview];
    }
    
     
  11. thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #11
    HANG ON..... I made 1 MAJOR mistake that for some reason seemed to be causing this problem.

    I failed to instantiate the NSMutableArray that was collecting the data for the tableView. I accidentally deleted it when removing some code. Now that it is instantiated the cellForRowAtIndex delegate method is begin called.

    It crashed in that method but that is a good sign and I can fix that.
     
  12. thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #12
    IT WORKS!!!!

    It can't believe such a small thing can cause a chain reaction like that. But now I can see what has happened and why it failed. Because I, by mistake, deleted my instantiation of my tableViewArray it had a trickle down effect. Now my numberOfRows returned nothing because because my array was nil

    Code:
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        //#warning Incomplete method implementation.
        // Return the number of rows in the section.
        return tableViewArray.count;
    }
    
    This explains why my cellForRowAtIndex never was executed. I did use NSLogs to check my Array before and I had instantiated it and it worked. But in while getting the tableView to work I deleted it and never rechecked it until now and saw it was nil. Once I repaired it everything worked perfectly!

    What a nightmare to resolve such a small thing.
     
  13. macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #13
    The essence of debugging is validating your assumptions. You have in your head a concept of how things should work. If there's a bug that means there is some disconnect between what you want it to do and what it is doing. For something like a tableview it has to exist and be visible and be added to a superview, it has to get its information from its delegate and dataSource. The information provided by the delegate and dataSource has to be valid, and so on. If things don't appear the way you think they should appear then you should start at the beginning of all these things that are required and check them one by one until you find the problem.

    Sometimes you need to use a divide and conquer to find out where the problem is and of course sometimes your conception of how things work is wrong. But a rational debugging process will point you to the line of code that is wrong even though you think it's right.
     
  14. thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #14
    Which is kind of what I did at the end. I began again debugging and then discovered the the nil array value. Once I fixed it everything worked.

    My biggest challenge this time was dealing with the tableView in an UIViewController which I have not done before. So I thought the problem had to be coming from that. When dantastic posted the code and it did not work I went back and followed the code and started debugging. Most of the time I like the way this forum works by not giving away the answer. But if I spend so much time and can't figure out the answer it is good to get the answer and analyze why it works.

    Now I can put this behind me and move forward on my app. If I have this issue again I will be able to solve it.

    Thanks guys!
     
  15. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #15
    I know you've moved beyond this but I just wanted to re-address a couple of things from your previous post:

    I really hope you just accidentally forgot to put the name of the method in there. Please tell me that's what happened?

    Well, knowing what you know now, do you understand the question? And do you understand what purpose properties serve? What are their advantages and disadvantages?
     
  16. thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #16
    dejo- I understand @Properties and @Synthesize as it pertains to artificially creating my setters and getters for my instance variables. I was getting lost and thinking I had to write some kind of an attribute for tableView, ie tableView.something.

    I was really hoping to take the iPhone class at City College this upcoming semester but was unable to. This would have helped fill in gaps in my knowledge. For the most part I get it, but I get lost in using the right words to explain things when I get into trouble. Also when I get the answers sometimes I might not know what they mean, even though I might already be coding it, I just don't know what it is called.

    In this case I use setters and getters all the time, @property and the other. But I did not think it was as simple as that when the question was asked about the property. I thought it meant something else that I did not understand yet.
     

Share This Page