编写我自己的块方法

ran*_*dom 6 singleton objective-c objective-c-blocks

我试图通过其他以及Apple的例子.我迷路了.

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

我想创建一个我可以调用的块,传入用户名/密码.该块将执行Web服务调用,如果成功则返回.

这是我到目前为止工作的目标:

我的单例类看起来像这样:

.H

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

@interface AuthManager : NSObject
+ (id)sharedManager;

+ (bool)loginUserWithBlock:(AMLoginBlock)block;

@end
Run Code Online (Sandbox Code Playgroud)

.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
Run Code Online (Sandbox Code Playgroud)

然后我调用这样的方法:

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

我的问题分为三部分:

  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
                   }];
Run Code Online (Sandbox Code Playgroud)

red*_*ulb 6

完成处理程序

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

@property (nonatomic, copy) void (^completionHandler)(bool *);
Run Code Online (Sandbox Code Playgroud)

因为要保存块,所以需要使用非类方法来获取块(请参阅以下有关如何执行此操作而不违反单例).您的方法的一个示例可能是:

- (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];
}
Run Code Online (Sandbox Code Playgroud)

然后当你的登录代码完成它的工作时,你可以调用块 - 这里我将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;
}
Run Code Online (Sandbox Code Playgroud)

好主意

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

  • 要求使用它的类实现协议(如在a中LoginDelegate)
  • 使用其他一些通知您的代码的系统,例如Key Value observing或Notifications
  • 硬代码只适用于一种类型的调用类

任何上述方法都很好,我觉得基于块的回叫系统是最简单和最灵活的.它允许您只使用您的类而无需担心其他基础结构(设置通知,符合协议等),同时仍允许您在其他类或程序中重用它.

Singelton

+在Objective-C中以a开头的方法是类方法.你不能使用类方法来操纵iVars,因为谁拥有这些数据?

你可以做的是有一个类方法,它始终返回该类的同一个实例,允许你拥有一个可以拥有数据的对象,但是避免使用多个对象.

这个出色的Stack Overflow答案包含示例代码.

祝好运!