如何编写Objective-C完成块

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

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

情况如下:

我使用Parse.com为我的应用程序后端。 当用户注册一个帐户时,他们在popup框中input他们的姓名,公司和其他信息,然后点击提交。 提交button链接到一个类方法(如下所示),它接收PFUser对象和公司名称并创build一些数据库对象。 函数完成之后,popup窗口将使用委托来解除。

问题是我需要创build这些对象以特定的顺序发生,因为它们依赖eachothers objectId的存在。 问题是,点击提交之后立即调用closurespopup窗口的委托方法,因为它是堆栈中的下一个。

当保存一个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. }]; 

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

 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]; } 

请让我知道,如果你需要更多的信息或澄清。

先谢谢你!

———编辑一

好了,所以后来几个相当大的时间单位,这就是我想出的。 整个实施可以更好地简化,使得更less的API调用,但将在这个工作。 其他几个明显的问题,但是第一步。

方法调用:

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

方法实施:

 @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 

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

http://fuckingblocksyntax.com

编辑

如果你正在写Swift,那么使用这个:

http://fuckingswiftblocksyntax.com

如果上述链接因为淫秽语言而无法打开,请使用这个链接。

http://goshdarnblocksyntax.com/

我给一个类写了一个completionBlock,它会在返回一个骰子的值之后,

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

     typedef void (^CompleteDiceRolling)(NSInteger diceValue); 
  2. 为块( .h )定义@property

     @property (copy, nonatomic) CompleteDiceRolling completeDiceRolling; 
  3. finishBlock.h )定义一个方法

     - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock; 
  4. 将以前定义的方法插入到.m文件中, @property finishBlock提交给之前定义的finishBlock

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

     if( self.completeDiceRolling ){ self.completeDiceRolling(self.dieValue); } 

关于http://goshdarnblocksyntax.com/

作为一个局部variables

 returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...}; 

作为财产

 @property (nonatomic, copy) returnType (^blockName)(parameterTypes); 

作为方法参数

 - (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName; 

作为一个方法调用参数

 [someObject someMethodThatTakesABlock:^returnType (parameters) {...}]; 

作为一个typedef

 typedef returnType (^TypeName)(parameterTypes); TypeName blockName = ^returnType(parameters) {...}; 

您将块定义为自定义types:

 typedef void (^ButtonCompletionBlock)(int buttonIndex); 

然后用它作为一个方法的参数:

 + (SomeButtonView*)buttonViewWithTitle:(NSString *)title cancelAction:(ButtonCompletionBlock)cancelBlock completionAction:(ButtonCompletionBlock)completionBlock 

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

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

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