0

I have set the delegate and datasource to the File's Owner, the outlet is set properly in the xib file. Now for the .h file:

@interface ProductsViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>{

    IBOutlet UITableView *objTableView;
}


@property(nonatomic,strong)IBOutlet UITableView *objTableView;

In the .m file:

NSLog(@"%@",self.objTableView);
[self.objTableView reloadData];

For the first time, self.objTableView is set properly: NSLog(@"%@",self.objTableView); gives:

<UITableView: 0x1d9a5800; frame = (4 54; 532 660); clipsToBounds = YES; autoresize = W+H; 

But for next time I got a (null) table view object and so the reloadData doesn't refresh the table view. How to fix that, thanx in advance.

EDIT:

I am using the Afnetworking method JSONRequestOperationWithRequest like the following:

AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON){

    [SVProgressHUD dismiss];
    //Get the response from the server
    //And then refresh the tableview

    [self.objTableView reloadData];//I shouldn't put this here, it should be in the main thread
}failure:^(NSURLRequest *request, NSHTTPURLResponse *response,NSError *error, id JSON){

            [SVProgressHUD dismiss];

            //Alert the error message

}];
[operation start];
[SVProgressHUD showWithStatus:@"Searching for products, please wait.."];

Actually, JSONRequestOperationWithRequestrun asynchronous and so not in the main thread, however it turned that the UI updates should be done in the main thread, so I need to remove [self.objTableView reloadData]; outside that method. But where? how to make sure to run it in the main thread after JSONRequestOperationWithRequest will finish?

Malloc
  • 15,434
  • 34
  • 105
  • 192
  • 2
    Given that you say that you have a line that says `@synthesize objTableView;`, the typical problem of duplicative ivar is not the problem. (You really should not explicitly declare your ivar, to avoid this potential confusion. Let the compiler do that for you.) Anyway, the problem must rest elsewhere. Going back to the original question, how are you initializing `objTableView`? You say it's an `IBOutlet` (but generally `IBOutlet` references are `weak`). Have you manually created the table view, or did you create in Interface Builder? If created in IB, have you checked that linkage? – Rob Mar 24 '13 at 03:43
  • @Rob, +1: I agree, the `IBOutlet` should be a `weak` reference and you should let the compiler handle creating the backing ivar (by `synthesizing` the property for you). Naming your `property` and its backing `ivar` the same is only going to cause confusion and problems for you... – JRG-Developer Mar 24 '13 at 03:51
  • I don't know though about the "duplicate ivar is not the problem" -- perhaps it's possible something goofy may be happening through IB or during runtime since there are two variables with the same name that are both listed as `IBOutlets`? Maybe try getting rid of said `objTableView` ivar and see if this changes anything? – JRG-Developer Mar 24 '13 at 03:53
  • What are you guys talking about? An IBOutlet should **always** be strong, otherwise you lose the object that the Xib file has initialized! – Matt Mar 24 '13 at 05:31
  • @Matt I disagree. "The pattern you should typically adopt is: outlets should be weak, except for those from File’s Owner to top-level objects in a nib file (or a storyboard scene) which should be strong," from the [Transitioning to ARC Release Notes](http://developer.apple.com/library/ios/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226-CH1-SW10). Also see http://developer.apple.com/library/ios/#documentation/General/Conceptual/CocoaEncyclopedia/Outlets/Outlets.html. If you let IB create the outlets, they're always weak, too. – Rob Mar 24 '13 at 05:48
  • @Rob Exactly. It says "**except** for those from File’s Owner to top-level objects in a nib file (or a storyboard scene) which should be **strong**", which is exactly the case when you're having an outlet of a UITableView, or any other UIKit element owned by the view controller. IBOutlets between objects that can each point to the other should be weak, otherwise you can easily create a retain cycle. – Matt Mar 24 '13 at 06:55
  • @Matt Again, I disagree. If he was using a `UITableViewController`, the top level object would be the `UITableView`, but then again, he wouldn't have an `IBOutlet` for that, as it's linked to the "file's owner", the table view controller's own `tableView`, not an `IBOutlet`. If this was a table view added to a standard `UIViewController`, the top level control is the main `UIView`, which again is connected to the file owner's `view` property, and the table view is a subview of the main view, and thus is not a top-level view. http://stackoverflow.com/questions/8170522 – Rob Mar 24 '13 at 11:55
  • Hi all, I edited my post for more details about the approach I am adopting. Basically my issue (as far as I understand) is that I tried to update `UI` in an asynchronous thread whereas it should be done in the main thread. Do yu have experience with Threading? how to make sure to run `reloadData` in the main thread? please feel free to suggest code directly in my snippet.Thanx in advance. – Malloc Mar 30 '13 at 00:35
  • @Rob Thanx Rob, so the issue couldn't be a threading related. I also tried to call another method to reload the table view instead of reloading it in the main success. Always doesn't refresh. That's really a headache issue. – Malloc Mar 30 '13 at 12:07
  • @Malloc I'm having a hard time understanding where the problem stands. You originally seemed to be focusing on the tableview variable getting `nil`ed. Are you saying that this problem is gone and that you now have a different problem, that it's not reloading at the appropriate time?!? – Rob Mar 30 '13 at 12:10
  • @Rob, actually it's the same problem but was thinking maybe it was around threading. Since you confirmed about AFNetworking main thread support, I will try to upload a sample example so that you may have a look at the code and help me with this 5 days issue, if you don't mind. Thanx in advance for your time. – Malloc Mar 30 '13 at 12:16

3 Answers3

2

Are you sure you're looking at self.objTableView (the property's accessor method) and not objTableView (the instance variable you manually defined)? Do you have a @synthesize line? If you omitted your @synthesize line, it would have effectively done @synthesize objTableView = _objTableView; for you, defining an instance variable called _objTableView for your property called objTableView, and thus your manually defined instance variable, objTableView would never have been initialized.

It is recommended that you remove the manually defined instance variable and let the compiler synthesize that for you, and just define the property, thus:

@interface ProductsViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>

// Following lines removed. Do not define the instance variable.
// Let the compiler synthesize it for you.
//
// {
//     IBOutlet UITableView *objTableView;
// }

@property(nonatomic,strong)IBOutlet UITableView *objTableView;

@end

The compiler will generate the instance variable for you, and unless to manually write your own @synthesize line, the compiler will name the instance variable _objTableView. If you ever need to reference the instance variable for your objTableView property (generally only needed in initializer and dealloc methods), remember to include the leading underscore. (The convention of the underscore is to minimize chances that you accidentally refer to the instance variable when you actually intended to use the self.objTableView accessor getter method.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Hi, Thanx for your quick reply, actually I already senthesized the property `@synthesize objTableView;` and BTW, I tested to remove th einstance declaration as you mention above, but the table view then gt werid behaviour (cell gets disappeared when click on it). And the table view always `null`. – Malloc Mar 24 '13 at 03:37
  • If you're manually invoking `@synthesize objTableView;`, then the duplicative ivar is not the issue. Still, I'd encourage you to get rid of this ivar, as this is only a source of potential confusion and it does absolutely nothing good. If you synthesized properly, commenting out the explicitly declared ivar would not affect the operation at all. If, indeed, you synthesized it as your say, the problem rests elsewhere, but you haven't shared enough to let us diagnose what's going on. – Rob Mar 24 '13 at 05:02
  • Hi Rob, I edited my pots, please have a look. My issue is not resolved and I think I should update the `UI` in the main thread, do you have any experience about that? Thanx in advance. – Malloc Mar 30 '13 at 00:33
  • @Malloc Yes, I do a lot of multithreaded programming. And, yes, you absolutely must run all UI updates on main queue. The thing is, most well written classes (such as AFNetworking), ensure that, although they perform operations on a background queue, that the completion blocks are invoked in the main queue already, so you don't need to worry about it. If you look at the AFNetworking source, you'll see they do the requisite `dispatch_async(dispatch_get_main_queue(),{...});` which sends the code represented by the ellipses to the main queue. – Rob Mar 30 '13 at 12:05
  • @Malloc So, not only is this not the problem, but this wouldn't explain why your tableview property is getting set to `nil`. If you want to compress your project and upload it somewhere, I can take a quick look if you want. – Rob Mar 30 '13 at 12:07
2

Have you tried setting a Watchpoint on objTableView?

In your -viewDidLoad set a breakpoint. When the debugger stops, secondary-click on objTableView in the variable list. Click on "Watch 'objTableView'". It will break anytime the value of objTableView changes.

It should let you know exactly when the value changes.

Jeffery Thomas
  • 42,202
  • 8
  • 92
  • 117
0

I suggest you create the following method:

- (void)setObjTableView:(UITableView *)tableView {
    _objTableView = tableView;
}

Then set a breakpoint on the _objTableView = tableView line, which should let you know what causes _objTableView to become nil.

Matt
  • 2,391
  • 2
  • 17
  • 18