如何编写Objective-C完成块

And*_*rew 38 objective-c ios objective-c-blocks

我需要从我的视图控制器调用类方法,让它做它的事情,但然后只在类方法完成后执行一些操作.

(我认为我需要的是一个完成块,但如果我错了请纠正我.)

情况如下:

我正在使用Parse.com作为我的应用程序的后端.当用户注册帐户时,他们会在弹出窗口中输入他们的姓名,公司和其他信息,然后单击"提交".提交按钮链接到一个类方法(如下所示),该方法获取其PFUser对象和公司名称并创建一些数据库对象.函数完成后,使用委托解除弹出窗口.

问题是我需要按特定顺序创建这些对象,因为它们依赖于彼此对象的存在.问题是,在单击提交后立即调用解除弹出窗口的委托方法,因为它是堆栈中的下一个.

保存Parse对象时,会调用一个看起来像这样的方法:(这是我希望编写的,我认为可以解决我的问题)

[someParseObject saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
    // Code here runs AFTER the method completes.
    // This also happens on another thread which
    // I'd like to implement as well.
}];
Run Code Online (Sandbox Code Playgroud)

所以,我需要弄清楚如何做以下事情:(与块有关的一切都是完全错误的我确定)

SignUpViewController.m

myUserOrg *userOrg = [myUserOrg object]; // myUserOrg = Custom PFObject Subclass

// My method that takes in a user object and a string, creates
// the database objects in order.
[userOrg registerNewUserOrgWithUser:(PFUser*) andCompanyName:(NSString*) companyName withBlock(somethingHere)block {

    if(error) {
        NSLog(@"Unable to create org!");
    } else {
        NSLog(@"Created Org!");
        [self.delegate dismissSignupView];
}
Run Code Online (Sandbox Code Playgroud)

如果您需要其他信息或说明,请与我们联系.

先感谢您!

---------编辑一个----------

好吧,以后几个相当大的时间单位,这就是我想出来的.整个实现可以更好地简化,并减少api调用,但会对此有所帮助.其他几个明显的问题也是第一步.

方法调用:

[testOrg registerNewUserOrgWithUser:currentUser
         creatingOrgContactWithName:@"MyBigHappy Corp."
                          withBlock:^(BOOL succeeded, NSError *error) {
                              if (error) {
                                  NSLog(@"Not working");
                              } else {
                                  NSLog(@"Working!");
                              }
                          }];
Run Code Online (Sandbox Code Playgroud)

方法实施:

@implementation MYUserOrg

@dynamic orgContact;
@dynamic orgDisplayName;
@dynamic members;
@dynamic contacts;

+ (NSString *)parseClassName {
    return @"MYUserOrg";
}

dispatch_queue_t NewUserOrgRegistrationQueue;

-(void)registerNewUserOrgWithUser:(MYUser*)user
       creatingOrgContactWithName:(NSString*) orgContactName
                        withBlock:(MYBooleanResultBlock) block {

    NewUserOrgRegistrationQueue = dispatch_queue_create("com.myapp.initialOrgCreationQueue", NULL);

    dispatch_async(NewUserOrgRegistrationQueue, ^{

        NSMutableArray *errors = [[NSMutableArray alloc] init];

        // Initial org save to generate objectId
        NSError *orgSaveError = nil;
        [self save:&orgSaveError];

        if (orgSaveError) {
            [errors addObject:@"Initial Org save Failed"];
        }

        // Create and Relate Org Contact
        NSError *saveOrgContactError = nil;
        MYontact *orgContact = [MYContact object];
        [orgContact setContactType:MYContactTypeUserOrganization];
        [orgContact setDisplayName:orgContactName];
        [orgContact setParentOrg:self];
        [orgContact save:&saveOrgContactError];

        if (saveOrgContactError) {
            [errors addObject:@"Saving Org Contact Failed"];
        } else {
            // If Org contact saved, set it;
            [self setOrgContact:orgContact];
        }

        // Create amd Relate User Contact
        NSError *saveUserContactError = nil;
        MYContact *userContact = [MYContact object];
        [userContact setFirstName:user.firstName];
        [userContact setLastName:user.lastName];
        [userContact setContactType:MYcontactTypeUser];
        [userContact setParentOrg:self];
        [userContact save:&saveUserContactError];

        if (saveUserContactError) {
            [errors addObject:@"Saving user contact failed"];
        }

        NSError *saveUserError = nil;
        [user setParentOrg:self];
        [user setUserContact:userContact];
        [user save:&saveUserError];

        if (saveUserError) {
            [errors addObject:@"Saving User failed"];
        }

        // Return if block succeeded and any errors.
        NSError *error = nil;
        BOOL succeeded;
        if (errors.count > 0) {

            NSDictionary *userInfo = @{@"error" : errors};
            errors = [NSError errorWithDomain:@"MyAppErrorDomain"
                                         code:1
                                     userInfo:userInfo];
            succeeded = NO;
        } else {
            succeeded = YES;
        }
        block(succeeded, error);
    });

}

@end
Run Code Online (Sandbox Code Playgroud)

CW0*_*007 82

当我想写一个块时,我总是使用它:

http://fuckingblocksyntax.com

编辑

如果您正在编写Swift,请使用以下命令:

http://fuckingswiftblocksyntax.com

如果由于淫秽语言而导致上述链接无法打开,请使用此链接.

http://goshdarnblocksyntax.com/

  • 很棒的网址.当我回到家时,我将不得不打开它.我甚至不想在我的历史中尝试这样做.大声笑! (7认同)

Ale*_*Cio 34

我为一个类写了一个completionBlock,它将在它们被震动后返回一个骰子的值:

  1. 使用returnType定义typedef(.h上面的@interface声明)

    typedef void (^CompleteDiceRolling)(NSInteger diceValue);
    
    Run Code Online (Sandbox Code Playgroud)
  2. @property为块定义a (.h)

    @property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;
    
    Run Code Online (Sandbox Code Playgroud)
  3. finishBlock(.h)定义方法

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;
    
    Run Code Online (Sandbox Code Playgroud)
  4. .m文件中插入先前定义的方法并提交finishBlock@property之前定义的

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{
        self.completeDiceRolling = finishBlock;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  5. 触发completionBlock传递预定义的variableType给它(不要忘记检查是否completionBlock存在)

    if( self.completeDiceRolling ){
        self.completeDiceRolling(self.dieValue);
    }
    
    Run Code Online (Sandbox Code Playgroud)


DUR*_*iya 13

您将块定义为自定义类型:

typedef void (^ButtonCompletionBlock)(int buttonIndex);
Run Code Online (Sandbox Code Playgroud)

然后将它用作方法的参数:

+ (SomeButtonView*)buttonViewWithTitle:(NSString *)title 
                      cancelAction:(ButtonCompletionBlock)cancelBlock
                  completionAction:(ButtonCompletionBlock)completionBlock
Run Code Online (Sandbox Code Playgroud)

在代码中调用它时,它就像任何其他块一样:

[SomeButtonView buttonViewWithTitle:@"Title"
                   cancelAction:^(int buttonIndex) {
                         NSLog(@"User cancelled");
               } 
                 completionAction:^(int buttonIndex) {
                         NSLog(@"User tapped index %i", buttonIndex);
               }];
Run Code Online (Sandbox Code Playgroud)

如果需要触发块,只需调用completionBlock()(其中completionBlock是块的本地副本的名称)


car*_*ich 12

关于http://goshdarnblocksyntax.com/

作为局部变量:

returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};
Run Code Online (Sandbox Code Playgroud)

作为财产:

@property (nonatomic, copy) returnType (^blockName)(parameterTypes);
Run Code Online (Sandbox Code Playgroud)

作为方法参数:

- (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName;
Run Code Online (Sandbox Code Playgroud)

作为方法调用参数:

[someObject someMethodThatTakesABlock:^returnType (parameters) {...}];
Run Code Online (Sandbox Code Playgroud)

作为typedef:

typedef returnType (^TypeName)(parameterTypes);
TypeName blockName = ^returnType(parameters) {...};
Run Code Online (Sandbox Code Playgroud)


Sun*_*rge 6

简单完成块

    // Completion block method
    -(void)myMethod:(void (^)(void))completion {
        NSLog(@"iPhone");
        completion();
        NSLog(@"iPod");
    }

   // Calling completion block method
    - (void)viewDidLoad {
        [super viewDidLoad];

        [self myMethod:^{
           NSLog(@"iPad");
        }];
    }

  // output
  iPhone
  iPad
  iPod
Run Code Online (Sandbox Code Playgroud)