it-swarm.com.ru

Как написать блок завершения Objective-C

Я нахожусь в ситуации, когда нужно вызвать метод класса из моего контроллера представления, заставить его сделать свое дело, но затем выполнить некоторые действия ТОЛЬКО ПОСЛЕ того, как метод класса завершил.

(Я думаю, что мне нужен блок завершения, но, пожалуйста, поправьте меня, если я ошибаюсь.)

Вот ситуация:

Я использую 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.
}];

Итак, что мне нужно выяснить, как сделать что-то вроде следующего: (Я уверен, что все, что связано с блоком, совершенно неправильно)

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

Пожалуйста, дайте мне знать, если вам нужна дополнительная информация или разъяснения.

Заранее спасибо!

--------- РЕДАКТИРОВАТЬ ОДИН ----------

Итак, несколько значительных единиц времени спустя, это то, что я придумал. Вся реализация могла бы быть лучше упрощена и делать намного меньше вызовов 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
36
Andrew

Я всегда использую это, когда я хочу написать блок:

http://fuckingblocksyntax.com

Или менее профанная версия:

http://goshdarnblocksyntax.com/

Для Свифта:

https://web.archive.org/web/20180527074325/http://fuckingswiftblocksyntax.com:80/

78
CW0007007

Я написал блок завершения для класса, который будет возвращать значения кубиков после их встряхивания:

  1. Определите typedef с помощью returnType (.h над @interface декларация)

    typedef void (^CompleteDiceRolling)(NSInteger diceValue);
    
  2. Определить @property для блока (.h)

    @property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;
    
  3. Определите метод с помощью finishBlock (.h)

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;
    
  4. Вставьте предыдущий определенный метод в .m файл и передайте finishBlock в @property определено ранее

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{
        self.completeDiceRolling = finishBlock;
    }
    
  5. Чтобы вызвать completionBlock, передайте ему предопределенный переменныйType (не забудьте проверить, существует ли completionBlock)

    if( self.completeDiceRolling ){
        self.completeDiceRolling(self.dieValue);
    }
    
32
Alex Cio

Относительно http://goshdarnblocksyntax.com/

Как локальная переменная :

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) {...};
12
carmen_munich

Вы определяете блок как пользовательский тип:

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

Если приходит время для запуска блока, просто вызову завершение блока () (где завершение блока - это имя вашей локальной копии блока).

11
DURGESH Chaurasiya