【问题标题】:Calling method from another class doesn't work properly从另一个类调用方法不能正常工作
【发布时间】:2014-01-17 16:25:02
【问题描述】:

我正在尝试从另一个类更改 UILabel 的文本和位置。

我已经成功地从我的 SecondViewController 类中调用了我的 FirstViewController 类中的 -changeLabel 方法。这是我在两个课程中使用的代码:

SecondViewController:

#import "FirstViewController.h"

@interface SecondViewController ()
@property (nonatomic,strong) FirstViewController *firstViewController;
@end

@implementation SecondViewController
@synthesize firstViewController;

- (IBAction)button:(id)sender {
    firstViewController = [[FirstViewController alloc] init];
    [firstViewController changeLabel];
}

FirstViewController:

- (void)changeLabel {
    NSLog(@"changeLabel is called!");
    label.text = @"New text.";
    label.frame = CGRectMake(10, 100, 150, 40);
    NSLog(@"%@", label.text);
    NSLog(@"%f", label.frame.size.width);
}

奇怪的是,按下调用方法的“按钮”后记录器看起来是这样的:

"2013-12-30 19:24:50.303 MyApp[655:70b] changeLabel is called!"
"2013-12-30 19:24:50.305 MyApp[655:70b] New text."
"2013-12-30 19:24:50.308 MyApp[655:70b] 0.000000"

所以标签文本似乎发生了变化,但它没有出现在屏幕上。并且标签宽度记录为 0.0.. 即使我只是将其设置为 150。

为什么会这样?我不能从另一个类更改框架变量吗?有没有其他方法可以做到这一点?

重要提示:

FirstViewController 是主视图控制器,而 SecondViewController 是侧菜单,类似于 facebook 应用程序:

我希望能够按下SecondViewController(侧边菜单)上的“按钮”并调用FirstViewController(主)中的一个方法来改变UILabel的位置(框架)。

编辑:

这是我创建 UILabel 的方式:

label = [[UILabel alloc] init];
label.frame = CGRectMake(0, 0, 150, 40);
label.text = @"Text."
[self.view addSubview:label];

【问题讨论】:

  • 你在使用自动布局吗?
  • 如何创建label
  • 很可能FirstViewController的视图没有加载。
  • 我所指的标签是以编程方式创建的,所以不,我没有使用自动布局。
  • @Peter:你用什么方法创建标签?

标签: ios iphone class methods uiviewcontroller


【解决方案1】:

我认为问题是这样的。您正在从 FirstViewController 的新实例调用方法。

假设

1. FirstViewController at stack[0].
2. SecondViewController at stack[1].

如果您正在导航或离开

FirstViewController->SecondViewController

在这种情况下,FirstViewController 已经在内存中,地址为 0x23ffff

SecondViewController 中,您再次创建了FirstViewController 的新实例,它指向另一个地址“0x234jurhu”

- (IBAction)button:(id)sender {
    firstViewController = [[FirstViewController alloc] init];
    [firstViewController changeLabel];
}

不要在这里创建新实例。

您可以为此使用delegateNSNotification 概念。

【讨论】:

  • 您从 First->Second ViewController 移动是正确的。但是如何在不创建 FirstViewController 的新实例的情况下调用该方法?
  • @Peter 我提到了,你可以使用delegate 概念或NSNotification
  • 你能举个例子说明如何使用委托概念吗?
  • 你可以在这里回答我stackoverflow.com/questions/20259159/…
【解决方案2】:

FirstViewController 的显示效果如何?

问题来了:

firstViewController = [[FirstViewController alloc] init];
[firstViewController changeLabel];

您创建了FirstViewController 的新实例并更新了标签文本。如果您在导航堆栈中使用这些 VC 并从 SecondViewController 弹回 FirstViewController,您将不会看到任何标签更改,因为 they 是该类的不同实例。

如果您使用 FirstViewController 作为 SecondViewController 的 childViewController(我不认为这是您在做什么),那么在 - (IBAction)button:(id)sender 方法中您不需要实例化每次按下按钮时的 FirstViewController。

【讨论】:

  • 这看起来很合法,但你有什么建议让它发挥作用?如何在不创建 FirstViewController 的新实例的情况下从 SecondViewController 调用 -changeLabel 方法?
  • 这涉及到你的堆栈是如何构建的。您是否使用导航控制器来推送视图?
  • @Peter 我刚刚看到你的编辑,我需要看看你是如何管理两个视图控制器的。它们是如何分层的? SecondViewController 是否管理 FirstViewController?处理打开和关闭的代码是什么?
  • 我自己还没有编写在两个视图控制器之间导航的代码。我按照本教程创建了幻灯片菜单:appcoda.com/ios-programming-sidebar-navigation-menu。但是当在两个视图控制器之间来回切换时,不会调用“加载”方法,我的意思是 -viewDidLoad、-viewWillAppear: 和类似的方法永远不会被调用。只有第一次打开应用程序。如果你明白我的意思。 :)
  • 我知道这个问题可能很复杂,但我希望你继续关注;)
【解决方案3】:

感谢“@Gaurav Wadhwani”对此问题的回答:call method from other class (self issue)

我在我的FirstViewController.h 中添加了这段代码:

+ (FirstViewController *)singletonInstance;

然后将此代码添加到我的FirstViewController.m

static FirstViewController  *_singletonInstance = nil;


+(FirstViewController*)singletonInstance
{
    @synchronized([FirstViewController class])
    {
        if (!_singletonInstance)
            _singletonInstance = [[self alloc] init];
        return _singletonInstance;
    }

    return nil;
}


+(id)alloc
{
    @synchronized([FirstViewController class])
    {
        NSAssert(_singletonInstance == nil, @"Attempted to allocate a second instance of a singleton.");
        _singletonInstance = [super alloc];
        return _singletonInstance;
    }

    return nil;
}

然后我在SecondViewController 中添加了这段代码来运行changeLabel 方法:

[[FirstViewController singletonInstance] changeLabel];

到目前为止,这似乎工作得很好。我希望它不会在未来引起任何其他“问题”,但现在它似乎很完美。

【讨论】:

    【解决方案4】:

    尝试这样做:

    [label setNeedsDisplay];
    

    changeLabel 的最后一行之后。

    【讨论】:

      猜你喜欢
      • 2014-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-05
      • 2016-08-01
      • 2012-11-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多