полностью отредактированный ответ
Ваш вопрос приводит к нескольким решениям и стратегиям.
Первый: общие возможности для реализации двунаправленной передачи данных между двумя классами.
по нескольким протоколам: слабая упаковка, но это приводит к петлям импорта, которые раздражают. Я знаю, как решить петли импорта для определений классов (@class), но я не знаю, как решить эту проблему для протоколов
хиджра:
#import "B.h"
@protocol ADelegate
-(void) adelegate:(NSString*)data;
@end
@interface A : NSObject<BDelegate>
{
id<ADelegate> delegate;
}
@end
B.h:
#import "A.h"
@protocol BDelegate
-(void) bdelegate:(NSString*)data;
@end
@interface B : NSObject<ADelegate>
{
id<BDelegate> delegate;
}
@end
по одному протоколу: плотная упаковка :( но без петли импорта (это уродливый стиль работы)
хиджра:
//no import here needed
@protocol ADelegate
-(void) adelegate:(NSString*)data;
@end
@interface A : NSObject<BDelegate>
{
id<ADelegate> delegate;
}
@end
B.h:
#import "A.h"
@interface B : NSObject<ADelegate>
{
A* delegate;
}
@end
через канал / поток: двунаправленная передача данных должна выполняться с использованием канала (без буферизации) или потока (с буферизацией)
здесь я покажу вам небольшой и простой канал делегата, но также существует NSPipe / NSStream
DelegatePipe.h
@protocol DelegatePipeDelegate
- dataArrived:(NSString*)data;
@end
@interface DelegatePipe : NSObject {
NSMutableArray *delegates;
}
-(void)open:(id<DelegatePipeDelegate>)d;
-(void)close:(id<DelegatePipeDelegate>)d;
-(void)send:(NSString*)data;
@end
DelegatePipe.m
@implementation DelegatePipe
-(id)init
{
if(self = [super init])
{
delegates = [NSMutableArray array];
}
return self;
}
-(void) dealloc
{
[delegates release];
delegates = nil;
}
-(void) open:(id <DelegatePipeDelegate>)d
{
@synchronized(self)
{
if([delegates containsObject:d])
return;
//if([delegates count]>=2) //Pipe contains originally only 2 delegates. but a broadcaster is also nice ;)
// return;
[delegates addObject:d];
}
}
-(void) close:(id <DelegatePipeDelegate>)d
{
@synchronized(self)
{
[delegates removeObject:d];
}
}
-(void) send:(NSString *)data
{
@synchronized(self)
{
for(id<DelegatePipeDelegate> d in delegates)
[d dataArrived:data];
}
}
@end
Второй: КВО
KVO часто используется в шаблоне ModelViewController (MVC). Например: визуализировать данные в представлении. Состояние сетевого подключения в вашем случае является частью данных, а ваш loginipad - это представление ( и контроллер )
Authentificator.h
typedef enum eAuthState
{
NOT_CONNECTED = 0,
LOGIN_FAILED,
CONNECING,
CONNECTED
} AuthState;
@interface Authentificator : NSObject {
AuthState state;
}
@property (nonatomic, assign) AuthState state;
@end
Authentificator.m
...
-(void) doAuthWithUsername:(NSString*)name password:(NSString*)pw
{
self.state = CONNECING;
//do network-stuff
}
//delegate from network. here NSURLConnection
-(void) connectionDidFinishLoading:(NSURLConnection *)connection
{
//parse network-answer
BOOL success = YES;
if(success)
self.state = CONNECTED;
else
self.state = LOGIN_FAILED;
}
loginipad.h
@interface loginipad : UIViewController
{
Authentificator *auth;
}
@property (nonatomic, retain) Authentificator *auth;
@end
loginipad.m
@implementation loginipad
@synthesize auth;
//override setter for more comfortable use (add/removeObserver)
-(void) setAuth:(Authentificator *)a
{
@synchronized(auth)
{
[auth removeObserver:self forKeyPath:@"state"];
[auth release];
auth = a;
[auth retain];
[auth addObserver:self forKeyPath:@"state" options:0 context:nil];
}
}
-(IBAction) buttonClicked:(id)aSender
{
self.auth = [Authentificator sharedAuthentificator];
}
-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if(![object isKindOfClass:Authentificator.class])
return;
AuthState state = ((Authentificator*)object).state;
NSLog(@"curState: %i",state);
//do sth with state
}
- (void)dealloc {
self.auth = nil;
[super dealloc];
}