为什么我不能使用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.phone
在prepareForSegue
很好
您应该将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。)因此需要strong
或copy
。
添加到@sergio响应,我想解释为什么第一个_TF_phoneOrEmail
不起作用,但第二个没有。 这只有在String
和NSString
的情况下才能找到。
您的_TF_phoneOrEmail
是在运行时创建的对象。 编译器在分配,启动和递增引用计数时生成代码(指令)。 因此,当您分配weak
引用时,从一个控制器导航到另一个控制器时,引用计数不会递增。 (您应该尝试使用@sergio提到的assign
或copy
)。
另一方面,当您声明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