Update Text Label From Another View

戏子无情 提交于 2020-01-17 16:37:10

问题


I have an NSTimer that runs every 10 seconds and is kicked off from LandingController.m. It continues to run as you go to other views in the application. I want to be able to (when a certain condition is met within that timer) update a label field from another view GuardMenu.m The label I want to update is called CurrentZone.text and I want to update it from value "N" to value "Y."

Here's my timer on LandingController.m

self.messageTimer = [NSTimer scheduledTimerWithTimeInterval:10.0
                        target:self
                        selector:@selector(checkForMessages)                                                                     
                        userInfo:nil
                        repeats:YES];

Which calls this on LandingController.m

- (void)checkForMessages
{

        if ( //some condition here ){

        //update CurrentZone.text label in GuardMenu view and set equal to "Y"

        } else {

        //no need to update label in GuardMenu as it's currently equal to "N"

        }


    }

回答1:


First create a NSNotification in your init method of GuardMenu class

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotification:) name:@"TextChangeNotification" object:nil];
    }
    return self;
}

Then implement the notification's selector, this is where you will be changing your CurrentZone label text.

- (void)receiveNotification:(NSNotification *) notification {
    if ([[notification name] isEqualToString:@"TextChangeNotification"]) {
        NSLog (@"Change you label here");
        self.lblCurrentZone.text = @"Y";
    }
}

Now in your LandingViewController.m -viewDidLoad Method

Start the timer.

self->msgTimer = [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(checkForMessages) userInfo:nil repeats:YES]; 

Now implement the @selector for the NSTimer, this is where you will be sending the notification back to the GuardMenu class

- (void)checkForMessages {
    NSString *strText = @"test";
    if ([strText isEqualToString:@"test"]){
        [[NSNotificationCenter defaultCenter] postNotificationName:@"TextChangeNotification" object:nil];
    }
    else {

    }
}

NOTE: the NotificationName should be the same.

Sample Project Code Dropbox Link




回答2:


You can use the prepareForSegue method to pass objects between view controllers in the storyboard. For example, to pass a string from the GreyViewController to the OrangeViewController, in GreyViewController.m you have:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    OrangeViewController *orange = [segue destinationViewController];
    orange.self.orangeString = @"text for orangeView";
}

Then in the viewDidLoad of the other view controller, in the OrangeViewController.m, you can set the text of the label by doing the following:

self.orangeLabel.text = self.orangeString;



回答3:


Maybe you should describe which error you're getting. Is your checkForMessages method (not) firing? Use an NSLog() message to check. Otherwise, check if the UILabel you want to change is actually loaded into memory (i.e. is not nil). Please also let us know if the currentZone.text is part of the view hierarchy of the LandingController or of another view controller.




回答4:


You can make use of notifications.

In GuardMenu class init register for custom notification

[[NSNotificationCenter defaultCenter] addObserver:self 
                                      selector:@selector(receiveNotification:) 
                                      name:@"MessageChangeNotification" 
                                      object:nil];

In LandingController->checkForMessages method post the notification when condition is satisfied.

[[NSNotificationCenter defaultCenter] postNotificationName:@"MessageChangeNotification" 
                                      object:nil];

In GuardMenu class implement the notification callback selector

- (void) receiveNotification:(NSNotification *) notification
{

    if ([[notification name] isEqualToString:@"MessageChangeNotification"]) {
        NSLog (@"Successfully received the notification");
        //Change the label text here..
    }
}

Hope it helps!
Amar.




回答5:


Make sure that the label you are trying to edit is declared as a property in the appropriate view and properly synthesised. Also make sure it is connected in Interface Builder.

In GuardMenu.h

@property (strong, nonatomic) IBOutlet UILabel *CurrentZone;

Also, in LandingController.h, import GuardMenu.h:

#import "GuardMenu.h"

You will now be able to access the label and its text property from LandingController.h using

-(void)checkForMessages
{
   GuardMenu *guardMenu = [[GuardMenu alloc]init];
   if (/* some condition here */) {
      //update CurrentZone.text label in GuardMenu view and set equal to "Y"
      guardMenu.CurrentZone.text = @"Y";
   } else {
      //no need to update label in GuardMenu as it's currently equal to "N"
   }
}



回答6:


For this you should use KVO(Key Value Observing). There are lot of ways to pass notifications, but KVO is potentially much simpler. I suspect that Notification is used more often because you can do a ‘chain of responsibility’ for an event as opposed to just assigning an observer. However, just having an observer in a controller that can watch a particular property in another object and get notified of changes is a powerful and simple way to solve a whole class of problems.

Firstly set a public property in LandingController like "lablelText" .

Then add the observer once, when you create the LandingController view. Once you've added the observer, the observeValueForKeyPath:ofObject:change:context: method will be executed in GuardMenu, so you can do the update to the GuardMenu UI from there. You shouldn't need to do anything every time GuardMenu is about to appear.

In GuardMenu, you should probably create LandingController just before you are going to push LandingController onto the controller stack, presumably in the event handler for some action the user took. Immediately after you create LandingController, add the observer in GuardMenu with the correct NSKeyValueObservingOption value.

If you just want to be notified whenever the public property "lablelText" in LandingController is changed, then try this:

LandingController

@interface LandingController : UIViewController {
}

@property (strong, nonatomic) NSString* lablelText;

- (void)checkForMessages;

@end


@implementation LandingController 

@synthesize lablelText;

- (void)checkForMessages
 {

    if ( //some condition here ){

    //update CurrentZone.text label in GuardMenu view and set equal to "Y"
    self.lablelText = @"Y";

    } else {

    //no need to update label in GuardMenu as it's currently equal to "N"
    self.lablelText = @"N";
    }


}
@end


GuardMenu

@interface GuardMenu : UIViewController {
}

@property (strong, nonatomic) IBOutlet UILabel* nameLabel;

- (IBAction) methodToHandleEvent:(id)sender;

@end

@implementation GuardMenu

- (IBAction) methodToHandleEvent:(id)sender{
    LandingController* tempVC = [[LandingController alloc]init];
    [tempVC addObserver:self forKeyPath:@"lablelText" options:NSKeyValueObservingOptionNew context:NULL];
    [self.navigationController pushViewController:tempVC animated:YES];

}

- (void) observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context {
   // Here you will be notified everytime lablelText changes
    if ([keyPath isEqual:@"lablelText"]) {
        NSString* changedName = [change objectForKey:NSKeyValueChangeNewKey];
        // do something with the changedName - call a method or update the UI here
        self.nameLabel.text = changedName;
    }
}

@end

As an alternative for this you can use NSNotificationCeneter to pass notifications from one class to another for some event. For this you can check my detailed answer How to pass Notifications from one class to another for some event.

Hope it helps you.




回答7:


Create a notification in the init of GuardMenu class

[[NSNotificationCenter defaultCenter] addObserver:self 
                                  selector:@selector(receiveNotification:) 
                                  name:@"UpdateCurrentZoneNotification" 
                                  object:nil];

In the LandingController,

  • (void)checkForMessages {

    if ( //some condition here ){
    [[NSNotificationCenter defaultCenter] postNotificationName:@"UpdateCurrentZoneNotification" 
                                  object:nil];
    //update CurrentZone.text label in GuardMenu view and set equal to "Y"
    
    } else {
    
    //no need to update label in GuardMenu as it's currently equal to "N"
    
    }
    

    }



来源:https://stackoverflow.com/questions/16498422/update-text-label-from-another-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!