2014-07-22 1 views
0

Je me demandais s'il est possible de passer la référence d'un NSWindow à un objet personnalisé, puis d'utiliser cet objet pour ajouter un NSButton et l'action/sélecteur associé à ce bouton.Puis-je transmettre la référence d'un NSWindow à un objet personnalisé et utiliser cet objet pour ajouter un NSButton et une action?

Je semble être confronté à des problèmes lorsque je tente cela. Quand je lance le programme d'échantillonnage et cliquez sur le bouton, l'erreur d'exécution suivante se produit: Discussion 1: EXC_BAD_ACCESS (code = 1, adresse = 0x18)

Voici mon code:

// AppDelegate.h 

#import <Cocoa/Cocoa.h> 

@interface AppDelegate : NSObject <NSApplicationDelegate> 
@property (assign) IBOutlet NSWindow *window; 
@end 

// AppDelegate.m 

#import "AppDelegate.h" 
#import "CustomObject.h" 
@implementation AppDelegate 

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification 
{ 
    CustomObject *test = [[CustomObject alloc]init]; 
    [test createButton:_window]; 
} 
@end 


// CustomObject.h 

#import <Foundation/Foundation.h> 

@interface CustomObject : NSObject 
{ 
    int test; 
    NSButton *testButton; 
} 
- (IBAction)pressCustomButton:(id)sender; 

-(void)createButton:(NSWindow*)win; 
@end 

// CustomObject.m 

#import "CustomObject.h" 

@implementation CustomObject 

-(IBAction)pressCustomButton:(id)sender 
{ 
    NSLog(@"pressCustomButton"); 
} 

-(void)createButton:(NSWindow*)win 
{ 
    testButton = [[NSButton alloc] initWithFrame:NSMakeRect(100, 100, 200, 50)]; 

    [[win contentView] addSubview: testButton]; 
    [testButton setTitle: @"Button title!"]; 
    [testButton setButtonType:NSMomentaryLightButton]; //Set what type button You want 
    [testButton setBezelStyle:NSRoundedBezelStyle]; //Set what style You want 

    [testButton setTarget:self]; 
    [testButton setAction:@selector(pressCustomButton:)]; 
} 
@end 

Répondre

1

Tout d'abord , Je suppose que vous utilisez le comptage automatique des références.

Lorsque vous cliquez sur le bouton, l'application tente d'appeler la méthode pressCustomButton: de la cible du bouton, que l'instance de CustomObject doit être elle-même. Toutefois, cette instance de CustomObject a déjà été désallouée.

Prenez le code suivant:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification 
{ 
    CustomObject *test = [[CustomObject alloc]init]; 
    [test createButton:_window]; 
} 

Une fois que cette méthode est fini d'être appelé, si vous utilisez ARC, l'instance CustomObject vous avez créé sera publié. Puisque les sous-classes NSControl comme NSButton ne conservent pas leurs cibles (pour éviter les cycles de retenue/cycles de référence forts), l'instance CustomObject sera également désaffectée. Cela entraînera des messages ultérieurs à cette instance pour produire des résultats inattendus tels qu'un accident.

Pour éviter cela, vous devez conserver l'instance CustomObject au-delà de la méthode applicationDidFinishLaunching:. Il y a deux façons de le faire, comme ce qui en fait une propriété du AppDelegate, ou si vous envisagez d'avoir plusieurs objets, utilisez un NSMutableArray pour les stocker dans

Quelque chose comme ce qui suit:.

@interface AppDelegate : NSObject <NSApplicationDelegate> 
.... 
@property (nonatomic, strong) NSMutableArray *customObjects; 
@end 

// AppDelegate.m 

#import "AppDelegate.h" 
#import "CustomObject.h" 
@implementation AppDelegate 

- (id)init { 
    if ((self = [super init])) { 
     customObjects = [[NSMutableArray alloc] init]; 
    } 
    return self; 
} 

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification 
{ 
    CustomObject *test = [[CustomObject alloc]init]; 
    [customObjects addObject:test]; 
    [test createButton:_window]; 
} 
@end 
Questions connexes