我能否传递NSWindow的引用给一个自定义对象并使用那个对象添加NSButton和Action



我想知道是否有可能将NSWindow的引用传递给自定义对象,然后使用该对象为该按钮添加NSButton和相关的操作/选择器。

当我尝试这个时,我似乎遇到了问题。当我运行示例程序并单击按钮时,发生以下运行时错误:线程1:EXC_BAD_ACCESS (code=1, address=0x18)

下面是我的代码:
//  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

首先,我假设您正在使用自动引用计数。

当您单击按钮时,应用程序尝试调用按钮目标的pressCustomButton:方法,CustomObject的实例将其设置为自身。但是,CustomObject的实例已经被释放了。

取以下代码:

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

一旦该方法被调用完成,如果您正在使用ARC,您创建的CustomObject实例将被释放。由于NSControl的子类如NSButton不保留它们的目标(为了避免保留周期/强引用周期),这也会导致CustomObject实例被释放。这将导致该实例的任何后续消息产生意想不到的结果,例如崩溃。

为了防止这种情况,您需要在applicationDidFinishLaunching:方法之外保留CustomObject实例。有几种方法可以做到这一点,例如使其成为AppDelegate的属性,或者如果您计划拥有多个对象,则使用NSMutableArray来存储它们。

类似如下:

@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

最新更新