为什么我不能使用prepareForSegue传递值?

我有两个UIViewControllers 。在ViewController我有代码:

 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"ToResetPwd_NumberSegue"]) { ResetPwdBySmsCodeViewController* vc = (ResetPwdBySmsCodeViewController*)[segue destinationViewController]; vc.phone_no = _TF_phoneOrEmail.text;//TF_phoneOrEmail is a UITextField vc.test = @"dagaga"; } } 

在B .h我有代码

 @interface ResetPwdBySmsCodeViewController : UIViewController @property (weak, nonatomic) NSString *phone_no; @property (weak, nonatomic) NSString *test; @end 

在B .m

我可以得到_phone_no的值,但不能_phone_no

我确信vc.phoneprepareForSegue很好

您应该将B ViewController中的2个属性声明为strong或更好的copy

 @interface ResetPwdBySmsCodeViewController : UIViewController @property (strong, nonatomic) NSString *phone_no; @property (strong, nonatomic) NSString *test; @end 

您可以获得_test的原因是您为其分配了一个文字字符串值,该值由编译器在特定的内存区域中分配。 因此它永远不会被释放, weak变量将无限期地指向它(直到你明确地为_test分配一个新值,即。)

另一方面,当你访问weak属性时,你可以从另一个可能不存在的对象中为vc.phone_no分配一个属性(因为当它指向的对象被解除分配时, weak属性是nil-ed。)因此需要strongcopy

添加到@sergio响应,我想解释为什么第一个_TF_phoneOrEmail不起作用,但第二个没有。 这只有在StringNSString的情况下才能找到。

您的_TF_phoneOrEmail是在运行时创建的对象。 编译器在分配,启动和递增引用计数时生成代码(指令)。 因此,当您分配weak引用时,从一个控制器导航到另一个控制器时,引用计数不会递增。 (您应该尝试使用@sergio提到的assigncopy )。

另一方面,当您声明test ,指针由编译器生成,但是使用@"dagga"对象。 这很有趣。 这是C中的内置优化,当您声明一个字符串(注意:不是String实例)时,不会生成创建保存值( @"dagga" )的String的新对象实例的指令。 如果遇到进程和线程内部,你会发现进程内存中有一个名为Code的内存段。 该过程(基本上执行编译器生成的指令)本身没有足够的权限写入此内存:它只能从中读取。 String对象(其指令不是由编译器生成)是在此内存中创建的。 它不完全是一个对象,它只是一个保存值的直接内存( @"dagga" )。

所以,甚至,当他提到“直到你明确地改变它的价值,那就是”时,@ sergio是错误的。 你不能。 尝试操作字符串(_test),您的应用程序将崩溃。

如果您已将其声明为[NSString stringWithString:@"dagga"] ,则编译器将生成在堆/堆栈内存中创建对象实例的指令,但您声明为文字,在任何执行时都无法释放。这个过程。

希望我很清楚。

您需要使您的属性强大或复制以声明内存的所有权。 您将它们设置为弱,这意味着您不会声明所有权,如果没有其他变量具有对数据的强引用,则数据将消失。

您总是希望使用NSString对象的副本,因为NSString有一个可变版本,这意味着您的数据可能会在您没有意识到的情况下进行更改。

 @interface ResetPwdBySmsCodeViewController : UIViewController @property (copy, nonatomic) NSString *phone_no; @property (copy, nonatomic) NSString *test; @end