6

我正在尝试通过其他以及 Apple 的示例。我迷路了。

我有一个单例类,用于处理我的用户登录(挑战网络服务器等)。

我想创建一个可以调用的块,传入用户名/密码。该块将执行 Web 服务调用,然后返回是否成功。

到目前为止,这是我设法开始的工作:

我的单例类如下所示:

。H

typedef void (^AMLoginBlock)(NSString *userName, NSString *password);

@interface AuthManager : NSObject
+ (id)sharedManager;

+ (bool)loginUserWithBlock:(AMLoginBlock)block;

@end

.m

@implementation AuthManager

+ (id)sharedManager
{
    static dispatch_once_t pred = 0;
    __strong static id _sharedObject = nil;
    dispatch_once(&pred, ^{
        _sharedObject = [[self alloc] init]; // or some other init method
    });
    return _sharedObject;
}

+ (bool)loginUserWithBlock:(AMLoginBlock)block {
    NSLog(@"im printing from AM");
    return true;
}

@end

然后我像这样调用该方法:

bool rtn = [AuthManager loginUserWithBlock:^(NSString *userName, NSString *password) {
        NSLog(@"im here in the block LVC.");
    }];

我的问题是三个部分:

  1. 如何为类似于UIView animation...块的块编写完成处理程序。

  2. 从基于块的实现中执行这些 Web 服务调用是个好主意吗?

  3. 我应该像这样声明块方法:

    - (bool)loginUserWithBlock:(AMLoginBlock)block;

而不是使用,+(bool)loginUser..因为它在单例类中。不确定这是否会导致创建单例的多个实例。

我的目标是能够像你一样调用这个块[UIView animation..]。所以我可以简单地做:

[AuthManager loginUserWithUsername:foo
                          password:bar1
                        completion:^(BOOL finished) {
                            if (finished)
                                //push new view controller.
                            else
                                //spit out error
                   }];
4

1 回答 1

6

完成处理程序

您需要将完成块复制到 iVar 类:

@property (nonatomic, copy) void (^completionHandler)(bool *);

因为您正在保存块,所以您需要有一个非类方法来获取块(请参阅以下内容以了解如何在不违反单例的情况下执行此操作)。您的方法的一个示例可能是:

- (void)loginUserWithUsername:(NSString *)username 
                     password:(NSString *)password 
                   completion:(void(^)(bool *finished))completionBlock
{
    // Copy the blocks to use later
    self.completionHandler = completionBlock;

    // Run code
    [self doOtherThings];
}

然后,当您的登录代码完成工作时,您可以调用该块 - 这里我将 self.error, a 传递bool给该块:

- (void)finishThingsUp
{
    // We are done with all that hard work. Lets call the block!
    self.completionHandler(self.error);

    // Clean up the blocks
    self.completionHandler = nil;
}

好主意

嗯,这是一个哲学问题,但我会这样说:Objective-C 中的块允许您编写执行单个任务的代码并轻松地将其集成到许多程序中。如果您选择不在您的登录代码中使用完成处理程序,您将需要您的登录代码:

  • 要求使用它的类实现协议(如在 a 中LoginDelegate
  • 使用其他一些系统来通知您的代码,例如键值观察或通知
  • 硬编码它只适用于一种类型的调用类

上述任何一种方法都可以,我觉得基于块的回调系统是最简单和最灵活的。它允许您只使用您的类而不用担心额外的基础设施(设置通知、符合协议等),同时仍然允许您在其他类或程序中重用它。

辛格尔顿

Objective-C 中以 a 开头的+方法是类方法。您不能使用类方法来操作 iVar,因为谁将拥有这些数据?

您可以做的是拥有一个始终返回该类的相同实例的类方法,允许您拥有一个可以拥有数据的对象,但避免拥有多个数据。

这个优秀的 Stack Overflow 答案有示例代码

祝你好运!

于 2013-01-11T16:07:37.180 回答