iOS 5 NSURLConnection - создание нескольких соединений с обратной связью пользовательского интерфейса - PullRequest
2 голосов
/ 05 марта 2012

В настоящее время я разрабатываю приложение для iOS 5 для iPhone, в котором для обновления данных будет использоваться веб-служба .NET RESTful.Когда приложение изначально установлено, оно подключается к WS для загрузки всех данных в формате JSON.После этого он будет выполнять только обновления.WS предоставляет метод POST для каждой таблицы, как GetAllTableRecords () и GetLastUpdatedTableRecords ().

Я использую iOS 5, и у меня есть сериализация / десериализация NSURLConnection и JSON, работающая правильно с нативными библиотеками.Каждый вызов метода WS POST в настоящее время находится в своем собственном классе Obj-C со всеми методами делегата.Кроме того, каждый класс обрабатывает вставки и обновления локального хранилища данных.

Каждое NSURLConnection является асинхронным, и все вызовы WS обрабатываются событиями кнопок от контроллеров представления.

Мои вопросы:

  1. Это правильная установка с точки зрения инкапсуляции и повторного использования кода?
  2. Как мне обрабатывать несколько вызовов WS, сохраняя пользователячерез пользовательский интерфейс?

В настоящее время есть две таблицы для загрузки.Это означает, что приложение будет вызывать WS дважды, чтобы получить исходные данные, и дважды снова при каждом обновлении.Я знаю, что, поскольку каждое NSURLConnection является асинхронным, соединение сделает запрос, но пользовательский интерфейс продолжит работу, пока делегат обрабатывает загрузку данных.Я провел некоторое исследование GCD и NSOperation / Queue, но я не знаю достаточно ни того, ни другого, чтобы кодировать решение или знать, является ли это даже правильным решением.

Любое понимание было бы наиболее полезным!

Редактировать # 1 : А как насчет предоставления обновлений в реальном времени обратно в пользовательский интерфейс?Приложение Mint делает нечто подобное при обновлении транзакций и учетных записей.У них есть небольшая строка состояния, которая выскакивает внизу во время выполнения запросов.

Edit # 2: Хорошо, я думаю, что я добился определенного прогресса.Мы используем Story Boards, и точкой входа является View / Controller входа в систему.Когда кнопка входа в систему нажата, NSURLConnection сделан к веб-службе.Если код состояния ответа 200 в соединении connectionDidFinishLoading: (NSURLConnection *), выполняется переход к представлению синхронизации данных.Цель этого представления - либо инициализировать, либо обновить базу данных, предоставляя пользователю обратную связь.Для обновления или инициализации требуется два дополнительных вызова веб-службы.

Вот мой DataSyncView.m :

@synthesize pvStatus, lbStatus;

// pvStatus = progress indicator
// lbStatus = label

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [self StartDataSync];
}

- (void)StartDataSync
{    
    [lbStatus setText:@"Syncing data..."];
    [pvStatus setProgress:0.0f];

    // TODO: Determine if database is popuplated
    [self PerformInitialSync];  

    // Next screen
    [self performSegueWithIdentifier:@"SegueFromSync" sender:self];
}

// Populates data store will data from web service
- (void)PerformInitialSync
{
    // Kicks off a series of synchronous requests
    [self DownloadAllEmployeeDataA];
}

- (void)DownloadAllDataA
{
    // Dictonary holds POST values
    NSMutableDictionary *reqDic = [NSMutableDictionary dictionary];

    // Populate POST key/value pairs
    [reqDic setObject:passWord forKey:@"Password"];
    [reqDic setObject:userName forKey:@"UserName"];

    NSError *error = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:reqDic options:NSJSONWritingPrettyPrinted error:&error];

    // Convert dictionary to JSON
    NSString *requestJSON = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];    

    // Declare Webservice URL, request, and return data
    NSURL *url = [[NSURL alloc] initWithString:@"http://wsurl/getalla"];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
    NSData *postData = [NSData dataWithBytes:[requestJSON UTF8String] length:[requestJSON length]];

    // Build the request
    [request setHTTPMethod:@"POST"];
    [request setValue:[NSString stringWithFormat:@"%d", [postData length]] forHTTPHeaderField:@"Content-Length"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [request setHTTPBody:postData];
    [request setCachePolicy:NSURLRequestUseProtocolCachePolicy];
    [request setTimeoutInterval:60.0];

    NSURLResponse *response;

    [lbStatus setText:@"Downloading employee data..."];
    [pvStatus setProgress:0.1f];

    // Make the response
    NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

    // If return data received
    if(returnData)
    {
        // Get the response and check the code
        NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
        int code = [httpResponse statusCode];

        // Check to make sure successful code
        if (code == 200) 
        {
            // Convert JSON objects to Core Data Entity
            // Update UIProgressView and Label

            // Call next WS call
            [self DownloadAllEmployeeDataA];
        }
    }
}

- (void)DownloadAllDataB
{                
    // Same code as above but with different URL and entity
}

Моя проблема, с которой я сталкиваюсь, заключается в следующем: UIProgressView иЯрлык не обновляется, так как звонки сделаны.Как я уже говорил ранее, я даже не знаю, является ли это лучшим способом сделать эти звонки.Не похоже, что я блокирую основной поток, но я могу ошибаться.Опять же, я задам вопрос: каков наилучший способ сделать несколько вызовов URL, сохраняя пользовательский интерфейс в курсе прогресса?Спасибо !!!

1 Ответ

2 голосов
/ 09 марта 2012
// Make the response
    NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

В своем вопросе вы сказали, что сделали асинхронную загрузку URL-запроса.Но в приведенной выше строке кода вы делаете синхронный запрос?

Это правильная установка с точки зрения инкапсуляции и повторного использования кода?

  • Глядя наваш код вы не придерживаетесь MVC.Ваш View Controller не должен управлять загрузкой URL-соединений.Вы можете создать класс, который делает это, и с помощью делегатов информировать контроллер представления о том, загружены или не загружены данные и т. Д.проинформированы через пользовательский интерфейс?
    • Если вы хотите создать параллельные соединения URL, используйте NSOperation и NSOperationQueue.Попробуйте избегать GCD (см. Сессию WWDC 2010 208).

    Моя проблема, с которой я сталкиваюсь, заключается в следующем: UIProgressView и Label не обновляются во время выполнения вызовов.

    • Вы делаете синхронный URL-запрос в главном потоке.Согласно вашему коду UIProgressView не должен обновляться.

    См. Руководство по программированию системы загрузки URL

    Другой комментарий, который у меня есть, - это имена ваших методов, начинайте имя метода смаленькая буква.Остальное выглядит хорошо. Руководство по кодированию для какао

...