Синхронные вызовы AFNetworking (например, / непохожий)

Мне нужно реализовать аналогичную функциональность в приложении. Все вызовы API выполняются с помощью AFNetworking и обработчиков ошибок / ошибок ( блоки ios ).

Проблема заключается в том, что когда пользователь делает много кликов по кнопке в течение короткого периода времени, часть запроса принимается сервером в неправильной последовательности, а затем все становится неправильным. Например, происходит двойное подобное или двойное.

Есть ли способ отправить все запросы через AFNetworking синхронно?

Если нет наилучшей практики для разработки подобных запросов API?

4 Solutions collect form web for “Синхронные вызовы AFNetworking (например, / непохожий)”

Отключение кнопки (как и предложения комментариев) не плохая идея, особенно если вы выбросите счетчик или изменение пользовательского интерфейса, чтобы пользователь знал, что вы обрабатываете изменение.

В противном случае вы можете просто ограничить вызовы API только для того, чтобы один выход был отключен. Если пользователь нажимает кнопку, запустите вызов и измените значение boolean или tracking. Если они снова нажмете кнопку, удерживайте ее до состояния изменения локально, но подождите, пока первый обратный вызов не войдет. Если они продолжают нажимать кнопку, просто отслеживайте их изменения, но никогда не запускайте ответ, пока не получите уведомление о завершении вызова API (вероятно, с тайм-аутом 10-30 секунд в случае его отказа).

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

Я бы даже задерживал первый вызов на 3 или около того секунд, и каждый раз, когда они нажимают кнопку в течение этого периода времени, сбросьте таймер. Таким образом, вы не будете увольнять случайные вызовы без необходимости (подумайте об этом как о сохранении coredata, если вы знаете, что может быть несколько изменений, которые вы делаете для них до сохранения).

Проблема с синхронизированной очередью заключается в том, что если они нажимают кнопку пять раз (или более), у нее будет довольно длинная очередь ожидания. Тогда что, если они закрывают приложение и ваши звонки не отправляются? Тогда ваша база данных имеет (потенциально) неточную информацию.

Самый простой способ сделать это, IMHO, – отключить кнопку перед отправкой запроса. После того, как вы ответите на обратный вызов успеха или отказа, вы можете внести изменения в пользовательский интерфейс, чтобы дать обратную связь, что пользователю понравилось то, что ему понравилось, и вы можете снова включить кнопку.

Мне кажется, что у вас есть два варианта:

  1. Простое решение – дать пользователю положительную обратную связь по интерфейсу, нажав кнопку, например, предложенную Moxy (т.е. UX, которая предотвращает «эй», я должен снова нажать на нее, потому что это не выглядит так, как будто я получил это в прошлый раз "), но затем отключите дальнейшее взаимодействие с этой кнопкой до тех пор, пока предыдущее действие не будет завершено. Или,

  2. Более сложное решение заключается в том, чтобы сразу отразить подобное / в отличие от изменения в пользовательском интерфейсе и асинхронно управлять сетевыми запросами (а не только по потокам, но и логически). Если вы это сделаете, вы захотите сохранить weak отношение к предыдущей операции типа «как в отличие от операции» (и очереди операций отлично подходят для этой проблемы) для каждой кнопки типа «like / unlike», например, когда вы делаете новый похожий / непохожий запрос , вы можете сделать его работу зависимой от предыдущей (так они происходят последовательно) и / или отменить предыдущий.

Операции AFNetworking вернутся к событию завершения, если вы поместите их в очередь операций. Проверьте это сообщение в блоге: http://www.dribin.org/dave/blog/archives/2009/05/05/concurrent_operations/

В вашем случае вам необходимо создать подкласс NSOperation, аналогичный следующему:

 //Header file @interface LikeOperation : NSOperation @property (readonly, nonatomic) BOOL isExecuting; @property (readonly, nonatomic) BOOL isFinished; + (instancetype)operationWithCompletionSuccessBlock:(void(^)())onSuccess failure:(void(^)(NSError *anError))onError; @end //Implementation file #import "LikeOperation.h" typedef void (^SuccessBlock)(); typedef void (^ErrorBlock)(NSError*); @interface LikeOperation() @property (readwrite, copy, nonatomic) SuccessBlock onSuccess; @property (readwrite, copy, nonatomic) ErrorBlock onError; @property (assign, nonatomic) BOOL isExecuting; @property (assign, nonatomic) BOOL isFinished; @property (readwrite, strong, nonatomic) AFHTTPClient *client; @end @implementation LikeOperation static NSString *const kBaseURLString = @"www.example.org"; static NSString *const kURLString = @"www.example.org/like"; - (id)initWithCompletionSuccessBlock:(void (^)())onSuccess failure:(void (^)(NSError *))onError { self = [super init]; if (self) { self.onSuccess = onSuccess; self.onError = onError; } return self; } + (instancetype)operationWithCompletionSuccessBlock:(void (^)())onSuccess failure:(void (^)(NSError *))onError { return [[self alloc] initWithCompletionSuccessBlock:onSuccess failure:onError]; } - (void)start { if (![NSThread isMainThread]) { [self performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:NO]; return; } NSString *key = NSStringFromSelector(@selector(isExecuting)); [self willChangeValueForKey:key]; self.isExecuting = YES; [self didChangeValueForKey:key]; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSURL *baseURL = [NSURL URLWithString:kBaseURLString]; self.client = [AFHTTPClient clientWithBaseURL:baseURL]; }); NSURL *url = [NSURL URLWithString:kURLString]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; AFHTTPRequestOperation *operation = [self.client HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { self.onSuccess(); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { self.onError(error); }]; [operation start]; } - (void)finish { NSString *isExecutingKey = NSStringFromSelector(@selector(isExecuting)); NSString *isFinishedKey = NSStringFromSelector(@selector(isFinished)); [self willChangeValueForKey:isExecutingKey]; [self willChangeValueForKey:isFinishedKey]; self.isExecuting = NO; self.isFinished = YES; [self didChangeValueForKey:isExecutingKey]; [self didChangeValueForKey:isFinishedKey]; } @end 

После этого вы можете безопасно выполнить указанную операцию в NSOperationQueue и установить максимальный параллельный maxConcurrentOperationCount равным 1, чтобы операции выполнялись один за другим. Вы также можете изучить зависимости nsoperation, как описано в http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html

 //Code to initialize the operation queue self.queue = [[NSOperationQueue alloc] init]; self.queue.name = @"Post data queue"; self.queue.maxConcurrentOperationCount = 1; //perform like - (void)like { NSOperation *likeOperation = [LikeOperation operationWithCompletionSuccessBlock:^{ } failure:^(NSError *anError) { }]; [self.queue addOperation:likeOperation]; } 
  • Добавление NSData в NSDirectory (JSON) получение недопустимого типа в ошибке JSON write (NSConcreteMutableData)
  • Использование AFJSONRequestOperation
  • Программно нажмите кнопку html из NSURLRequest
  • Выполняет ли AFHTTPRequestOperationManager запросы на операциюQueue?
  • Нежелательное кэширование запроса GET с использованием AFNetworking
  • AFNetworking сбоев, загрузка больших файлов 200MB +
  • AFNetworking 2.x Запрос POST с корпусом xml
  • iOS - Можно ли кэшировать ответный HTTP-ответ?
  • AFNetworking несовместим с iOS 4.3
  • ограничение установки одновременных задач в AFNetworking 2 с запуском AFHTTPSessionManager
  • Аутентификация AFNetworking с веб-службой
  • Загрузка видео с использованием AFNetworking вызывает проблемы с памятью
  • PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.