iphone SDK: клиент для сокетов ... как мне обрабатывать делегаты получения данных в разных представлениях / классах? - PullRequest
1 голос
/ 24 марта 2009

Я пишу контроллер для аудиосервера на iPhone. Каждое «представление» обычно должно получать данные из сокета TCP / IP в качестве клиента. У меня есть сокеты, работающие от одного класса, использующего класс AsyncSocket . (который после попытки заставить клиента сокетов работать дольше, чем я хотел бы признать, является очень впечатляющим и полезным классом) .. Для этого требуется написать функции делегата для получения данных ...

- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag

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

Мой вопрос: когда я перехожу от просмотра к просмотру, каков наилучший способ по-прежнему отправлять и получать данные? Нужно ли создавать новый сокет для каждого класса представления? (кажется, немного чрезмерно) Как-то снова связать делегат локального получателя?

Кажется, я не могу придумать «правильный» способ заставить это работать за пределами 1 класса, и в интернете не так много информации об общении с сокет-клиентами на iphone.

Ответы [ 2 ]

2 голосов
/ 24 марта 2009

Звучит так, как будто вы хотите получить методы делегата несколькими объектами, верно? В Mac OS X решение состоит в том, чтобы использовать систему уведомлений. Я не смотрел на класс AsyncSocket, но похоже, что он поддерживает только делегата из коробки.

Уведомления хороши тем, что позволяют объекту передавать информацию любым другим объектам, которые заинтересованы в ее получении. Объекты регистрируются в центре уведомлений, чтобы получать уведомления при публикации определенных уведомлений. Вы можете очень легко добавить эту возможность, реализовав свой собственный класс для переноса AsyncSocket.

Вот что ты будешь делать. Вы бы написали свой собственный класс с AsyncSocket в качестве переменной экземпляра. Вы должны установить этот класс в качестве делегата для объекта AsyncSocket. Затем, когда будут вызваны методы делегата, вы отправите уведомления на NSNotificationCenter. Вероятно, вам потребуется вставить параметры из методов делегата в словарь userInfo уведомления.

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

Хватит разговоров; вот какой-то код:

extern NSString *const AsyncSocketDidReadData;

@interface MySocketWrapper : NSObject { // give this class a better name ;-)
    AsyncSocket *socket;
}

@property (nonatomic, readonly) socket;

@end

В файле .m:

NSString *const AsyncSocketDidReadData = @"AsyncSocketDidReadData";

@implementation MySocketWrapper

@synthesize socket;

- (id)init {
    if (![super init]) return nil;

    socket = [[AsyncSocket alloc] init]; // initialize this however you want
    [socket setDelegate:self];
    return self;
}

- (void)onSocket:(AsyncSocket *)aSocket didReadData:(NSData *)data withTag:(long)tag {
    NSDictionary *userInfo = 
         [NSDictionary dictionaryWithObjectsAndKeys:
          data, @"data",
          [NSNumber numberWithLong:tag], @"tag",
          nil];
    [[NSNotificationCenter defaultCenter] postNotificationName:AsyncSocketDidReadData object:self.socket userInfo:userInfo];
}

@end

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

- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)bundle {
    if (![super initWithNibName:nibName bundle:bundle]) return nil;

    // Do any initalization you need here

    // Note that if you specify 'nil' for object, you'll be sent notifications for every MySocketWrapper object.
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(asyncSocketDidReadData:) notification:AsyncSocketDidReadData object:nil]; 

    return self;
}

- (void)asyncSocketDidReadData:(NSNotification *)notification {
    AsyncSocket *socket = [[notification object] socket];
    NSData *theData = [[notification userInfo] objectForKey:@"data"];
    long tag = [[[notification userInfo] objectForKey:@"tag"] longValue];

    // Do what you want with the data here
}

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

0 голосов
/ 21 июля 2009

Предыдущий ответ великолепен, но в уведомлении контроллера view должно быть указано «имя:».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...