2011-04-13 56 views
1

我是objc/Cocoa的新手,我從來沒有使用過C語言。在Obj-c中訪問先前定義的C Struct數據的問題

我已經得到先前定義的C結構數據的問題...
這裏是我的代碼:

AppController.h

#import <Cocoa/Cocoa.h> 

@interface AppController : NSObject { 
    AuthorizationRef authRef; 
    AuthorizationRights authRights; 
    AuthorizationFlags authFlags; 
} 
- (IBAction)toggleAuthentification:(id)sender; 
@end 

AppController.m

#import "AppController.h" 

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

     AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authRef); 
     AuthorizationItem rightItems[1] = {{"com.myname.myapp.adminRights", 0, NULL, 0}}; 
     authRights.count = 1; 
     authRights.items = rightItems; 
     authFlags = kAuthorizationFlagDefaults | kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagPreAuthorize; 

     return self; 
    } 

    - (IBAction)toggleAuthentification:(id)sender { 
     NSLog(@"%d", AuthorizationCopyRights(authRef, &authRights, kAuthorizationEmptyEnvironment, authFlags^kAuthorizationFlagInteractionAllowed, NULL)); 
    } 
@end 

當我點擊在我的應用程序的一個按鈕調用toggleAuthentification:,我得到錯誤代碼-60008(errAuthorizationInternal)。
在調試器中,我可以看到authRights.count = 1,表示正確,但authRights.itemsinit中定義的數據沒有任何對應關係。

我嘗試了很多不同的方式,但是我找不到解決方案。

請,任何人都可以解釋爲什麼它不工作,就像我會工作,以及如何解決我的問題。

膽紅素

回答

2

在你的代碼的問題是內存管理。

當您創建rightItems[],一個AuthorizationItem元素的數組時,它將在堆棧中創建,因爲rightItems[]是一個自動(本地)變量。這意味着數組使用的內存在方法結束時被釋放。由於指定爲authRights.items,authRights.items-init執行完成後指向虛假內存地址。對authRights.items的任何進一步引用都有未定義的行爲,並可能在您的程序中產生錯誤。

你需要做的是在堆中創建數組,以便在-init完成執行時不會釋放它。你可以通過malloc()來完成。例如:

const size_t numberOfRightItems = 1; 
AuthorizationItem *rightItems = malloc(sizeof(AuthorizationItem) 
    * numberOfRightItems); 
rightItems[0] = (AuthorizationItem){"com.myname.myapp.adminRights", 0, NULL, 0}; 

authRights.items = rightItems; 

理論上,你負責時,因爲你已經在堆中分配給它的內存不是需要它不再釋放authRights.items。因此,在您的-dealloc方法:

- (void)dealloc { 
    free(authRights.items); 
    super[dealloc]; 
} 

我,因爲你存儲在你的應用程序控制器的授權權利說在理論上。由於應用程序控制器處於整個應用程序生命週期中,技術上它不會收到-release-dealloc。但是,這是一種很好的做法,對於重新構建應用程序以及代碼最終處於一個類中,其中的對象在應用程序退出前不一定處於活動狀態時纔有用。

還有一點需要注意:您應該在-init方法中將[super init]的返回值分配給self。這也是一種好的做法,因爲[super init]可能返回與當前self不同的對象。

+0

感謝Bavarious的解釋和解決方案,它的工作完美。我在想,函數範圍中定義的變量和全局變量中引用的變量會自動保留在內存中。現在我將使用'self = [super init];如果(!self)返回零;' – Bil 2011-04-13 11:18:00