How to pass data to parent view IOS - ios

I know this question is asked once every two days. I can not see what I am doing wrong though.
I have a storyboard navigation controller based app.
My notification and pop / push segues works well, only thing is I can not add string to parents view NSmutablearray.
I want to add a string object to parent view's nsmutablearray. My decent code does not pass any data.
parent.h
#interface CreaatePlistTableViewController : UITableViewController<UITableViewDelegate, UITableViewDataSource>{
NSMutableArray *presenterList;
}
#property (nonatomic, strong) NSMutableArray *presenterList;
parent.m
NSString * const NOTIF_CreatePlist_UpdateTableview= #"CreatePlist/UpdateTableview";
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Private interface definitions for update tableview
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#interface CreaatePlistTableViewController (private)
- (void)CreatePlistUpdateTableview:(NSNotification *)notif;
#end
#implementation CreaatePlistTableViewController
#synthesize presenterList=_presenterList;
- (void)viewDidLoad
{
[super viewDidLoad];
_presenterList=[[NSMutableArray alloc] init];
// Register observer to be called when logging out
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(CreatePlistUpdateTableview:)
name:NOTIF_CreatePlist_UpdateTableview object:nil];
NSLog(#"Presenter List: %#", _presenterList);
}
- (void)CreatePlistUpdateTableview:(NSNotification *)notif{
NSLog(#"Notification recieved");
NSLog(#"Presenter List: %#", _presenterList);
[_createPlistTableview reloadData];
}
child.h
#interface AddPresenterViewController : UITableViewController<UITextFieldDelegate,UIAlertViewDelegate>{
CreaatePlistTableViewController *crereaatePlistTableViewController;
}
#property(nonatomic,strong) CreaatePlistTableViewController *crereaatePlistTableViewController;
child.m
#synthesize crereaatePlistTableViewController=_crereaatePlistTableViewController;
//finished adding presenter
-(IBAction)finishedAddingPresenter:(id)sender{
//some xml string here
NSLog(#"final result XML:\n%#", writer.XMLString);
_crereaatePlistTableViewController=[[CreaatePlistTableViewController alloc]init];
//add object to parents view data source
[_crereaatePlistTableViewController.presenterList addObject:writer.XMLString];
//dismiss the view
[self.navigationController popViewControllerAnimated:YES];
//notify the parent view to update its tableview
[[NSNotificationCenter defaultCenter] postNotificationName:#"CreatePlist/UpdateTableview" object:nil];
}
Output
Notification recieved
Presenter List: (
)
So notification works when I click the button. But it does not pass object to nsmutablearray.
What I am doing wrong here ? How can I add an object to parent view's nsmutablearray?

It seems everything is good except your alloc of parent view object I am not that familiar with storyboard but You said you are using navigation navigation controller
so change this
_crereaatePlistTableViewController=[[CreaatePlistTableViewController alloc]init];
to
_crereaatePlistTableViewController= [self.navigationController.viewControllers objectAtIndex:0];
It may work I am not sure

You wrote this.
[_crereaatePlistTableViewController.presenterList addObject:writer.XMLString];
Do you ever initialize the array? No. Use the debugger and you will see that at this line the presenterList is nil.
Now as a point of style. Avoid using NSNotificationCenter to pass data or signaling other objects. #TheRonin gave a handy link. You should also look into some tutorials on Segues, because these are solved problems.
This is another related post that you might find interesting.

Related

NSObject does not give data UIViewController

Description of the problem is shown below:
Function contained in the UIViewController link functions contained in the NSObject
NSObject return value to another function contained in UIViewController
When a function referenced to UIViewController it does not update UILabel
UILabel found in UIViewController
NSObject class:
-(void)getCategoryId:(NSString *)categoryid {
categoryMap *catMap = [[categoryMap alloc] init];
[catMap getCategoryId:categoryid];
catMap.nePOI = categoryid;
}
UIViewController:
-(void)getCategoryId:(NSString *)categoryid {
self.label.text = categoryid;
}
You are creating an new categoryMap View controler object and you are updating its label, not the one from the categoryMap view controller that is being currently displayed.
To achieve what you want, the "NSObject" instance would have to have a refen-rence (property) pointing to the ViewController that is actually displayed on screen.
-(void)getCategoryId:(NSString *)categoryid {
// View controller is created
categoryMap *catMap = [[categoryMap alloc] init];
// label updated
[catMap getCategoryId:categoryid];
catMap.nePOI = categoryid;
// End of the method, View controller is destroyed
// See the problem here??? You are not updated the good viewController...
}
Although this is not a recommended way to go. Your viewController should ask the object what to display, not the other way around. But, in your case, you can fix this with a notification. Replace the implementation of getCategoryId: in the object class by
[[NSNotificationCenter defaultCenter] postNotificationWithName:#"categorySelected" object:categoryId];
and subscribe to it in your view controler viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(getCategoryId:) name:#"categorySelected" object:nil];
and then replace the getCategoryId: method of your view controller by:
-(void)getCategoryId:(NSNotification *)notif {
self.label.text = (NSString *)(notif.object);
}
That should do... ;)
To better understand architecture behind the ViewController principles, please refer to Apple MVC documentation: https://developer.apple.com/library/mac/documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html

_tableView reloadData not working when i called method from another class

This table view is working fine when tableview is firstly loaded
but when I tried to reload data using [_tableView reloadData], suddenly list won't reload at all.
Here's code:
-(void)loadListLoop{
AppDelegate* delegate = [[UIApplication sharedApplication] delegate];
shuffleLbl.hidden=false;
[self.view bringSubviewToFront:shuffleLbl];
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
NSString*playlistID=delegate.gPlaylistID;
NSString*token=[ud stringForKey:#"youtube_token"];
NSString *origin = [NSString stringWithFormat: #"https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=%#&key=AIzaSyBeFK_llQHRl7TyXoQxGkLDmIfKGzOPezM&access_token=%#",playlistID,token];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:origin]];
NSData *json = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSArray *array = [NSJSONSerialization JSONObjectWithData:json options:NSJSONReadingAllowFragments error:nil];
_titleList=[array valueForKeyPath:#"items.snippet.title"];
_thumbnailList=[array valueForKeyPath:#"items.snippet.thumbnails.default.url"];
_idList=[array valueForKeyPath:#"items.snippet.resourceId.videoId"];
NSLog(#"%#",_titleList);
[[NSRunLoop currentRunLoop]runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
dispatch_sync(dispatch_get_main_queue(), ^{
[_tableView reloadData];
});
}
The method loadListLoop is called from another class using:
PlaylistDetailViewController *playlistDetail = [[PlaylistDetailViewController alloc] init];
[playlistDetail loadList];
Looks like loadListLoop is successfully called and everything before [_tableView reloadData]; is also successfully loaded.
I put NSLog inside - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
to see is app is at least trying to reload data but it seems its not working at all.
EDIT:
first,view controller that contains "-(void)loadListLoop" is container view.so target view controller should be on screen
EDIT2:
i defined outlet at .h file below
#import <UIKit/UIKit.h>
#interface PlaylistDetailViewController : UIViewController<UITableViewDelegate, UITableViewDataSource>{
//IBOutlet UITableView *tableView;
IBOutlet UIButton *shuffleLbl;
}
-(void)exitLoopVoid;
-(void)loadListLoop;
#property (nonatomic,strong) IBOutlet UITableView *tableView;
#property (nonatomic,retain) NSMutableArray *titleList;
#property (nonatomic,retain) NSMutableArray *authorList;
#property (nonatomic,retain) NSMutableArray *thumbnailList;
#property (nonatomic,retain) NSMutableArray *idList;
-(IBAction)shuffle;
#end
IMPORTANT
EDIT3:
looks like some thing very weird is happening to NSMutableArray.
overwrite NSMutableArray at loadListLoop method(works fine and checked content with NSLog)
reload table(seems this is working fine too)
content inside NSMutableArray will rollback to old content
anyone has idea about this issue?
EDIT4:
1.overwrite NSMutableArray at loadListLoop method(success)
2.reload table and NSMutableArray will be null only at this method
3.rollback to data that i overwrites data at loadListLoop
I see a couple of problems.
First, the code you posted is a method loadListLoop. But the code that you posted is calling a different method loadList. The two are not connected.
Second, you say:
the method "loadListLoop" is called from another class using
PlaylistDetailViewController *playlistDetail =
[[PlaylistDetailViewController alloc] init];
[playlistDetail loadList];
That code is very wrong. It is creating a brand new instance of PlaylistDetailViewController that is not on-screen, and invoking the loadList method on that newly created view controller.
The view controller hasn't had a chance to display itself yet, so it's view properties will be nil. Plus, the view controller probably doesn't have any data in the model structure it uses to populate it's table view, so it won't have anything to display.
Further, if your view controller's view structure is defined in a storyboard, you can't use alloc/init to create new view controller instances.
At the point where you're trying to call loadList/loadListLoop, is the target view controller on screen? You need to explain your calling sequence.
use NSNotificationCenter for Update the table from one class to another class
1.do this in from where you have to call.
[[NSNotificationCenter defaultCenter] postNotificationName: #"UpdateTable" object:nil userInfo:userInfo];
2.And use this one for table view class. Write this in ViewDidLoad method.
[[NSNotificationCenter defaultCenter]addObserver:self
selector:#selector(refresh_method)
name:#"UpdateTable"
object:nil];
3.
-(void)refresh_method
{
//reload table here.
}

Refreshing background view from modal view

I want to update the view controller that is covered with a modal view in my application, I'm using swift. What I have currently is this:
The view on the right is the caller, and the views on the left are the modal views triggered by each button from the first one. They do basic edit, add new operations. These views are modally presented over the main one, and what I want to do is update the table view controllers enbedded in the two containers once I save the data from one of the modals.
I researched the use of one of the viewLoad events, but I'm kinda stuck at the moment. How can I do this?
Well you can do it in two ways
1. Delegate
2. NSNotificationCenter
In your Model class.h file
#protocol someProtoColName<NSObject>
-(void)finishedDoingMyStuff;
#end
#interface ModelClass()
#property (nonatomic,weak) id<someProtoColName> delegateObj;
Then in your ModelClass.m
-(void)someactionHappend{
//this is the method where you save your things call the delegate method inside here like this.
[self.delegateObj finishedDoingMyStuff];
}
Then in your CallerClass.h
#import ModelClass.h
#interface CallerClass:UIViewController<someProtoColName>
Inside CallerClass.m viewDidLoad
-(void)viewDidLoad{
ModelClass *model = [[ModelClass alloc]init];
model.delegateObj = self;
}
//Now declare the delegate method
-(void)finishedDoingMyStuff{
//update your code that this has happend. this will be called when your model class's button action inside which you sent the `self.delegateObj`message is invoked instantaneously.
}
NSNotificationCenter
CallerClass.m
-(void)viewDidLoad{
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(someMethod) name:#"NOTIFICATIONNAME" object:nil];
}
-(void)dealloc{
[[NSNotificationCenter defaultCenter]removeObserver:self name:#"NOTIFICATIONNAME" object:nil];
}
-(void)someMethod{
//something has happened, do your stuff
}
And in each of the Model class (if they are many or one dsnt matter)|
ModelClass.m
-(void)someactionHappend{
//this is your action method that you want to do stuff in the model
[[NSNotificationCenter defaultCenter] postNotificationName:#"NOTIFICATIONNAME" object:nil userInfo:nil];
}
Hope this helps you out.

iOS singleton viewDidLoad empty and on viewDidAppear not

I created a singleton in ios7 like this:
SharedData.h
#interface SharedData : NSObject
{
}
+ (id)sharedInstance;
#property (strong, nonatomic) NSMutableArray *list;
#end
SharedData.m
#import "SharedData.h"
#implementation SharedData
#synthesize list;
// Get the shared instance thread safe
+ (SharedData *)sharedInstance {
static dispatch_once_t once = 0;
static SharedData *sharedInstance = nil;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (id)init {
self = [super init];
if (self) {
//initialize
list = [[NSMutableArray alloc] init];
}
return self;
}
#end
I always use this code to access this class:
SharedData *sharedData = [SharedData sharedInstance];
The problem is now when I switch the view in my viewDidLoad method the list is empty but in my viewDidAppear method everything is fine. Any ideas?
EDIT:
This is the code how I change the views:
SharedData *sharedData = [SharedData sharedInstance];
//clear feed and add new feed
[sharedData.list removeAllObjects];
[sharedData.list addObjectsFromArray:newList];
//show new gui
[self.navigationController performSegueWithIdentifier:#"goToMain" sender:self];
NOTE: I push from a normal ViewController to a TabBarController -> NavigationController -> TableViewController to display the list.
I guess you have the confusion between these two viewcontroller methods:
-(void)viewDidLoad{
//
}
&
-(void) viewDidAppear{
//
}
viewDidAppear is the method which is called each time your view changes but viewDidLoad is the method which is not necessarily called each time your view changes.
ViewDidLoad method is called when view loads for the first time, after that it doesn't get called until the views are removed/released.
P.S: I suggest you to put the breakpoint in your viewDidLoad and viewDidAppear method and feel it. Your answer lies there.
Hope this helps you alot.
Good Luck.
The problem was i created a segue which went from the button to the next view. Because of this the viewDidLoad gets earlier called than the list assigned. I just changed the segue to go from view to view.
How are you changing from one viewController to the other? Wich classes are the parents of your destination ViewController?,
If you are modifying properties of the view in the prepareForSegue method... you are forcing the view to load.
For example, you are setting the list of your singleton in prepareForSegue, but before setting the list you are modifying a property of your destination viewController. (doing something like destVC.view = XXX or destVC.viewControllers = XX if you are subclassing a UITabBarViewController...) Then you are triggering the viewDidLoad method , and it's executing before you have set the list to the correct value.
Or maybe you are seguing in two different places to the destinationViewController. And when the viewDidLoad happens, you still have not updated the list on the singleton.
Here is the transcription of the chat with the poster of the question: https://chat.stackoverflow.com/transcript/55218

NSNotification sends value that get reset in viewDidLoad

I have this problem:
2 views called A and B, both are TableViewController.
A listen for notification, B sends notification
I'm not going to explain in detail, but for sake of simplicity it's like this:
A can display multiple types of data, B has a list of these types, selecting one row from B makes A load in it's tableView the right list of data.
While i'm in B i'm sending a notification like this
NSNumber *section = [NSNumber numberWithInt:indexPath.row];
NSDictionary *infoDictionary = [NSDictionary dictionaryWithObject:section
forKey:#"CurrentTableView"]
NSString *UpdateTableView = #"UpdateTableView";
[[NSNotificationCenter defaultCenter] postNotificationName:UpdateTableView
object:self
userInfo:infoDictionary];
Now in A i'm listening like this
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(updateTableView:)
name:#"UpdateTableView"
object:nil];
which calls the method
#property (strong, nonatomic) NSNumber *section;
// :::: Some code here ::::
- (void)updateTableView:(NSNotification*)note
{
_section = [[note userInfo] valueForKey:#"CurrentTableView"];
NSLog(#"%d",[_section intValue]);
[self.tableView reloadData];
}
and the NSLog works fine, i mean it prints the right value.
I'm using _section to discriminate in the TableView delegate methods what kind of data to load.
The problem is that the call to this method (after the notification is received) happens BEFORE the view is actually reloaded (viewDidAppear and so) which set my #property _section to 0, in this way every time my TableView loads the data standing behind the [_section intValue] == 0.
How could i solve this? I need something that don't gets reset every time the view loads itself. Any suggestion?
EDIT: navigation controller to move from B to A
MenuNavigationController *navigationController = [self.storyboard instantiateViewControllerWithIdentifier:#"contentController"];
AViewController *homeViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"homeController"];
navigationController.viewControllers = #[homeViewController];
Do you really need NSNotification ? Notifications are used where you want to update a view, and by update i mean that the view is already created.
What i would do is fairly simple, in B i would set your NSNumber *section as an ivar (if you display controller A some place different from where you post you notification). When you posted your notification you would just instantiate your ivar.
Then A would have a similar variable and when you want to display A :
AViewController *homeViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"homeController"];
homeViewController.section = section;
navigationController.viewControllers = #[homeViewController];
Perhaps your property section isn't synthesizing to use your instance variable _section. Does your synthesize line look like this:
#synthesize section=_section;
Otherwise the compiler will implicitly create an instance variable name section
UPDATE
As #Justafinger mentioned, as of Xcode 4.4, the ivar will be named _section if you completely leave out the #synthesize line. If you do explicitly synthesize, however, and don't assign the ivar name in the #synthesize line the ivar name will default to section.

Resources