如何编写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
当我想写一个块时,我总是使用这个:
编辑
如果你正在写Swift,那么使用这个:
http://fuckingswiftblocksyntax.com
如果上述链接因为淫秽语言而无法打开,请使用这个链接。
我给一个类写了一个completionBlock,它会在返回一个骰子的值之后,
-
使用returnType定义typedef(在
@interface
声明之上的.h
)typedef void (^CompleteDiceRolling)(NSInteger diceValue);
-
为块(
.h
)定义@property
@property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;
-
用
finishBlock
(.h
)定义一个方法- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;
-
将以前定义的方法插入到
.m
文件中,@property
finishBlock
提交给之前定义的finishBlock
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{ self.completeDiceRolling = finishBlock; }
-
触发
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是块的本地副本的名称