-1

我有一个NSTimer每 10 秒运行一次,并从 LandingController.m 启动。当您转到应用程序中的其他视图时,它会继续运行。我希望能够(当在该计时器内满足某个条件时)从另一个视图 GuardMenu.m 更新标签字段我要更新的标签称为 CurrentZone.text,我想将其从值“N”更新为值“Y”。

这是我在 LandingController.m 上的计时器

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

这在 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"

        }


    }
4

7 回答 7

8

首先在initGuardMenu 类的方法中创建一个 NSNotification

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

然后实现通知的选择器,这是您将更改CurrentZone标签文本的地方。

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

现在在你的LandingViewController.m -viewDidLoad方法中

启动计时器。

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

现在@selector为 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 {

    }
}

注意:NotificationName应该是一样的。

示例项目代码 Dropbox 链接

于 2013-05-18T05:48:36.600 回答
0

您可以使用该prepareForSegue方法在情节提要中的视图控制器之间传递对象。例如,要将字符串从 GreyViewController 传递给 OrangeViewController,在 GreyViewController.m 中您有:

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

然后在viewDidLoad另一个视图控制器的 OrangeViewController.m 中,您可以通过执行以下操作来设置标签的文本:

self.orangeLabel.text = self.orangeString;
于 2013-05-13T04:01:01.263 回答
0

也许您应该描述您遇到的错误。你的checkForMessages方法(不是)触发了吗?使用NSLog()消息进行检查。否则,检查UILabel您要更改的是否实际加载到内存中(即不是nil)。如果它是另一个视图控制器currentZone.text的视图层次结构的一部分,也请告诉我们。LandingController

于 2013-05-13T15:55:59.153 回答
0

您可以使用通知。

在 GuardMenu 类init中注册自定义通知

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

在 LandingController->checkForMessages 方法中,当条件满足时发布通知。

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

在 GuardMenu 类中实现通知回调选择器

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

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

希望能帮助到你!
阿马尔。

于 2013-05-14T11:05:55.810 回答
0

确保您尝试编辑的标签在适当的视图中声明为属性并正确合成。还要确保它已在 Interface Builder 中连接。

GuardMenu.h

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

此外,在LandingController.h,导入GuardMenu.h

#import "GuardMenu.h"

LandingController.h您现在可以通过使用访问标签及其文本属性

-(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"
   }
}
于 2013-05-14T11:39:37.217 回答
0

为此,您应该使用KVO(Key Value Observing)。有很多方法可以传递通知,但KVO可能要简单得多。我怀疑通知的使用频率更高,因为您可以为事件执行“<strong>责任链”,而不是仅仅分配观察者。然而,仅仅在控制器中有一个观察者,它可以观察另一个对象中的特定属性并获得更改通知,这是解决一整类问题的一种强大而简单的方法。

LandingController首先在类似 " "中设置一个公共属性lablelText

然后在创建 LandingController 视图时添加一次观察者。添加观察者后,observeValueForKeyPath:ofObject:change:context:方法将在 GuardMenu 中执行,因此您可以从那里更新 GuardMenu UI。每次 GuardMenu 即将出现时,您都不需要做任何事情。

在 GuardMenu 中,您可能应该在将 LandingController 推送到控制器堆栈之前创建 LandingController,大概是在用户执行的某些操作的事件处理程序中。创建 LandingController 后,立即在 GuardMenu 中添加具有正确NSKeyValueObservingOption值的观察者。

如果您只想在 LandingController 中的公共属性“labellText”发生更改时收到通知,请尝试以下操作:

着陆控制器

@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

作为替代方案,您可以使用NSNotificationCeneter将通知从一个类传递到另一个类以获取某些事件。为此,您可以查看我的详细答案How to pass Notifications from one class to another for some event

希望它可以帮助你。

于 2013-05-15T05:45:43.897 回答
0

在 GuardMenu 类的 init 中创建通知

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

在着陆控制器中,

  • (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"
    
    }
    

    }

于 2013-05-15T13:31:08.517 回答