- objective-c - iOS 5 : Can you override UIAppearance customisations in specific classes?
- iphone - 如何将 CGFontRef 转换为 UIFont?
- ios - 以编程方式关闭标记的信息窗口 google maps iOS
- ios - Xcode 5 - 尝试验证存档时出现 "No application records were found"
将数据从子模态视图传递到父 View Controller 的最佳方法是什么?
我的 iPad 应用程序上有一个子模式登录屏幕,我想将用户信息传递回父 Split View Controller 。
我正在考虑使用 NSNotification,但我不确定这是否是将数据传回父级的最简单/最有效的方法。
谢谢!
艾伦
最佳答案
我建议,as iPatel did , 使用 delegation来解决你的问题。父 View Controller 和登录 View Controller 之间的关系使这种模式很合适。当一个对象创建另一个对象以履行特定职责时,应将委托(delegate)视为使创建的对象与创建者通信的一种方式。选择委托(delegate)的一个特别令人信服的理由是,如果要完成的任务可能有多个步骤,需要对象之间的高级交互。你可以看看 NSURLConnectionDelegate
protocol作为一个例子。连接到 URL 是一项复杂的任务,涉及处理响应、满足身份验证挑战、保存下载的数据和处理错误等阶段,连接和委托(delegate)在连接的整个生命周期内一起处理这些。
您可能已经注意到,在 Objective-C 中,协议(protocol)用于实现委托(delegate),而无需将创建的对象(在本例中为您的登录 View Controller )与创建它的对象(父 View Controller )紧密耦合。然后,登录 View Controller 可以与任何可以接收其协议(protocol)中定义的消息的对象进行交互,而不是依赖于任何特定的类实现。明天,如果您收到允许任何 View Controller 显示登录 View 的要求,则登录 View Controller 不需要更改。您的其他 View Controller 可以实现其委托(delegate)协议(protocol),创建和呈现登录 View ,并将自己分配为委托(delegate),而登录 View Controller 不知道它们的存在。
您在 Stack Overflow 上找到的一些委托(delegate)示例可能非常令人困惑,并且与内置框架中的示例非常不同。必须仔细选择协议(protocol)的名称和接口(interface),以及分配给每个对象的职责,以便最大限度地重用代码,达到代码的目的。
您应该首先查看内置框架中的许多委托(delegate)协议(protocol),以了解在代码中表达的关系是什么样的。这是另一个基于您的登录用例的小示例。我希望你会发现委托(delegate)的目的是明确的,所涉及的对象的角色和职责是明确的,并通过它们在代码中的名称来表达。
首先,我们看一下 LoginViewController 的委托(delegate)协议(protocol):
#import <UIKit/UIKit.h>
@protocol LoginViewControllerDelegate;
@interface LoginViewController : UIViewController
// We choose a name here that expresses what object is doing the delegating
@property (nonatomic, weak) id<LoginViewControllerDelegate> delegate;
@end
@protocol LoginViewControllerDelegate <NSObject>
// The methods declared here are all optional
@optional
// We name the methods here in a way that explains what the purpose of each message is
// Each takes a LoginViewController as the first argument, allowing one object to serve
// as the delegate of many LoginViewControllers
- (void)loginViewControllerDidLoginSuccessfully:(LoginViewController *)lvc;
- (void)loginViewController:(LoginViewController *)lvc didFailWithError:(NSError *)error;
- (void)loginViewControllerDidReceivePasswordResetRequest:(LoginViewController *)lvc;
- (void)loginViewControllerDiDReceiveSignupRequest:(LoginViewController *)lvc;
- (BOOL)loginViewControllerShouldAllowAnonymousLogin:(LoginViewController *)lvc;
@end
#import "LoginViewController.h"
@interface LoginViewController ()
@property (weak, nonatomic) IBOutlet UIButton *anonSigninButton;
@end
@implementation LoginViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Here we ask the delegate for information used to layout the view
BOOL anonymousLoginAllowed = NO;
// All our protocol methods are @optional, so we must check they are actually implemented before calling.
if ([self.delegate respondsToSelector:@selector(loginViewControllerShouldAllowAnonymousLogin:)]) {
// self is passed as the LoginViewController argument to the delegate methods
// in this way our delegate can serve as the delegate of multiple login view controllers, if needed
anonymousLoginAllowed = [self.delegate loginViewControllerShouldAllowAnonymousLogin:self];
}
self.anonSigninButton.hidden = !anonymousLoginAllowed;
}
- (IBAction)loginButtonAction:(UIButton *)sender
{
// We're preteneding our password is always bad. So we assume login succeeds when allowed anonmously
BOOL loginSuccess = [self isAnonymousLoginEnabled];
NSError *loginError = [self isAnonymousLoginEnabled] ? nil : [NSError errorWithDomain:@"domain" code:0 userInfo:nil];
// Fake concurrency
double delayInSeconds = 1.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// Notify delegate of failure or success
if (loginSuccess) {
if ([self.delegate respondsToSelector:@selector(loginViewControllerDidLoginSuccessfully:)]) {
[self.delegate loginViewControllerDidLoginSuccessfully:self];
}
}
else {
if ([self.delegate respondsToSelector:@selector(loginViewController:didFailWithError:)]) {
[self.delegate loginViewController:self didFailWithError:loginError];
}
}
});
}
- (IBAction)forgotPasswordButtonAction:(id)sender
{
// Notify delegate to handle forgotten password request.
if ([self.delegate respondsToSelector:@selector(loginViewControllerDidReceivePasswordResetRequest:)]) {
[self.delegate loginViewControllerDidReceivePasswordResetRequest:self];
}
}
- (IBAction)signupButtonAction:(id)sender
{
// Notify delegate to handle signup request.
if ([self.delegate respondsToSelector:@selector(loginViewControllerDiDReceiveSignupRequest:)]) {
[self.delegate loginViewControllerDiDReceiveSignupRequest:self];
}
}
- (BOOL)isAnonymousLoginEnabled
{
BOOL anonymousLoginAllowed = NO;
if ([self.delegate respondsToSelector:@selector(loginViewControllerShouldAllowAnonymousLogin:)]) {
anonymousLoginAllowed = [self.delegate loginViewControllerShouldAllowAnonymousLogin:self];
}
return anonymousLoginAllowed;
}
@end
#import "MainViewController.h"
#import "LoginViewController.h"
#define LOGGED_IN NO
@interface MainViewController () <LoginViewControllerDelegate>
@end
@implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Fake loading time to show the modal cleanly
if (!LOGGED_IN) {
double delayInSeconds = 1.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// Create a login view controller, assign its delegate, and present it
LoginViewController *lvc = [[LoginViewController alloc] init];
lvc.delegate = self;
[self presentViewController:lvc animated:YES completion:^{
NSLog(@"modal completion finished.");
}];
});
}
}
#pragma mark - LoginViewControllerDelegate
- (void)loginViewControllerDidLoginSuccessfully:(LoginViewController *)lvc
{
NSLog(@"Login VC delegate - Login success!");
[self dismissViewControllerAnimated:YES completion:NULL];
}
- (void)loginViewController:(LoginViewController *)lvc didFailWithError:(NSError *)error
{
// Maybe show an alert...
// UIAlertView *alert = ...
}
- (void)loginViewControllerDidReceivePasswordResetRequest:(LoginViewController *)lvc
{
// Take the user to safari to reset password maybe
NSLog(@"Login VC delegate - password reset!");
}
- (void)loginViewControllerDiDReceiveSignupRequest:(LoginViewController *)lvc
{
// Take the user to safari to open signup form maybe
NSLog(@"Login VC delegate - signup requested!");
}
- (BOOL)loginViewControllerShouldAllowAnonymousLogin:(LoginViewController *)lvc
{
return YES;
}
@end
userInfo
中。属性是
NSDictionary
无论你决定往里面塞什么。通知会影响性能,但我知道现在只有当观察者人数达到数百人时才会发生这种情况。尽管如此,这在我看来并不是最自然的,因为您有父对象(或多或少控制子对象的生命周期)向第三方对象询问子对象的更新。
关于ios - 将数据从子模态 VC 传递到父 View Controller 的最佳方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15814426/
是否有更快的算法来计算 (n! modulo m)。在每个乘法步骤都比减少更快。并且有没有比左右二元法更快的算法来计算 (a^p modulo m)。 这是我的代码:n!模数m ans=1 for(i
我有非常简单的代码循环遍历数组中的元素并检查是否index % 2 == 0。如果是这样,它应该改变颜色。 var e = document.getElementById("list").childN
让我简短一点。我正在计算 alert((Math.pow(7,35))%71) 但它给了我 61,而结果必须是 70。怎么了? 最佳答案 正如其他人之前提到的关于使用 Math.pow(7,35) 的
我试图弄清楚如何在汇编中计算模 10,所以我在 gcc 中编译了以下 c 代码,看看它想出了什么。 unsigned int i=999; unsigned int j=i%10; 令我惊讶的是我得到
例如使用以下输入: int num = -100 int divisor = 10 => -100 mod 10 = 0 (Edge-case: negative numbers as inpu
这个问题在这里已经有了答案: Random float number generation (14 个答案) 关闭 9 年前。 在 C++ 中,我希望得到一个随机 float 。据我所知,典型的随机
我试图找到潜在阶乘素数的除数(n!+-1 形式的数),因为我最近购买了 Skylake-X 工作站,我认为我可以使用 AVX512 指令提高一些速度。 算法简单,主要步骤是对同一个除数重复取模。主要是
我有一个保存角度(以度为单位)的变量,该角度可以是正值也可以是负值。我现在需要确保该数字仅在 0 到 360 之间。该数字是 double 。 执行此操作的好算法是什么?简单地执行角度 % 360 是
我有一个 UInt8 数组,我想计算 CheckSum8 模 256。如果字节总和小于 255,checkSum 函数返回正确的值。 例如 let bytes1 : [UInt8] = [1, 0xa
使用海湾合作委员会: printf("%i \n", -1 % (int)4); printf("%u \n", -1 % (unsigned int)4); 输出: -1 3 我可以跨平台依赖这种行
我无法理解代码中几行的含义。我最近开始学习 C++,并阅读了 Bjarne Stroustrup 的“编程:使用 C++ 的原理和实践”。第四章有个问题让我很困惑,所以我在网上搜索了一个解决方案以供引
我试图解决一个涉及大阶乘模质数的问题,并在另一个人的解决方案中发现了以下算法: long long factMod (long long n, long long p) { long long
我正在尝试计算 𝐹𝑛 模 𝑚,其中 𝑛 可能非常大:高达 10^18,𝐹𝑛 是第 n 个斐波那契数这是我的代码,它适用于小数字,但对于大数字,它会抛出 OutOfMemoryError 或
我有两个以 16 为模的循环整数,因此它们的值介于 0 和 15 之间。 我需要比较两个数字以确定 n_1 是否大于 n_0 n_1 > n_0 很明显,这个没有准确定义,所以我定义n_1如果小于前面
我一直在尝试使用 Java 处理一些更大的值,但遇到了一些我不理解的问题。出于某种原因,Java 似乎喜欢给我垃圾数据(尽管,我更可能告诉它给我垃圾数据) 这是一个片段,为清楚起见进行了编辑:
好吧,我今天做了一个小函数,它应该会生成一个随机字符串。 std::string randString(size_t length) { std::string randStr; fo
Ruby 的负数取模规则不明确。在 IRB 中: -7 % 3 == 2 应该是1!为什么? 最佳答案 因为 -7/3 在 Ruby 的整数除法语义下是 -3。 3*-3 是 -9,所以会留下 2
这个问题在这里已经有了答案: Calculating pow(a,b) mod n (14 个答案) 关闭 6 年前。 在 Javascript 中是否有获取大数模数的技巧。我用 modulo(7,
此代码使用公式 (a^x) % 101 检查值 a 是否唯一映射到值 1 到 100 local function f(a) found = {} bijective = true
在《Core Java Volume1》一书中有一条警告: CAUTION: The right-hand side argument of the shift operators is reduce
我是一名优秀的程序员,十分优秀!