我用两个视图控制器做了一个非常简单的基于故事板的项目。
我想简单地从VC2访问在VC1中声明的字符串。第二个VC应该在按下按钮时在文本字段中显示文本。
我不想使用委派,一个用于全局数据的独立类或全局变量和Extern。相反,我读到使用对另一个VC的引用来实现变量共享很容易。
对于下面显示的代码,XCode没有抱怨,但我的问题是:第二个VC中的NSLog返回null
如果有人能告诉我如何修改代码以将字符串传递给第二个VC/告诉我哪里出了问题,我将不胜感激。
VC1标题:
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property NSString* textToPassToOtherVC;
VC1实现:
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
@synthesize textToPassToOtherVC = _textToPassToOtherVC;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_textToPassToOtherVC = @"Here is some text";
NSLog (@"Text in VC1 is: %@", _textToPassToOtherVC);
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
@end
VC2标题:
#import <UIKit/UIKit.h>
@class ViewController;
@interface ViewController2 : UIViewController
@property (nonatomic, strong) ViewController *received;
@property (strong, nonatomic) IBOutlet UITextField *textDisplay;
- (IBAction)textButton:(id)sender;
@end
VC2实现:
#import "ViewController2.h"
#import "ViewController.h"
@interface ViewController2 ()
@end
@implementation ViewController2
@synthesize textDisplay;
@synthesize received;
- (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.
}
- (void)viewDidUnload
{
[self setTextDisplay:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (IBAction)textButton:(id)sender {
NSLog (@"Text in VC1 from VC2 is: %@", self.received.textToPassToOtherVC);
textDisplay.text = self.received.textToPassToOtherVC;
}
@end
您的第二个视图控制器需要将其received
属性设置为表示第一个视图控制器的值。
对于基于故事板的项目,这通常在prepareForSegue:
中完成。在执行到第二个视图控制器的分段之前,将在第一个视图控制器中调用此方法。
(在我看来,你最好只把字符串传给你的第二个视图控制器,而不是一个指向整个视图控制器的指针,因为这减少了依赖性,是你的第三个视图控制器真正需要的唯一信息,但我们不要让事情复杂化。)
以下是我认为你需要采取的步骤:
- 在故事板中为从第一个视图控制器到第二个视图控制器的片段命名。对于这个例子,我将称之为
mySegue
- 在"ViewController.m"中导入"ViewController 2.h"-第一个视图控制器需要知道第二个视图控制器具有
received
属性 -
在您的第一个视图控制器中添加类似的
prepareForSegue:
方法:- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"mySegue"]) { ViewController2 *targetVC = (ViewController2*)segue.destinationViewController; targetVC.received = self; } }
希望这段代码的作用非常清楚。
您的错误是基于对属性的根本误解。属性只是处理getter和setter的样板和实现细节的语法糖。尽管设置_textToPassToOtherVC确实会使属性返回该值,但它不会"通知"其他属性,因为默认情况下,它对"received"的引用设置为nil,而您从未设置过。
如果在您实际检查此共享文本的值之前,您有以下行:
ViewController *myVC1;
ViewController2 *myVC2;
// ...some initialization.
myVC2.received = myVC1;
// Now the IBAction will display the correct text.
一切都会好起来的。
尝试使用NSNotification。当您需要发送字符串时,请发布带有该对象的NSNotification!
当你想发送字符串时(当然是在你给字符串一个值之后):
yourString = @"Hello";
[[NSNotificationCenter defaultCenter] postNotificationName:@"sendString" object:yourString];
在您的第二个视图控制器中:
-(void)viewDidLoad:
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ThingYouWantToDoWithString:) name:@"sendString" object:nil];
}
- (void)ThingYouWantToDoWithString:(NSNotification *)notification{
// Make sure you have an string set up in your header file or just do NSString *theString = [notification object] if your using ARC, if not allocate and initialize it and then do what I just said
theString = [notification object];
NSLog("%@", theString);
[self performSelector:@selector(OtherThings:) object:theString];
}
希望这能有所帮助!
您是否检查过您的self.received
不是null/nil?
在代码中设置一个断点,看看self.received
是否真的初始化了(如果没有初始化,那就是你什么都看不到的原因):
- (IBAction)textButton:(id)sender {
// Breakpoint here
NSLog (@"Text in VC1 from VC2 is: %@", self.received.textToPassToOtherVC);
textDisplay.text = self.received.textToPassToOtherVC;
}