アラートが消える時に実行させる処理をブロックで渡していたが、そのブロックが実行される時にはもうdelegate先のオブジェクトが解放されているため起こっていた。
クラス変数から参照を張ってdidDismissが実行されるまではdelegate先のオブジェクトが解放されないようにした。
@implementation BlockAlertSheet @interface BlockAlertSheet() @property(nonatomic, strong) NSString *title; @property(nonatomic, strong) NSString *message; @property(nonatomic, strong) NSWindow *docWindow; @property(nonatomic, assign) AlertBlock didEnd; @property(nonatomic, assign) AlertBlock didDismiss; @property(nonatomic, assign) void *contextInfo; @property(nonatomic, strong) NSString *defaultButtonTitle; @property(nonatomic, strong) NSString *alternateButtonTitle; @property(nonatomic, strong) NSString *otherButtonTitle; @property(nonatomic, strong) NSString *id; @end @implementation BlockAlertSheet static NSMutableDictionary *retainer; + (void)initialize { retainer = [NSMutableDictionary dictionary]; } - (id)initWithTitle:(NSString *)title message:(NSString *)message docWindow:(NSWindow *)docWindow didEnd:(AlertBlock)didEnd didDismiss:(AlertBlock)didDismiss contextInfo:(void *)contextInfo defaultButtonTitle:(NSString *)defaultButtonTitle alternateButtonTitle:(NSString *)alternateButtonTitle otherButtonTitle:(NSString *)otherButtonTitle { self = [super init]; if (self) { self.title = title; self.message = message; self.docWindow = docWindow; self.didEnd = didEnd; self.didDismiss = didDismiss; self.contextInfo = contextInfo; self.defaultButtonTitle = defaultButtonTitle; self.alternateButtonTitle = alternateButtonTitle; self.otherButtonTitle = otherButtonTitle; self.id = [NSString stringWithFormat:@"%p", self]; } return self; } - (void)show { // didEndなどのブロックが実行された時にselfが解放されていてエラーになるのを防ぐために // retainしておく [retainer setObject:self forKey:self.id]; NSBeginAlertSheet(self.title, self.defaultButtonTitle, self.alternateButtonTitle, self.otherButtonTitle, self.docWindow, self, @selector(sheetDidEnd:returnCode:contextInfo:), @selector(sheetDidDismiss:returnCode:contextInfo:), self.contextInfo, self.message); } - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo { if (self.didEnd) { self.didEnd(sheet, returnCode, contextInfo); } } - (void)sheetDidDismiss:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo { if (self.didDismiss) { self.didDismiss(sheet, returnCode, contextInfo); } // TODO:なぜかオブジェクトが削除されないことがある。メモリリークしている。 [retainer removeObjectForKey:self.id]; } @end