NSURLConnection делегат

REVISED ...

Суть приложения - связь с сервером базы данных. Ответы от сервера на приложение все в формате XML. Есть несколько экранов. Например, на экране 1 перечислены сведения о пользователе, на экране 2 перечислены предыдущие сделки пользователя, разрешены новые сделки и т. Д.

Вот код из моего AppDelegate:

StartViewController *svc = [[StartViewController alloc] init];
TradeViewController *tvc = [[TradeViewController alloc] init];
CashViewController *cvc = [[CashViewController alloc] init];
ComViewController *covc = [[ComViewController alloc] init];
PrefsViewController *pvc = [[PrefsViewController alloc] init];

NSMutableArray *tabBarViewControllers = [[NSMutableArray alloc] initWithCapacity:5];
UITabBarController *tabBarController = [[UITabBarController alloc] init];

UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:svc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;

navigationController = [[UINavigationController alloc] initWithRootViewController:tvc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;

navigationController = [[UINavigationController alloc] initWithRootViewController:cvc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;

navigationController = [[UINavigationController alloc] initWithRootViewController:covc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;

navigationController = [[UINavigationController alloc] initWithRootViewController:pvc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;

[tabBarController setViewControllers:tabBarViewControllers];

[[self window] setRootViewController:tabBarController];

self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];

Пытаясь придерживаться стиля MVC, у меня есть одноэлементный класс, который выполняет всю «обработку».

Теперь пример того, как я врезаюсь в стену… пользователь может изменить свой адрес электронной почты на экране 5. Введите новый адрес электронной почты в текстовое поле и нажмите кнопку «Сохранить». Затем кнопка вызывает метод из класса singleton, который отправляет новый адрес электронной почты на сервер и (через URL) и получает XML-ответ, подтверждающий изменение.

Вот мои проблемы: 1. Я запускаю спиннер из контроллера представления, прежде чем сделать вызов метода синглтон-класса - но не зная, когда приложение отправляет / получает сервер, как я могу остановить спиннер в нужное время ? Я не могу этого из класса синглтон, я попробовал это. Из того, что я знаю, это должно быть из VC или есть способ изменить выход VC из моего синглтон-класса?

Синглтон-класс NSURLConnection обрабатывает ВСЕ мои сообщения. Все от простого изменения электронной почты до обновления таблиц транзакций. Это просто кажется мне неправильным и делает очень трудным отслеживать, кто что звонит. Опять же, я иду по моей интерпретации MVC. Я думаю, что было бы намного проще иметь NSURLConnection для каждого VC и выполнить некоторую обработку в этих классах. Однако это не будет MVC (ish).

В моем синглтон-классе есть около 100 переменных, массивов и т. Д., Которые я использую для присвоения значений всем моим ВК. Мне это тоже кажется неправильным, но я не могу придумать другого пути.

 sangony04 июн. 2012 г., 20:44
Jitendra - Для простоты, скажем, у меня есть 3 кнопки UIB, которые, при касании, имеют 3 уникальных URL для получения данных. Данные, которые используются для обновления 3 таблиц соответственно. Вы хотите, чтобы я опубликовал пример кода?
 Jitendra Singh04 июн. 2012 г., 20:29
Пожалуйста, напишите, как вы используете один и тот же объект подключения с несколькими запросами.

Ответы на вопрос(5)

Решение Вопроса

ading), какой URL-вызов выполняется?

Каждый из методов делегата (например,-connectionDidFinishLoading:) имеетconnectionараметр @, который сообщает, какое соединение отправило сообщение. Данное соединение может загружать только один URL-адрес за раз, поэтому между URL-адресами и соединениями существует однозначное соответствие.

Как я могу сказать за пределами "connectionDidFinishLoading", когда загрузка будет завершена?

Этот метод Говорит вы, когда соединение установлено. Вы должны хранить эту информацию где-нибудь, где она будет полезна для вашего приложения.

Обновить Исходя из того, что вы добавили, ваш класс «обработки» является моделью вашего приложения. Остальному приложению не нужно заботиться о том, чтобы каждая транзакция включала в себя сообщение на сервер - это только бизнес модели. Кроме того, нет причин, по которым модель должна представлять собой один объект (не говоря уже об одиночном объекте) - это может быть группа объектов, которые работают вместе.

Итак, у вас может быть класс (назовем его Processor), который представляет интерфейс приложения к модели (некоторые могут даже назвать это «контроллером модели»). Экземпляр Processor может создать локальную базу данных для хранения текущего локального состояния приложения. У вас также может быть класс Transaction, представляющий одну транзакцию с сервером. Транзакция может создать запрос, отправить его на сервер, получить ответ, обновить базу данных и сообщить процессору, что транзакция выполнена. Или, может быть, когда какая-то другая часть приложения (например, один из ваших контроллеров представления) просит обработчика обработать новую транзакцию, обработчик передает запрашивающий объект вместе с создаваемой им транзакцией, чтобы транзакция могла напрямую обновить запрашивающую сторону.

Трудно сказать, каков лучший план для вашего приложения, не зная, где вы планируете его принимать, но обычные правила верны:

разбить вашу проблему на части, которые легче решить

ограничить сферу ответственности каждого класса

если что-то кажется сложным, это, вероятно,

Разбивка вашей модели на несколько классов также облегчит тестирование. Вы можете представить, как легко было бы написать набор модульных тестов для класса Transaction. То же самое относится и к процессору - если серверные транзакции находятся в другом классе, проще проверить, что процессор работает правильно.

 Caleb04 июн. 2012 г., 20:57
@ sangony Правильно, но решение зависит от вашего кода. Как вы отслеживаете различные связи? Что в вашем приложении зависит от состояния соединений? Кто отвечает за эти вещи - делегат соединения или какой-то другой объект? Реализация делегатом вашего соединенияdidFinishетод @ может опубликовать уведомление, обновить запись в словаре, остановить сам счетчик или что-то еще. Тот факт, что каждое приложение должно делать что-то свое, является причиной того, что естьdidFinish Метод делегата в первую очередь.
 sangony04 июн. 2012 г., 20:47
Caleb - я знаю, что connectionDidFinishLoading выполняется только после завершения загрузки ... Мой вопрос касается возможности узнать за его пределами. Например, запустите счетчик после совершения вызова и узнайте, когда это будет сделано, чтобы остановить счетчик за пределами делегата.
 Caleb04 июн. 2012 г., 21:51
Может быть легче помочь, если вы расширите свой вопрос, чтобы объяснить, что выдействительн пытаюсь достичь. Почему вы используете один делегат для многих соединений? (Ничего плохого в этом нет, но расскажите нам, что происходит.) Как делегат связан с остальной частью программы? Как это
 sangony04 июн. 2012 г., 21:27
Прямо сейчас я пытаюсь написать общий код, чтобы обойти эту часть, но я думаю об использовании переменной класса (извините, если я здесь использую неправильный термин), чтобы отслеживать, кто делает вызов. Например, установите classVar на 1, если кнопка 1 нажата для обновления данных в таблице 1, установите classVar на 2, если ... В didFinish я думал об использовании classVar, чтобы увидеть, кто работает. Но, будучи новичком, это выглядит несколько неправильно для меня. Я также думал об установке переменных / словарей из didFinish ... но как я могу проверить это снаружи? Я думал о таймерах, но это также кажется неправильным.
 sangony04 июн. 2012 г., 23:00
Я разместил больше информации. Надеюсь, это не излишне

та, рассмотрите возможность использования глобального (ну, скажем, скорее переменную экземпляра) NSMutableDictionary, в котором вы храните данные в зависимости от того, какой NSURLConnection вызывается. Вы можете использовать, например, адрес в памяти соединений, преобразованных в строку NSString (что-то вроде

[NSString stringWithFormat:@"%p", connection]

должен сделать свое дело).

Также вconnectionDidFinishLoading: а такжеconnection:didFailLoadWithError: методы, удалите ключи, соответствующие NSURLConnections. Таким образом, вы можете сказать извне, завершено ли соединение: просто проверьте, есть ли оно в словаре или нет.

 sangony05 июн. 2012 г., 21:29
Спасибо за ответ H2CO3.

я бы предложил использовать ASIHttpRequest. Это позволит вам загружать файлы асинхронно, что означает, что ваш интерфейс не зависает во время процесса загрузки.

Если ты используешьASIHttpRequest, вы также можете установитьdidFinishSelector. Делая это, вы можете контролировать, какой метод вызывается после завершения загрузки определенного URL.

Посмотри на это

NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];

[request setDelegate:self];
[request startAsynchronous];
[request setDidFinishSelector:@selector(requestDone:)];

Затем

- (void)requestDone:(ASIHTTPRequest *)request
{
   // Use when fetching text data
   NSString *responseString = [request responseString];

   // Use when fetching binary data
   NSData *responseData = [request responseData];

   // If you want, you can get the url of the request like this
   NSURL *url = [request url];
}

Что касается второй части вашего вопроса, еслиrequestDone: метод не был вызван, вы знаете, что загрузка не завершена.

Если вы хотите сделать что-то более сложное с несколькими загрузками,ASIHttpRequest также предлагает функциональность очереди. ПосмотриВо.

 sangony04 июн. 2012 г., 20:52
У меня ноль опыта. с ASIHttpRequest ... он обрабатывает https?
 Bill Burgess04 июн. 2012 г., 20:53
Да, это так. Просто используйте https для URL, никаких проблем.
 Caleb04 июн. 2012 г., 21:04
Даже автор ASIHTTPRequest предлагает использовать что-то еще сейчас, когда он остановил дальнейшее развитие проекта.
 Josh Caswell04 июн. 2012 г., 20:48
NSURLConnection также работает асинхронно по умолчанию. Вот почему существуют методы делегатов; это обратные вызовы для получения результатов соединения.
 Bill Burgess04 июн. 2012 г., 20:54
Этот ответ, вероятно, подойдет для кого-то, кто не очень хорошо справляется с несколькими вызовами одного и того же метода делегата. Вы можете иметь разные методы возврата для каждого обратного вызова (returnDone :). Конечно, это сделает ваше приложение более тяжелым, значительно упростит поддержку и поддержит прямые обратные вызовы.

два свойства: NSInteger,tag и БУЛА,isFinished. Таким образом, вы можете#define теги для каждого отдельного запроса, а затем идентифицируйте их по тегу в ваших методах делегата. ВconnectionDidFin,ishLoading, вы можете установитьisFinished BOOL to YES, и затем вы можете проверить другие методы, если тогда соединение завершено.

Вот мой собственный подкласс NSURLConnection, TTURLConnection:

TTURLConnection.h:

#import <Foundation/Foundation.h>

@interface TTURLConnection : NSURLConnection <NSURLConnectionDelegate>

@property (nonatomic) NSInteger tag;
@property (nonatomic) BOOL isLocked;

- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:
    (BOOL)startImmediately tag:(NSInteger)tagParam;

@end

TTURLConnection.m:

#import "TTURLConnection.h"

@implementation TTURLConnection

@synthesize tag;

- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:
    (BOOL)startImmediately tag:(NSInteger)tagParam {
    self = [super initWithRequest:request delegate:delegate 
        startImmediately:startImmediately];

    if(self) {
        self.tag = tagParam;
    }

    return self;
}

@end
 sangony04 июн. 2012 г., 21:27
Как я могу проверить другие методы? Таймеры?
 sangony05 июн. 2012 г., 21:32
Спасибо за ответ, Рикей. Я собираюсь создать отдельный класс для NSURLConnection и посмотреть, как это работает.
 eric.mitchell05 июн. 2012 г., 22:43
Я опубликую свой собственный подкласс NSURLConnection
 eric.mitchell04 июн. 2012 г., 22:06
Ну, вы можете просто сохранить экземпляры каждого из NSURLConnections

Надеюсь, что это поможет вам

- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{   
    NSString *urlString = [[[connection originalRequest] URL] absoluteString];
    if ([urlString caseInsensitiveCompare:@"http://www.apple.com"] == NSOrderedSame) {
        //Do Task#1
    }
    else if ([urlString caseInsensitiveCompare:@"http://www.google.com"] == NSOrderedSame)
    {
        //Do Task#2
    }
}
 Jitendra Singh05 июн. 2012 г., 22:08
рад, я могу тебе помочь
 sangony05 июн. 2012 г., 21:30
Спасибо за ответ Джитендра. Ваше решение более продвинутое и более чистое, о чем я думал.

Ваш ответ на вопрос