I'm using this code to display the image but I would love to link that image back to the rootView. Any suggestions?
UIImage *image = [UIImage imageNamed: #"Invest.png"];
UIImageView *imageView = [[UIImageView alloc] initWithImage: image];
Thanks!
As I mentioned in my comment above, you can use an NSNotification to post it back to your rootView controller:
YourViewController.m: (The view controller where your image resides)
Call: [self yourMethod]; to post the image back to the rootView
- (void)yourMethod
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"postImage" object:self.yourImage userInfo:nil];
}
RootViewController.m:
Here we need to add an observer that way we can later receive the image you want to post later from other parts of your app.
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(postedImage:) name:#"postImage" object:nil];
}
Here we grab the notification's object as the postedImage:
- (void)postedImage:(NSNotification *)notification
{
UIImage *postedImage = notification.object;
}
Don't forget dealloc method to remove the observer!
- (void)dealloc
{
[[NSNotificationCenter defaultCenter]removeObserver:self];
}
You can use NSNotification to "move" the data to a different ViewController.
Post the notification inside your current ViewController
NSDictionary *dictionary = [NSDictionary dictionaryWithObject:image forKey:#"image"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"imageNotification" object:nil userInfo:dictionary];
Add an observer in the viewDidLoad method of the other ViewController
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedImage:) name:#"imageNotification" object:nil];
Add a method that will get called when the notification got posted (inside the other ViewController)
- (void)receivedImage:(NSNotification *)notification {
UIImage *image = [[notification userInfo] objectForKey:#"image"];
}
Related
I am facing an issue with NSNotificationCenter.
I am not able to send message and receive message using NSNotificationCenter in latest ios 8.4 (XCode 6.4)
Please check the following code:
1) I want to send data using first view controller to another view.
so i have written the following code in first viewcontroller:
When user btn clicked method as following :
- (IBAction)btnClicked:(id)sender
{
[self postNotification];
[self performSegueWithIdentifier:#"asGo" sender:self];
}
-(void)postNotification{
[[NSNotificationCenter defaultCenter] postNotificationName:#"MyNotification" object:self];
}
2) In Second view controller i have added observer in ViewWillApper as following :
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(eventListenerDidReceiveNotification:)
name:#"MyNotification"
object:nil];
}
-(void)eventListenerDidReceiveNotification:(NSNotification*)txt
{
NSLog(#"i got notfication:");
}
so eventListenerDidReceiveNotification is not called while come on view.
But i am not getting above log while i come on second vc with navigation
As others have noted, NSNotificationCenter doesn't work like a post office. It only delivers notifications if someone actually listens to them at the moment they arrived. This is the reason your eventListenerDidReceiveNotification method is not being called: you add an observer in viewWillAppear, which is called after the segue (I assume that you're using segues because of the performSegueWithIdentifier method in your code) is finished, so it's definitely called after postNotification has been called.
So, in order to pass data via NSNotificationCenter you have to add an observer before you post a notification.
The following code is completely useless and unnecessarily overcomplicated, you shouldn't do anything like that, but since you keep insisting on using a scheme like this, here you go:
//Didn't test this code. Didn't even compile it, to be honest, but it should be enough to get the idea.
NSString * const SOUselessNotificationName = #"MyUselessNotification";
#pragma mark - FIRST VC
#interface SOFirstVC : UIViewController
#end
#implementation SOFirstVC
NSString * const SOasGoSegueIdentifer = #"asGo";
- (IBAction)btnClicked:(id)sender {
[self performSegueWithIdentifier:SOasGoSegueIdentifer sender:self];
}
-(void)postNotification {
[[NSNotificationCenter defaultCenter] postNotificationName:SOUselessNotificationName object:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifer isEqualToString:SOasGoSegueIdentifer]) {
SOSecondVC *destinationVC = (SOSecondVC *)segue.destinationViewController;
[destinationVC registerToReceiveNotificationsFromObject:self];
[self postNotification];
}
}
#end
#pragma mark - SECOND VC
#interface SOSecondVC : UIViewController
-(void)registerToReceiveNotificationsFromObject:(id)object;
#end
#implementation SOSecondVC
-(void)registerToReceiveNotificationsFromObject:(id)object {
[[NSNotificationCenter defaultCenter] addObserver:self selector:(eventListenerDidReceiveUselessNotification:) name:SOUselessNotificationName object:object];
}
-(void)eventListenerDidReceiveUselessNotification:(NSNotification*)uselessNotification {
NSLog(#"I got a useless notfication! Yay!");
}
-(void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#end
NSNotificationCenter basically has 3 steps
Adding Observer like [[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(open:) name:#"OpenDetail" object:nil];
Posting Notification [[NSNotificationCenter defaultCenter] postNotificationName:#"OpenDetail" object:self];
Removing Observer [[NSNotificationCenter defaultCenter] removeObserver:self name:#"OpenDetail" object:nil];
I think you are posting your notification and then later adding observer while it's vie versa. You have to add observer first then post notification.
HTH
First you have to setup the data you want to send
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:myObject forKey:#"aKey"];
Then you post it with the data like so:
[[NSNotificationCenter defaultCenter] postNotificationName: #"MyNotification" object:nil userInfo:userInfo];
And finally you read the data off the notification:
-(void)eventListenerDidReceiveNotification:(NSNotification*)notification
{
NSLog(#"i got notification:");
NSDictionary *userInfo = notification.userInfo;
NSString *myObject = [userInfo objectForKey:#"aKey"];
}
I have this really unexplained problem with NSNotification method.
I have been using NSNotificationCenter for a long time but i can't explain why this is happening.
My problem is this,
I have a UITableViewCell subclass where i send a NSNotificationCenter method to the UIViewController when a user taps a button in the cell.
[[NSNotificationCenter defaultCenter] postNotificationName:MOVE_TO_PROGRAM_VIEW
object:self
userInfo:#{INDEX_ROW : [NSNumber numberWithInteger:self.tag]}];
Where the self.tag is the row (for the data model in the controller).
In the controller i register for the notification in viewWillAppear: like so:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(userWantsToGoToProgramView:) name:MOVE_TO_PROGRAM_VIEW object:nil];
I also remove myself in the viewWillDisappear:
[[NSNotificationCenter defaultCenter] removeObserver:self name:MOVE_TO_PROGRAM_VIEW object:nil];
Now in the method for the notification i try to get the userInfo and the row but the notificaiton argument is nil for some reason..
- (void)userWantsToGoToProgramView:(NSNotification *)notification
{
// notification is nil here
// get the index of the video in the feed
NSDictionary *userInfo = notification.userInfo;
NSInteger videoIndex = [userInfo[INDEX_ROW] integerValue];
NSDictionary *videoData = self.feed[videoIndex];
}
Any advice of help will be appreciated
Thanks!
How can I pass NSString values from ViewController1 to ViewController2 by using notifications in iOS? I have tried:
ViewController1
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(incomingNotification:) name:#"test" object:nil];
}
- (void) incomingNotification:(NSNotification *)notification{
NSString *theString = [notification object];
NSLog(#"theString value=%#",theString);
}
ViewController2
- (void)viewDidLoad
{
NSString *myString=#"testing";
[[NSNotificationCenter defaultCenter] postNotificationName:#"test" object: myString];
}
It works fine while am going to ViewController2.
But I want to send values from ViewController1 to ViewController2 using these notifications. Is it possible. How?
You can use it by initializing ViewController2 in ViewController1's on button click event..Steps to invoke,
1.Create on method (say like notifRegister) in ViewController2,which initialize notification to receive dictionary value.
2.On button click event init ViewController2 and call method notifRegister
3.Then post notification in ViewController1.
Example:
- (IBAction)navigation:(id)sender {
ViewController1 *vc= [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"ViewController2"];
[vc notifRegister];
[self.navigationController pushViewController:(UIViewController*)vc animated:YES];
NSDictionary *name=[[NSDictionary alloc] initWithObjectsAndKeys:#"Tommy",#"name",nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"TextChanged" object:name];
}
On ViewController2:
-(void)notifRegister
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reloadLabel:) name:#"TextChanged"object:nil];
}
-(void)reloadLabel:(NSNotification*)sender
{
NSLog(#"reload label called %#",sender.object);
self.labelName=[sender.object objectForKey:#"name"];
}
Here self.labelName is an NSString object...
I think it is not necessary to call a invisible viewController to send notification. You can pass your values as below:
If you use storyboard, you can get ViewController2 in ViewController1's method prepareForSegue, so you can pass your reference here.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var targetViewController = segue.destinationViewController as UIViewController
}
If your manually create the second ViewController and use presentViewController, just pass your reference when initializing your ViewController2.
If you insist to use notification. Set view2 as a notification sender and view1 as a receiver with another notification.
You get an NSNotification object passed to your function.
Put your strings or other objects in the dictionary
NSDictionary* userInfo = #{#"completionHandler" : completionHandler,
#"myStringIdentifier" : myString};
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc postNotificationName:#"myNotification" object:self userInfo:userInfo];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveNotification:) name:#"UIKeyboardWillHideNotification" object:nil];
-(void) receiveNotification:(NSNotification*)notification
{
if ([notification.name isEqualToString:#"MyNotification"])
{
NSDictionary* userInfo = notification.userInfo;
... do dictionary stuff
}
}
This is a question which has been asked before search for userinfo and NSNotification for more examples
As per the doc, yes it's possible. But you should read the doc first (see NSNotificationCenter class reference).
The method you should look at is
- (void)postNotificationName:(NSString *)notificationName
object:(id)notificationSender
userInfo:(NSDictionary *)userInfo
where
notificationName is the notification you want to post. The notificationSender is the object that want to post the notification and userInfo is the info you want to pass with the notification.
So, if you want to pass a notification from ViewController2 to ViewController1 (or viceversa).
// ViewController1
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(incomingNotification:) name:#"myNotificationName" object:nil];
}
- (void) incomingNotification:(NSNotification *)notification {
NSDictionary *userInfo = notification.userInfo;
NSString *theString = userInfo[#"stringKey"]; // Here you retrieve the passed string from ViewController2 to ViewController1
NSLog(#"%#",theString);
}
// ViewController2
// Suppose you have an action set up for a specific button
- (IBAction)buttonTapped {
NSDictionary *userInfo = #{#"stringKey": #"stringPassed"};
[[NSNotificationCenter defaultCenter] postNotificationName:#"myNotificationName" object:self userInfo:userInfo];
}
Here I would highlight two main things.
Both controllers should be "valid". In other words they should be allocated in memory and presented somewhere.
When you add an observer you should also remove it.
Update 1
In this case you are passing a string from UIViewController2 to UIViewController1. Just switch the code you are using and you will be able to pass the same string from ViewController1 to ViewController2.
My question: what's your goal?
this will work...
in ViewController 2
[[NSNotificationCenter defaultCenter] postNotificationName:#"test" object:self userInfo:#{#"stringValue": myString}];
in ViewController 1
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(incomingNotification:) name:#"test" object:nil];
}
- (void) incomingNotification:(NSNotification *)notification{
NSString *theString = notification.userInfo[#"stringValue"] ;
NSLog(#"theString value=%#",theString);
}
I have a view I want to display on a certain event. My view controller is listening for a broadcast notification sent by the model and it attempts to display the view when it receives the broadcast.
However the view is not appearing. BUT if I run the exact same view code from elsewhere within the View Controller then it will be displayed. Here's some code from the VC to illustrate:
- (void) displayRequestDialog
{
MyView *view = (MyView*)[[[NSBundle mainBundle] loadNibNamed:#"MyView" owner:self options:nil] objectAtIndex:0];
view.backgroundColor = [UIColor lightGrayColor];
view.center = self.view.window.center;
view.alpha = 1.0;
[self.view addSubview:view];
}
- (void) requestReceived: (NSNotification*) notification
{
[self displayRequestDialog];
}
When the above code is run the view does not appear. However if I add the call to displayRequestDialog elsewhere, for example to viewDidAppear:
- (void) viewDidAppear
{
[self displayRequestDialog];
}
Then it is displayed.
My question therefore obviously is why can I get the view to successfully appear if I call displayRequestDialog from viewDidLoad, but it will not display if called from within requestReceived?
(Note that I am not calling requestReceived prematurely before the view controller / its view has loaded and displayed)
At first I was posting the notification like this:
[[NSNotificationCenter defaultCenter] postNotificationName: kMyRequestReceived
object: self
userInfo: dictionary];
Then I tried this:
NSNotification *notification = [NSNotification notificationWithName:kMyRequestReceived object:self userInfo:dictionary];
NSNotificationQueue *queue = [NSNotificationQueue defaultQueue];
[queue enqueueNotification:notification postingStyle:NSPostWhenIdle];
Then I tried this:
dispatch_async(dispatch_get_main_queue(),^{
[[NSNotificationCenter defaultCenter] postNotificationName: kMyRequestReceived
object: self
userInfo: dictionary];
});
Then I tried this:
[self performSelectorOnMainThread:#selector(postNotificationOnMainThread:) withObject:dictionary waitUntilDone:NO];
- (void) postNotificationOnMainThread: (NSDictionary*) dict
{
[[NSNotificationCenter defaultCenter] postNotificationName: kMyRequestReceived
object: self
userInfo: dict];
}
And I have tried invoking displayRequestDialog like this:
dispatch_async(dispatch_get_main_queue(),^{
[self displayRequestDialog];
});
I have found the cause of the view not displaying - the frame's origin is getting negative values when invoked via the notification code but positive values when invoked otherwise and thus was being displayed off the screen.
No idea why there should be a difference however.
You are not listening for the notification. Do so like this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(displayRequestDialog) name:kMyRequestReceived object:nil];
As far as we cannot see the code you use to register your controller to receive notifications I would recommend you to use the observer registration method which enforce getting notifications on the main thread "for free"
[[NSNotificationCenter defaultCenter] addObserverForName:#"Notification" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
NSLog(#"Handle notification on the main thread");
}];
I'm using Storyboards and iOS 6.1, I'm initiating a view like this:
PropertiesViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"Properties"];
PropertiesViewController has a 60px height viewn an including some labels and more. I want to add these views to another ScrollView as subview. Here what I'm doing:
controller.leftLabel.text = #"Test";
controller.background.image = [UIImage imageNamed: #"someimage.png"];
controller.view.frame = CGRectMake(0, currentHeight, controller.view.frame.size.width, cellHeight);
[self.scrollView addSubview: controller.view];
leftLabel is a UILabel and backgorund is a UIImageView.The problem is none of view's elements are not updating outside of PropertiesViewController. addSubview: is just adding as how its created, not allow to configure.
I've already checked NSNotificationCenter approach, if I'm not wrong it's not about updating instances. And I've also already added a method to receiver class to update labels inside of PropertiesViewController. That even did not worked.
What am I doing wrong?
Note: You may ask that why just I'm not using a TableView. There has to be more dynamic resources and their besides are not clear. There is also one thing that TableView is not possible with ScrollView, in some cases I've never use a TableView so scrollview will manage scroll.
Any help would be great.
EDIT:
According to Kalpesh's answer here what I did:
In my sender view controller:
PropertiesViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"Properties"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"update" object:#"Test string"];
controller.view.frame = CGRectMake(0, currentHeight, controller.view.frame.size.width, cellHeight);
// not sure how but I can change frame successfully.
[self.scrollView addSubview: controller.view];
Here is receiver:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Called"); // Working fine
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(changetext:) name:#"update" object:nil];
//even if set some object, nothing changed
}
- (void) changetext:(NSNotification *)notification {
NSLog(#"Received"); // Not working
leftLabel.text = [notification object];
}
Try this, You have to send notification from other viewcontroller when you want to change label of text
..
[[NSNotificationCenter defaultCenter] postNotificationName:#"changetext" object:stringobj];
in mainviewcontroller
-(void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(changetext:) name:#"changetext" object:nil];
}
- (void) changetext:(NSNotification *)notification
{
NSString * text =[notification object];
lbl.text=text;
}