我有两个视图控制器,称之为viewA
和ViewB
ViewA
ViewB
,一切正常,菜单出现现在,用户触摸了一个IBAction
按钮,该按钮在编程上只需要:
BOOL
的值,将其称为myBOOL
至YES
ViewB
myBOOL
变量的当前状态YES
传递回ViewA
我已声明相同的BOOL
,设置属性,在两个视图上合成,但在NSLog
被解除ViewB
并加载回ViewA
时,它会恢复回到NO
所以我知道我正在切线,我只是想知道你是否可以在两个控制器之间发送BOOL
的值,如果是,请给我一个例子......作为搜索已经找到NSString
的协议和委托示例,当我尝试使用BOOL
时,我陷入了导入循环,但是我已经读过它可以创建一个全局{{1} ,就像它的设计一样糟糕,我现在只需要克服这个障碍。
答案 0 :(得分:7)
关于这个主题的问题应该更多地关注NSNotificationCenter
而不是NSUserDefaults
,注意两者都是单身。
NSUserDefaults
:
此类的目的是 NOT 在类之间传递变量。它的目的是存储用户的默认值。 (即偏好,设置等)。
NSNotificationCenter
:
这个类非常方便,有许多不同的用途,其中一个用于广播 任何类接收的变量。接收类称为观察者。此模式称为Observer Pattern。
注意: NSUserDefaults
方法的优点是允许您在初始化其他类之前设置变量,并且可以随时检索。然而,这真的很草率(恕我直言),并认为是不好的做法。
NSNotificationCenter
上的快速和脏代码示例:
// upon initializing the class that wants to observe the changes, we add it as an observer.
// So, somewhere in the A.m, upon being initialized (init, maybe?).
- (id)init {
if (self = [super init]) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(calledUponNotif:)
name:@"MyObserveKey"
object:nil];
}
return self;
}
// the selector should look something like this:
- (void)calledUponNotif:(NSNotification *)notif {
id sentVar = [notif object];
}
// Somewhere in the B.m
[[NSNotificationCenter defaultCenter] postNotificationName:@"MyObserveKey"
object:varToSend];
另一个注释:调用postNotification方法后,其他类中已注册的选择器将被同步调用,因此您不必担心。
答案 1 :(得分:3)
有独立于视图的价值保持工具。您可以使用:
[[NSUserDefaults standardUserDefaults]setObject:<#(id)#> forKey:<#(NSString *)#>]
例如,您在A视图中输入字符串或数据,您可以将它们存储在上面的变量中。然后,在B视图中,您可以通过以下代码使用它们:
[[NSUserDefaults standardUserDefaults]objectOrKey:<#(NSString *)#>]
以下是NSUserDefaults
数据的示例:
查看A:
- (void)textFieldDidEndEditing:(UITextField *)sender
{
if (sender == homepage) {
[[NSUserDefaults standardUserDefaults]
setURL:[NSURL URLWithString:homepage.text] forKey:Ever5secHomepagePrefKey];
if( [homepage canResignFirstResponder] ) {
[homepage resignFirstResponder];
}
} else if (sender == userId) {
[[NSUserDefaults standardUserDefaults]
setObject:userId.text forKey:Ever5secUserIdPrefKey];
objectForKey:Ever5secUserIdPrefKey]);
if( [userId canResignFirstResponder] ) {
[userId resignFirstResponder];
}
} else if (sender == password) {
[[NSUserDefaults standardUserDefaults]
setObject:password.text forKey:Ever5secPasswordPrefKey];
if( [password canResignFirstResponder] ) {
[password resignFirstResponder];
}
}
}
查看B:
userId.text = [[NSUserDefaults standardUserDefaults]
objectForKey:Ever5secUserIdPrefKey];
password.text = [[NSUserDefaults standardUserDefaults]
objectForKey:Ever5secPasswordPrefKey];
homepage.text = [[[NSUserDefaults standardUserDefaults]
URLForKey:Ever5secHomepagePrefKey]
description];
答案 2 :(得分:3)
这不是一个很好的封装答案,但是没有能够使用协议或代理我不相信它会有很好的封装。
您还可以创建一个全局变量,您可以在一个视图控制器中设置该访问,并在另一个视图控制器中访问。
ViewControllerOne.h
extern NSString *globalVariable;
@interface ViewControllerOne
@end
ViewControllerOne.m
#import "ViewControllerOne.h"
@implementation ViewControllerOne
NSString *globalVariables = @"Some String in the variable to access in second controller";
@end
ViewControllerTwo.m
#import "ViewControllerTwo.h"
#import "ViewControllerOne.h"
@implemetation ViewControllerTwo
- (void)viewDidLoad
{
NSLog("%@", globalVariables);
}
@end
这将打印到控制台
****CONSOLE****
Some String in the variable to access in second controller
答案 3 :(得分:1)
您不需要使用NSNotificationCenter,NSUserDefaults或全局变量。
只要视图控制器是相关的(并查看OP的问题,它们看起来确实如此),您可以简单地设置视图控制器以保持对彼此的引用(使用其中一个引用)当然是软弱的,以避免&#34;保留&#34;或强大的参考&#34;,循环)。然后,每个视图控制器可以根据需要在另一个视图控制器上设置属性。示例如下......
注意:此概念对任何两个相关的视图控制器都有效。但是,以下代码假定:
FirstViewController.h
@interface FirstViewController : UIViewController
/* Hold the boolean value (or whatever value should be
set by the second view controller) in a publicly
visible property */
@property (nonatomic, assign) BOOL someBooleanValue;
/* Provide a method for the second view controller to
request the first view controller to dismiss it */
- (void)dismissSecondViewController;
@end
FirstViewController.m
#import "FirstViewController.h"
#import "SecondViewController.h"
@implementation FirstViewController
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
/* Get the reference to the second view controller and set
the appropriate property so that the secondViewController
now has a way of talking to the firstViewController */
SecondViewController *vc = [segue destinationViewController];
vc.firstViewController = self;
}
- (void)dismissSecondViewController
{
// Hide the secondViewController and print out the boolean value
[self.navigationController popViewControllerAnimated:YES];
NSLog(@"The value of self.someBooleanValue is %s", self.someBooleanValue ? "YES" : "NO");
}
@end
SecondViewController.h
#import "FirstViewController.h"
@interface SecondViewController : UIViewController
// Create a 'weak' property to hold a reference to the firstViewController
@property (nonatomic, weak) FirstViewController *firstViewController;
@end
SecondViewController.m
@implementation SecondViewController
/* When required (in this case, when a button is pressed),
set the property in the first view controller and ask the
firstViewController to dismiss the secondViewController */
- (IBAction)buttonPressed:(id)sender {
self.firstViewController.someBooleanValue = YES;
[self.firstViewController dismissSecondViewController];
}
@end
当然,处理这种inter-viewController通信的最正确方法是使用协议/委托/数据源,以便SecondViewController不需要知道其父/所有者对象的细节。但是,有时为了证明这个概念,更快/更简单地构建这样的解决方案。然后,如果一切正常并且代码值得保留,则重构使用协议。
如果视图控制器没有 - 并且不应该彼此了解,则可能需要使用NSNotificationCenter。不要使用全局变量或NSUserDefaults来进行视图控制器之间的通信。
答案 4 :(得分:1)
有两个选项可用于在不同的视图控制器中存储和检索数据。
1)NSUserDefaults
是存储数据和访问任何其他视图控制器的最佳选择。
NSUserDefaults
类提供了访问float, double, integer, Boolean
等常见类型的便捷方法。
默认对象必须是属性列表,即(或集合的实例组合)的实例:NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary
。
这是存储和检索数据的最简单方法。
如果你想阅读NSUserDefaults
,我在这里分享文件。
[NsuserDefaults Document。] [1]
2)当您希望在类或其他视图控制器外部访问属性时,可以创建属性。
以这种方式创建属性。 @property (nonatomic, retain) NSArray *arrayData;
然后您也可以在其他视图控制器中使用此数组值。
属性替换对象的访问器方法。
答案 5 :(得分:1)
有两个选项可用于在不同的视图控制器中存储和检索数据。
1)NSUserDefaults
是存储数据和访问任何其他视图控制器的最佳选择。
NSUserDefaults
类提供了访问float, double, integer, Boolean
等常见类型的便捷方法。
默认对象必须是属性列表,即(或集合的实例组合)的实例:NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary
。
这是存储和检索数据的最简单方法。
如果你想阅读NSUserDefaults
,我在这里分享文件。
NsuserDefaults Document.
2)当您希望在类或其他视图控制器外部访问属性时,可以创建属性。
以这种方式创建属性。 @property (nonatomic, retain) NSArray *arrayData;
然后您也可以在其他视图控制器中使用此数组值。
属性替换对象的访问器方法。
你可以在这里看到我的答案。 Pass value from one view controller to another
答案 6 :(得分:0)
我认为以下方式使用块的强大功能的最佳方法。
在ViewB.h中
typedef void (^CompletionHandler)(BOOL myBool);
@interface ViewB : UIViewController {
CompletionHandler completionHandler;
}
- (void)dismissHandler:(CompletionHandler)handler;
在ViewB.m
中- (void)dismissHandler:(CompletionHandler)handler {
completionHandler = handler;
}
- (IBAction)dismiss:(id)sender {
completionHandler (YES); // your yes no logic here
}
在ViewA.m
中- (IBAction)showPopup:(id)sender {
ViewB *vc = [[ViewB alloc] init];
[self.view addSubview:vc.view];
[vc dismissHandler:^(BOOL myBool) {
if (myBool) {
//Do your work;
}
}];
}