【问题标题】:How to access a parameter that is passed dynamically to a child viewController in iOS?如何访问在 iOS 中动态传递给子 viewController 的参数?
【发布时间】:2012-12-16 06:03:19
【问题描述】:

我有一个viewController,它有一个按钮,单击该按钮时,会动态创建对另一个viewController 类的引用,并在此过程中设置该viewController 的参数。我在 for 循环中执行此操作,如下所示:

-(void) clickOnButton:(id)sender {


    for (PersonObject *checkPerson in [DataModel sharedInstance].personList) {

        if (((UIControl*)sender).tag == checkPerson.personID) {

            ParentViewController *parentView = [[NSClassFromString(checkPerson.childViewController) alloc] init];
            parentView.personName = checkPerson.name;
            NSLog(parentView.personName);
            [self.navigationController pushViewController:parentView animated:YES];


        }

    }

}

在创建的并将用户发送到的 viewController 中,我的 viewDidLoad 方法中有以下代码:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    NSLog(@"Hello %@", personName);
    UILabel *title = [[UILabel alloc] initWithFrame:CGRectMake(0, 10, 150, 35)];
    [title setCenter:CGPointMake(self.view.frame.size.width/2, 27)];
    [title setBackgroundColor:[UIColor clearColor]];
    [title setTextAlignment:NSTextAlignmentCenter];
    [title setFont:[UIFont boldSystemFontOfSize:15]];
    [title setText:personName];
    [self.view addSubview:title];

}

当我运行我的代码时,第一个 viewController 向我提供了 personName 参数的 NSLog 的正确输出,但是,第二个 viewController 语句中 viewDidLoad 方法中的 NSLog() 显示我的 personName 值为 nil,并且什么都没有显示为我的 viewController 标题。

参数 personName 是 NSString 类型,在父 viewController 类和子 viewController 类中都可以找到(有几个 viewController 类扩展了这个父类)。如何动态创建子 viewController 对象并让它捕获使用父 viewController 发送给它的正确参数值?

【问题讨论】:

  • 声明为(非原子,保留)
  • 顺便说一句(与您的问题无关),我注意到您将您的财产声明为retain。如果您使用 ARC,则应将 retain 替换为 strong。如果你没有使用 ARC,那么你的代码可能有泄漏,因为当你 alloc/init 你的 ParentViewController 时,你可能也应该 autorelease 它。

标签: ios inheritance uiviewcontroller


【解决方案1】:

一个常见的错误是在您要转换到的视图控制器中拥有一个界面,以便拥有如下界面:

@interface MyViewController : UIViewController
{
    NSString *personName;
}
@property (nonatomic, retain) NSString *personName
@end

然后是一个没有显式合成personName 或具有@synthesize 语句的实现,例如:

@implementation MyViewController

@synthesize personName = _personName;

// the rest of the implementation

@end

注意,如果你没有显式声明@synthesize 语句,它会像上面的语句一样自动合成personName

这段相当无害的代码是有问题的,因为你最终会得到两个实例变量,一个叫做personName,另一个是为你合成的,叫做_personName .

您真正应该做的是消除显式声明的 ivar,因此 @interface 看起来像:

@interface MyViewController : UIViewController
@property (nonatomic, retain) NSString *personName
@end

然后要么完全省略 @synthesize 语句,要么有一个看起来像这样的语句:

@synthesize personName = _personName;

然后,您的代码可以通过其访问器引用该属性,例如

NSLog(@"Hello %@", self.personName);

或者你可以使用实例变量(ivar):

NSLog(@"Hello %@", _personName);

(顺便说一句,通常建议在setting properties 时使用访问器(例如self.personName)。您真正必须使用ivar(例如_personName)的唯一一次是在initializer methods and dealloc。)

但是,归根结底,不要显式定义实例变量,让编译器为您合成它,从而消除此类问题。并且建议将 ivar 与前导下划线合成,以尽量减少在您真正打算使用属性的访问器方法时意外使用 ivar。

有关详细信息,请参阅高级内存管理编程指南中的Practical Memory Management

【讨论】:

  • 感谢 Rob 的回复。您实际上帮助我找到了解决方案。因为参数已经在Parent类中声明了,我不需要在子类中再次声明。将子类中参数的声明注释掉后,值就成功传递了。再次感谢您的帮助,以及上面关于使用强与保留的评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-25
  • 2020-06-14
  • 1970-01-01
  • 2018-08-15
  • 2013-06-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多