2011-11-03 65 views
1

第一篇文章在這裏,所以我希望它足夠詳細。充當NSUrlConnection委託的NSObject實例似乎不是孤立的

在開發iPhone應用程序時,我遇到了一些奇怪的行爲。我的「WebserviceConnection」類的某個實例的成員變量似乎獲得了我分配給另一個相同類的實例的值。

對於插圖:這是我的日誌摘錄。我假設 0x000000是一個實例ID。第四個迴應應該是「< - :1」。

2011-11-03 16:25:13.227 Dashboard[540:707] ->: 1, <WebserviceConnection: 0x11f950> 
2011-11-03 16:25:13.256 Dashboard[540:707] ->: 0, <WebserviceConnection: 0x323db0> 
2011-11-03 16:25:15.318 Dashboard[540:707] <-: 0, <WebserviceConnection: 0x323db0> 
2011-11-03 16:25:15.325 Dashboard[540:707] <-: 0, <WebserviceConnection: 0x11f950> 

該類是一個NSUrlConnection委託,當兩個連接同時打開時,它表現出這種行爲。

這個類:WebserviceConnection.h

(該ConnectionType是一個枚舉)

#import "WebserviceConnection.h" 
#import "WebserviceUtility.h" 

@implementation WebserviceConnection 

BOOL isCanceled; 
NSDictionary *result; 
ConnectionType connectionType; 
id <WebserviceConnectionDelegate> delegate; 

- (id)initWithDelegate:(id)webServiceDelegate connectionType:(ConnectionType) type { 
    delegate = webServiceDelegate; 
    connectionType = type; 
    isCanceled = NO; 
    NSLog(@"->: %i, %@", connectionType, self); 
    return self; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 

    switch (connectionType) { 
     case GetAllAlerts: 
      result = [WebserviceUtility getJsonFromData:data]; 
      break; 
     case GetServerAlerts: 
      result = [WebserviceUtility getJsonFromData:data]; 
      break; 
     case GetServers: 
      result = [WebserviceUtility getJsonFromData:data]; 
      break; 
     default: 
      result = nil; 
      break; 
    } 
} 

- (void)displayErrorAlert { 
    UIAlertView *errorMessage = [[UIAlertView alloc] initWithTitle:@"Fout" message:@"Verbinding met webservice niet mogelijk" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil]; 
    [errorMessage show]; 
} 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 
    if(!isCanceled) { 
     @try { 
      [delegate connection:connection ofType:connectionType didFinishWithError: [NSDictionary dictionaryWithObject:@"error" forKey:@"WebserverConnectionFailed"]]; 
     } 
     @catch (NSException *e) {} 
     @finally {} 
     [self displayErrorAlert]; 
    } 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 
    NSLog(@"<-: %i, %@", connectionType, self); 
    if(!isCanceled) { 
     [delegate connection:connection ofType:connectionType didFinishWithResult:result]; 
    } 
} 

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { 
    NSURLCredential *credential = [WebserviceUtility getCredentials]; 
    if ([challenge previousFailureCount] == 0) { 
     [[challenge sender] useCredential:credential 
       forAuthenticationChallenge:challenge]; 
    } 
    else { 
     [delegate connection:connection ofType:connectionType didFinishWithError: [NSDictionary dictionaryWithObject:@"error" forKey:@"WebserverConnectionFailed"]]; 
     [self displayErrorAlert]; 

    } 
} 

- (void)delegateDidDealloc { 
    NSLog(@"!!: %i, %@", connectionType, self); 
    isCanceled = YES; 
} 

@end 

像這樣來使用:

- (void) getAllAlerts { 
    NSURLRequest *request = [WebserviceUtility getRequestForPath:@"/dashboard/DashboardAppleConnector.asmx/GetActiveAlerts"]; 
    webserviceConnection = [[WebserviceConnection alloc] initWithDelegate:self connectionType:GetAllAlerts]; 
    connection = [[NSURLConnection alloc] initWithRequest:request delegate: webserviceConnection]; 
} 

當另一個視圖控制器具有自己webserviceConnection實例使用它的實例(類似於getAllAlerts)都變成了梨形!

任何想法的人?

問候, 伯特

回答

1

由於您聲明像connectionType這樣的變量,因此看起來問題正在發生。如果你希望他們被聲明爲實例變量,你應該把它們放在接口聲明:

@interface WebServiceConnection { 
    BOOL isCanceled; 
    NSDictionary *result; 
    ConnectionType connectionType; 
    id <WebserviceConnectionDelegate> delegate; 
} 
@end 

通過聲明他們在@implementation塊,你實際上是創建全局變量,而不是實例變量。

有關更多信息,請參見this SO post

+0

作品!謝謝......不僅是我的問題的答案,而且是對obj-c的洞察力!一個人在學習...... – Berdus

1

定義塊:

BOOL isCanceled; 
NSDictionary *result; 
ConnectionType connectionType; 
id <WebserviceConnectionDelegate> delegate; 

宣佈這四個東西是全局變量,就好像他們不是在@implementation塊。簡單地把東西放入@implementation不會使它們成爲本地對象 - 它只是解釋了所有後續方法實現屬於哪個對象。

如果您不介意將實現細節放入頭文件中,可以將它們移動到@interface聲明中,例如,

@interface WebserviceConnection 
{ 
    BOOL isCanceled; 
    NSDictionary *result; 
    ConnectionType connectionType; 
    id <WebserviceConnectionDelegate> delegate; 
} 

// etc 

@end 

您可以通過類別將它們添加到您的類讓他們純粹是內部在一些重複的語法成本的實現,例如

#import "WebserviceConnection.h" 
#import "WebserviceUtility.h" 

@interface WebserviceConnection() // a category to add additional properties 
@property (nonatomic, assign) BOOL isCanceled; 
@property (nonatomic, retain) NSDictionary *result; 
@property (nonatomic, assign) ConnectionType connectionType; 
@property (nonatomic, assign) id <WebserviceConnectionDelegate> delegate; 
@end 

@implementation WebserviceConnection 

// synthesising the properties also adds the named properties as instance variables 
@synthesize isCanceled; 
@synthesize result; 
@synthesize connectionType; 
@synthesize delegate; 

- (id)initWithDelegate:(id)webServiceDelegate ... etc... 

旁白:一個名爲getJsonFromData:方法應根據可可的命名規則,因爲它不包含「新」,「ALLOC」,「保留」或「創建」返回非擁有參考。如果你服從的話,那麼在代碼中就會出現一個懸掛指針result

+0

太棒了!選擇一個。感謝您的快速回復 – Berdus