Why relaodData call the viewDidLoad - ios

I am maintaining an app developed by someone else and I got a strange behaviour when debugging it. when allocating a view controller object from another class, it will call viewDidLoad, in viewDidLoad, I make call to another method in which I fill in an array:
- (void)viewDidLoad
{
[super viewDidLoad];
[self fillArray];
}
-(void)fillArray{
arrayProduct = [[NSMutableArray alloc] init];
//fill in the array from server
[self.objTableView reloadData];//refresh the table view
}
The strange behaviour is, once [self.objTableView reloadData]; statement is executed, the viewDidLoad gets called again. Why is this happening? Thanx in advance.

You can solve this issue by using flag.
Declare on BOOL variable and make it true before call the reloadData method. and in viewDidLoad check if variable is true then don't init your array.

Related

My NSString object is not being updated until I leave my main viewController and go back?

I have been trying to figure this out for the last couple of hours and still cannot figure it out or find anything related that might help me out.
I have a method showFriendRequestData and this method makes a server call to get a JSON response. I take my data that I get back and store it into an NSMutableArray. I than make an NSString object and store the total amount of items in the array to a string value.
I then add the value to a UILabel object and try to display it. I have tried calling this method showFriendRequestData in my viewDidAppear method like this.
-(void)viewDidAppear:(BOOL)animated{
[self showFriendRequestData];
}
But ONLY when I leave the mainViewController and go BACK does the label update..... Make no sense. Am I calling this method I made in the wrong place?? Any help or guidance would be great. I want the label to update the moment I login into my main view controller.
You must invoke [super viewDidAppear:animated];
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self showFriendRequestData];
}
Setting your data too late?
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// ...
}
See guidelines-for-viewwillappear-viewdidappear-viewwilldisappear-viewdiddisappear for complete instructions.

Not going into method

I'm just learning iOS development but I have experience in C++ and I'm having an issue where my I call a method on an object but that object is not being called. Here is my code:
#implementation EXCoursesViewController{
EXNetworkingController *_networkController;
}
-(instancetype)initWithStyle: (UITableViewStyle)style{
self = [super initWithStyle: style];
if(self){
self.navigationItem.title = #"Title";
[_networkController createSession];
[self fetchFeed];
}
return self;
}
[_networkController createSession] doesn't seem to actually call the createSession method in the EXNetowrkingController I made. I'm not sure why this is happening. Any help would be greatly appreciated.
I'm not sure why this is happening.
Most likely, it's because _networkController is nil. It's apparently an instance variable, but you haven't given it a value at the point in -initWithStyle: where you're trying to send it a message.
To fix the problem, just create an EXNetworkingController instance and assign it to your ivar before using:
_networkController = [[EXNetworkingController alloc] init]; // or use the correct initializer
[_networkController createSession];
You are not doing the alloc and init for your EXNetworkingController. What i recommend is make your createSession method as public and call it. It can be called through the EXNetworkingController class name itself.
Do something like this:
+(void)createSession{
//Your createSession code goes here
}
You just have to replace the minus(-) which is in front of the -(void)createSession method with plus(+)
Then in your EXCoursesViewController class inside the initWithStyle replace [_networkController createSession]; with [EXCoursesViewController createSession];
And you no longer require to make an object of your EXCoursesViewController.
So you can remove EXNetworkingController *_networkController;
Hope this helps. Thanks.

Problems reloading data in a tableView

I am trying to reload data in a tableview based on a users account permissions whenever they log in.
The two classes involved in this are:
mainViewController and menuViewController
Currently I am able to use
[self.tableView reloadData];
To reload the data when called within the viewWillAppear method. Which is no good for me since the user hasn't logged in when the view loads so there is no data to populate the table at this point.
I have created a method called populateTable in menuViewController.h which I am calling in the mainViewController.m file on button press using the following;
(IBAction)Reload:(id)sender {
menuViewController *mvc = [[menuViewController alloc]init];
[mvc populateTable];
}
This seems to work correctly as I have an NSLog within the populateTable method which executes. However the reloadData does not work.
Here is my populateTable method;
-(void)populateTable {
self.section1 = [NSMutableArray arrayWithObjects:#"test settings", #"test", #"test",#"Users and access",#"No-track IPs", nil];
self.section2 = [NSMutableArray arrayWithObjects:#"Rules", #"Channels",#"Goals",#"Pages", nil];
self.menu = [NSMutableArray arrayWithObjects:self.section1, self.section2, nil];
[self.tableView reloadData];
NSLog(#"Reloading data");
}
Can you guys help me out here, I have been staring at this all day and getting nowhere, thanks!
From my experience this is likely a problem with timing - the IBOutlet of self.tableView is not ready when you call reloadData on it (add an NSLog and see for yourself - it is nil when called).
To solve this, the populateTable method must be called within the UIViewController's viewDidLoad method. This guarantees that the outlets are not nil and that everything is ready for your data population.
Also, you should not instantiate your MenuViewController with [[MenuViewController alloc] init] but using the storyboard's instantiateViewControllerWithIdentifier.
Your problem is this line,
menuViewController *mvc = [[menuViewController alloc]init];
This creates a new instance of menuViewController, not the one you see on screen. You need to get a reference to the one you have, not create a new one. How you get that reference depends on how, when, and where your controllers are created.

Bug dynamically subclassing a UIViewController

Summary
I am trying to dynamically subclass objects to do some cleanup before dealloc. I add a subclass to the object and add my own dealloc method that does the cleanup and then calls [super dealloc]. This works for most cases but I am running into something strange when it happens to UIViewControllers. It seems some cleanup is not happening in dealloc because I am getting a crash when -hash is being sent to a deallocated view controller.
This happens when creating a view for a new view controller and it is growing some hash set in a class method of UIViewController. It seems to be a hash of view controllers for views because it is in a method +[UIViewController setViewController:forView:].
If I do not do the add my own dealloc method to the dynamic subclass everything is fine. Even if I only call [super dealloc] in my own version of dealloc it crashes the same way.
Does anyone have any idea what could be going wrong? Do I need to do something else other than calling [super dealloc] so that it still executes everything it should?
The Code
The dealloc method looks like this:
- (void)deallocWithRemoveAllAssociatedBindings {
[[BindingManager sharedInstance] removeAllBindingsAssociatedWithObject:self];
[super dealloc];
}
My dynamic swizzling method looks like this:
+ (void)createSubclassForObject:(id)object {
Class objectClass = object_getClass(object);
NSString *objectClassString = NSStringFromClass(objectClass);
NSString *subclassName = [NSString stringWithFormat:#"RemoveAllAssociatedBindings_%#", objectClassString];
Class subclass = objc_getClass([subclassName UTF8String]);
if (!subclass) {
subclass = objc_allocateClassPair(objectClass, [subclassName UTF8String], 0);
if (subclass) {
Method dealloc = class_getInstanceMethod(self, #selector(deallocWithRemoveAllAssociatedBindings));
class_addMethod(subclass, #selector(dealloc), method_getImplementation(dealloc), method_getTypeEncoding(dealloc));
[self addRemoveMethodToClass:subclass];
objc_registerClassPair(subclass);
}
}
if (!!subclass) {
object_setClass(object, subclass);
}
}
You can see the full code on github: https://github.com/drewag/property-bindings
you are never supposed to call dealloc on your own, thats apple's job. my suggestion would be to override the standard dealloc method and add what ever checks you need with an if statement to do your "custom dealloc" stuff. or you could just call your custom dealloc from inside dealloc just like how [super dealloc] is called... or just use ARC.

UIView factory and delegate

I want to draw a chart in an UIView. The question is how do I get the data (Points) to the view. If I create a protocol and set the UIViewController as the delegate where in the UIView do I call the delegate methods (initWithFrame? might be to early, and the delegate might not be set, awakeFromNib? but the view is 100% created in code, it has no nib file) ..
initWithFrame? might be to early, and the delegate might not be set.
In fact, the delegate cannot be set by the time you're in initWithFrame:, since the first thing you do with an object after allocation is initialization, i. e. until the init method returns, you can't call (well, it's idiomatic not to do so, at least) any other methods.
What you have to do is have a loadData or reloadData method, that the delegate must call explicitly after having set itself as the delegate of your view. I. e., from the view controller, you can call it like this:
#implementation ChartViewController
- (id)init
{
if ((self = [super init])) {
chartView = [[ChartView alloc] initWithFrame:self.view.frame];
chartView.delegate = self;
[self.view addSubview:chartView];
[chartView reloadData];
}
return self;
}
Then, in your chart drawing view, implement - reloadData as follows:
- (void)reloadData
{
// Call the delegate here,
// then do the drawing
}
A better way is to use UIViewController instead of a UIView. Because your that view has to manage data. Managing data is a UIViewController's job.
make a protocol but dont call it delegate. call it dataSource :D
anyways, call it when you first need the data .... as late as possible.. NOT in init.. maybe in the setDataSource call.
or when you draw for the first time and see you have no data..
look at UITableView to see how he does it and imitate that

Resources