How to Update UILabel from Another ViewController - ios

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;
}

Related

iOS - awakeFromNib of UITableViewCell gets called when an NSNotification is received

NSNotification observers are added when awakeFromNib is called in my UITableViewCell. Then, I am removing the observers when removeFromSuperView is called.
- (void)awakeFromNib
{
[super awakeFromNib];
[self setNotificationObserver];
_vHolder.layer.cornerRadius = 10.0f;
_vHolder.layer.shadowColor = [UIColor blackColor].CGColor;
_vHolder.layer.shadowRadius = 2.0f;
_vHolder.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
_vHolder.layer.shadowOpacity = 0.5f;
}
- (void)removeFromSuperview
{
[super removeFromSuperview];
[self removeNotificationObserver];
}
- (void)setNotificationObserver
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didReceiveESSMQTTMessageNotification:) name:NOTIF_ESSMQTT_MESSAGE_RECEIVED object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didReceiveDeviceStatesMessageNotification:) name:NOTIF_DEVICE_STATES_RECEIVED object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didReceiveDeviceOnOffStateNotification:) name:NOTIF_DEVICE_ON_OFF_STATE_RECEIVED object:nil];
}
- (void)removeNotificationObserver
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:NOTIF_ESSMQTT_MESSAGE_RECEIVED object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NOTIF_DEVICE_STATES_RECEIVED object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NOTIF_DEVICE_ON_OFF_STATE_RECEIVED object:nil];
}
I am using NSNotification to refresh states of my buttons and images within this UITableViewCell.
The problem I am facing is, every time an NSNotication is received, the awakeFromNib is called. This will cause the states of my buttons and images to refresh back to its initial states. The strange thing is, I never saw removeFromSuperview getting called before that.
So my questions are:
Why is awakeFromNib getting called when NSNotification is received?
I am just wondering, is adding observer under awakeFromNib the correct thing to do when you want your UITableViewCells to observe NSNotifications? (Well, I've been doing this all the time.)
Because your cell was refreshed content but did not be remove from superview
You had to call removeNotificationObserver when content of cell was refreshed successfully.
I suggest you using protocol instead of notification.
Hope help.

handleKeyboardWillShow notification Handling

I have a Tableview in inside a viewcontroller. I have added following code to get keyboard notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(handleKeyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(handleKeyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
And on keyboard show i am scrolling my table to bottom.
- (void)handleKeyboardWillShow:(NSNotification *)notification
{
[self scrollToBottomAnimated:YES];
}
But i have a textview in my view controller as well. So when i click on textview the handleKeyboardWillShow method is called as well resulting unnecessary scrolling my tableview which i do not need if textview is clicked.
Can some one please help me figure out how to detect from which sender handleKeyboardWillShow is called.
Thanks
You can do it by checking who is first responder.
- (void)handleKeyboardWillShow:(NSNotification *)notification
{
if ([textFieldForScrolling isFirstResponder]) {
[self scrollToBottomAnimated:YES];
} else {
NSLog(#"Is a different text input");
}
}
Let me know if you need more explanation.
I would register for keyboardWillChange - which covers both showing and hiding. You can get the keyboard rect and adjust your content offset based on the keyboard's location. Note: You can animate the change in content offset - I just didn't do it in this answer.
In your textfield delegate methods willBeginEditing and didEndEditing, you can set the state variable called currentTextField.
-(void)keyboardWillChange:(NSNotification *)notification {
keyboardRect = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
keyboardRect = [self.view convertRect:keyboardRect fromView:nil];
CGPoint currentFieldPoint = [currentTextField convertPoint:currentTextField.frame.origin toView:self.view];
if(keyboardRect.origin.y < currentFieldPoint.y + currentTextField.frame.size.height){
//move stuff here
[[self tableView] setContentOffset:CGPointMake(0, [self tableView].contentOffset.y + offsetValue)];
}
}

Top bar - UIImage link

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"];
}

is this a valid workaround to keyboard obscuring content

I have a Tableview where the user can enter values into a textField as one of the custom cells
Apple have some documentation about how to adjust view content by repositioning the view clear of the keyboard's vertical dimension ( Here ) but it relies upon one placing that view into a UIScrollView. I cant do this with a tableview.
I could redesign the app so that the entry gets done in a separate detail view using the usual navigation controller, but i'd rather the user not have to perform an extra touch ( and be ferried off into yet another screen ) if possible. I like the idea of doing the deed "right where we are"
so my workaround to have a few extra tableview cells at the bottom containing a %20 or so, normal usage shouldn't register the oddity, as they are only focussed on what is visible.
I'd have to store the spaces in my datasource array and then sort descending, but that's OK
the question is, is this good practice? and even more possibly, could it be against Apple's HIG sufficient for refusal?
UITableView is a subclass of UIScrollView, so should be able to adjust the content and scroll view insets just like in the example you linked.
The way I've solved this issue is to subclass UITableView. Here's what I've done:
// AOTableView.h file
typedef enum
{
AOKeyboardStateUnknown = 0,
AOKeyboardStateShowing,
AOKeyboardStateHidden
} AOKeyboardState;
#import <UIKit/UIKit.h>
#import "AOKeyboardState.h"
#interface AOTableView : UITableView
#property (nonatomic) BOOL observeKeyboardNotifications;
#property (nonatomic) AOKeyboardState keyboardState;
#end
// AOTableView.m file
#import "AOTableView.h"
#interface AOTableView(Private)
#property (nonatomic) CGRect frame0;
- (void)setup;
- (void)keyboardWillShow:(NSNotification *)notification;
- (void)keyboardWillHide:(NSNotification *)notification;
#end
#implementation AOTableView
#pragma mark - Object lifecycle
- (void)awakeFromNib
{
[self setup];
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
[self setup];
}
return self;
}
- (void)setup
{
self.contentSize = self.frame.size;
self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_keyboardState = AOKeyboardStateUnknown;
_frame0 = self.frame;
_observeKeyboardNotifications = NO;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - Custom setters
- (void)setObserveKeyboardNotifications:(BOOL)observeKeyboardNotifications
{
if (_observeKeyboardNotifications == observeKeyboardNotifications)
return;
_observeKeyboardNotifications = observeKeyboardNotifications;
if (_observeKeyboardNotifications)
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
else
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
}
#pragma mark - UIKeyboard Notifications
- (void)keyboardWillShow:(NSNotification *)notification
{
if (self.keyboardState == AOKeyboardStateShowing)
return;
self.frame0 = self.frame;
self.keyboardState = AOKeyboardStateShowing;
NSDictionary* info = [notification userInfo];
CGRect keyboardFrame = CGRectZero;
[[info objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrame];
CGRect frame = self.frame0;
frame.size.height = CGRectGetMinY(keyboardFrame) - CGRectGetMinY(frame);
self.frame = frame;
[self scrollToRowAtIndexPath:self.indexPathForSelectedRow atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
[self deselectRowAtIndexPath:self.indexPathForSelectedRow animated:NO];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
if (self.keyboardState == AOKeyboardStateHidden)
return;
self.keyboardState = AOKeyboardStateHidden;
self.frame = self.frame0;
}
#end
After creation (or loading the view from an IBOutlet), you call this method to tell the class to start listening for keyboard notifications:
[tableViewInstance setObserveKeyboardNotifications:YES];
Whenever a user clicks on a cell, it becomes the self.indexPathForSelectedRow cell... so its scrolled to by the AOTableView instance automatically.
For this to work, though, I've had to turn off userInteraction on the UITextField within the cell (otherwise, the device can get confused about if the user is clicking on the cell or on the text field). Instead, when a user selects a cell that has a text field, I tell the text field to the become first responder, like this:
[cell.textField becomeFirstResponder];
I hope this helps.
You don't need the extra cells or anything fancy.
Since your text fields are inside the table view cells, you can use the following:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
UITableViewCell *cell = (UITableViewCell *)textField.superview.superview;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
return YES;
}
This means that the keyboard will scroll appropriately each time a text field becomes first responder. This takes advantage of the table view being a scroll view subclass.
Note that this assumes:
Your (table) view controller is the text fields' delegate.
Your text field is a subview of the cell's content view, not the cell itself.
If the text field is a subview of the cell, the first line of the method above should reference only one superview (i.e., textField.superview).

Issue with UIView loaded from nib file

I am developing an application with multiple views. I have a template for an image gallery which I have created in a xlib file. This view will be loaded as a single page in a scroll view. I am able to get the view loaded multiple time from xlib with the following:
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
- (id)initWithFrame:(CGRect)frame
{
self = [[[NSBundle mainBundle] loadNibNamed:#"GSEstimateView" owner:self options:NULL] lastObject];
self.commentText.delegate = self;
self.scrollView.delegate = self;
self.commentText.delegate =self;
[self registerForKeyboardNotifications];
return self;
}
The first issue I am facing is, when the key board is shown the keyboardWasShown: method is getting called for as many UIViews I have created. If I try to load the keyboard from the second UIView, I get an exception for invalid selector being called. Is the UIView loaded from a nib or xlib Singleton? How can I have my UIView instance notified if I load it from nib file?
(^.^)"Hi sorry for my English is not good if someone like correct my redaction I would appreciate this"
Hi first I don't recommend to use NSNotification prefer to use protocols like this.
#protocol KeyBoardDelegate <NSObject>
- (void)KeyBoardVisible:(BOOL)op;
#end
And if you have multiples views and if you want to now the view control like this:
*viewDidLoad, viewDidUnload, viewWillDisappear, viewWillAppear, and others *
I recommend use the view of the UIViewController like this.
UIViewControllerCustom *example = [[UIViewControllerCustom alloc] initWithNibName:#"exampleNIB" bundle:[NSBundle mainBundle]];
[self.view addSubview:example.view];
Using this you can take the control of the view of example viewcontroller and use the methods
- (void)viewDidLoad{
[super viewDidLoad];
//When the nib has been loaded.
}
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
//When the view is show.
}
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
//The view is hidden
}
- (void)viewDidUnload{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
And some more methods. :)

Resources