简体   繁体   English

Xcode:如何从子类访问方法?

[英]Xcode: How do I access methods from Sub Classes?

When I try to access a method in my main ViewController from a SubView, my app crashes. 当我尝试从SubView访问主ViewController中的方法时,我的应用程序崩溃。

Please help. 请帮忙。

I have a UIButton in my main ViewController that changes the text in a UILabel, which is also in my main View. 我的主ViewController中有一个UIButton,它可以更改UILabel中的文本,该UILabel也位于我的主View中。 I have a UIButton in a SubView that is supposed to change the string again, by accessing the same method from the main ViewController. 我在SubView中有一个UIButton,应该通过从主ViewController访问相同的方法来再次更改字符串。 But the app crashes. 但是该应用程序崩溃了。

Here's my code: 这是我的代码:

Main ViewController 主ViewController

ViewController.h ViewController.h

#import <UIKit/UIKit.h>
#import "SubViewController.h"

@interface ViewController : UIViewController

@property (nonatomic, strong) UILabel *label;
@property (nonatomic, retain) UIButton *mainClassButton;

- (void) setLabelTo:(NSString *)copy;

@end

ViewController.m ViewController.m

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

@synthesize label;
@synthesize mainClassButton;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    self.label = [[UILabel alloc] initWithFrame:CGRectMake(30.0, 30.0, 200.0, 30.0)];
    self.label.text = @"Let's Go Mets!";
    [self.view addSubview:label];

    mainClassButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    mainClassButton.frame = CGRectMake(30.0, 70.0, 200.0, 30.0);
    [mainClassButton setTitle:@"Main Class Button" forState:UIControlStateNormal];
    [mainClassButton addTarget:self action:@selector(touchAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:mainClassButton];

    SubViewController *subViewController = [[SubViewController alloc] init];
    subViewController.view.backgroundColor = [UIColor clearColor];
    [self.view addSubview:subViewController.view];

    [self.view bringSubviewToFront:self.mainClassButton];
}

- (IBAction)touchAction:(UIButton *) sender
{
    [self setLabelTo:@"Here we go Yankess!"];
}

- (void) setLabelTo:(NSString *)copy
{
    self.label.text = copy;
}

Sub ViewController 子ViewController

SubViewController.h SubViewController.h

#import <UIKit/UIKit.h>
#import "ViewController.h"

@interface SubViewController : UIViewController

@property (nonatomic, retain) UIButton *subClassButton;

@end

SubViewController.m SubViewController.m

@implementation SubViewController

@synthesize subClassButton;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    subClassButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    subClassButton.frame = CGRectMake(30.0, 115.0, 200.0, 30.0);
    [subClassButton setTitle:@"Sub Class Button" forState:UIControlStateNormal];
    [subClassButton addTarget:self action:@selector(touchAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:subClassButton];

}

- (IBAction)touchAction:(UIButton *) sender
{
    ViewController *vc = [[ViewController alloc] init];

    [vc setLabelTo:@"If you ask me, I prefer the White Sox."];
}

I'm still kind of new to Xcode and Objective-C and I would appreciate any help you could offer. 我还是Xcode和Objective-C的新手,希望您能提供任何帮助。

Thanks 谢谢

You need to call -setLabelTo on your already existing instance of ViewController from within -[SubViewController touchAction:] --at the moment, you are creating a new instance of ViewController and calling -setLabelTo: on that new instance. 你需要调用-setLabelTo您已有的实例ViewController-[SubViewController touchAction:] --at此刻,你正在创建的新实例ViewController ,并呼吁-setLabelTo:对新实例。

In order to call -setLabelTo on the ViewController , we need a reference to that ViewController . 为了在ViewController上调用-setLabelTo ,我们需要对该ViewController的引用。

UIViewController provides a property parentViewController which, under ideal circumstances, would provide your SubViewController a reference to your ViewController . UIViewController提供了性能parentViewController其中,在理想情况下,将提供您的SubViewController您参考ViewController However, in this case, it does not provide such a reference. 但是,在这种情况下,它没有提供这样的参考。 You add your SubViewController 's view as a subview of your ViewController , but you do not add your SubViewController as a child view controller of your ViewController . 您将SubViewController的视图添加为ViewController的子视图,但没有SubViewController添加为ViewController的子视图控制器。 (See also this question and the accepted answer .) To fix this issue, in -[ViewController viewDidLoad] , add the line (另请参见此问题可接受的答案 。)要解决此问题,请在-[ViewController viewDidLoad] ,添加以下行

[self addChildViewController:subViewController];

after

SubViewController *subViewController = [[SubViewController alloc] init];

giving you 给你

SubViewController *subViewController = [[SubViewController alloc] init];
[self addChildViewController:subViewController];
subViewController.view.backgroundColor = [UIColor clearColor];
[self.view addSubview:subViewController.view];

At this point, your SubViewController is a child view controller of ViewController and your SubViewController 's view is a subview of your ViewController 's view. 此时,您的SubViewControllerViewController的子视图控制器,而SubViewController的视图是ViewController的视图的子视图。

At this point, you can change your implementation of -[SubViewController touchAction:] to 此时,您可以将-[SubViewController touchAction:]实现更改为

- (IBAction)touchAction:(UIButton *) sender
{
    ViewController *vc = self.parentViewController;

    [vc setLabelTo:@"If you ask me, I prefer the White Sox."];
}

Which will call -setLabelTo: on your original ViewController rather than creating a new instance and causing a crash. 它将在原始ViewController上调用-setLabelTo:而不是创建新实例并导致崩溃。

您必须为subviewcontroller获取父视图控制器: self.parentViewController在subViewController中的touchAction中完成的操作是创建一个新的View Controller。

Look at these lines: 看一下这些行:

ViewController *vc = [[ViewController alloc] init];
[vc setLabelTo:@"If you ask me, I prefer the White Sox."];

You are instantiating ViewController, but the viewDidLoad is not called. 您正在实例化ViewController,但未调用viewDidLoad There you instantiate UILabel which you want to set the title on using setLabelTo method. 在此实例化要使用setLabelTo方法设置标题的UILabel。

The viewDidXXXX and viewWillXXXX are called automatically when they are used in Storyboard or in some UINavigationController. Storyboard或某些UINavigationController中使用viewDidXXXX和viewWillXXXX时,它们会自动调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM