I'm new on objc/Cocoa and I never use C before.
I've a problem to get previously defined C struct data…
Here's my code :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
When I click on a button in my开发者_Go百科 app that call toggleAuthentification:
, I get error code -60008 (errAuthorizationInternal).
authRights.count
= 1, that correct, but authRights.items
do not correspond in any way to data defined in init
.
I try many different way but I don't find solution.
Please, anyone can explain why it doesn't work like I would it work and how to resolve my problem.
Bil
The problem in your code is memory management.
When you create rightItems[]
, an array of AuthorizationItem
elements, it is created in the stack since rightItems[]
is an automatic (local) variable. This means that the memory used by the array is deallocated at the end of the method. Since you’re assigning rightItems[]
to authRights.items
, authRights.items
points to a bogus memory address after -init
has finished executing. Any further reference to authRights.items
has undefined behaviour and is likely to produce an error in your program.
What you need to do is to create the array in the heap so that it isn’t deallocated when -init
has finished executing. You can do that via malloc()
. For instance:
const size_t numberOfRightItems = 1;
AuthorizationItem *rightItems = malloc(sizeof(AuthorizationItem)
* numberOfRightItems);
rightItems[0] = (AuthorizationItem){"com.myname.myapp.adminRights", 0, NULL, 0};
authRights.items = rightItems;
In theory, you’re responsible for releasing authRights.items when it’s not needed any longer since you’ve allocated memory for it in the heap. Hence, in your -dealloc
method:
- (void)dealloc {
free(authRights.items);
super[dealloc];
}
I’ve said in theory because you’re storing the authorisation rights in your application controller. Since the application controller lives throughout the application lifecycle, technically it won’t receive -release
or -dealloc
. However, it’s good practice and potentially useful in case you rearchitect your application and that code ends up being in a class whose objects are not necessarily alive until the application exits.
One further note: you should assign the return value of [super init]
to self
in your -init
method. This is also good practice since it is possible that [super init]
returns a different object than current self
.
精彩评论