Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use [NSAlert beginSheetModalForWindow:completionhandler:] on older versions of OS X

OS X Mavericks implemented a new API for more convenient displaying of NSAlert:

- (void)beginSheetModalForWindow:(NSWindow *)sheetWindow completionHandler:(void (^)(NSModalResponse returnCode))handler

Is there an easy way to create a similar method in a category that does the same thing but supported on OS X 10.8 and earlier?

like image 507
Jakob Egger Avatar asked Jan 12 '23 20:01

Jakob Egger


1 Answers

Yes, you can simulate a similar API using the delegate based API. The only tricky part is getting all the casts right so it works with ARC. Here's a category on NSAlert that provides a backward compatible block-based API:

NSAlert+BlockMethods.h

#import <Cocoa/Cocoa.h>
@interface NSAlert (BlockMethods)
-(void)compatibleBeginSheetModalForWindow: (NSWindow *)sheetWindow
                        completionHandler: (void (^)(NSInteger returnCode))handler;
@end

NSAlert+BlockMethods.m

#import "NSAlert+BlockMethods.h"
@implementation NSAlert (BlockMethods)

-(void)compatibleBeginSheetModalForWindow: (NSWindow *)sheetWindow
                        completionHandler: (void (^)(NSInteger returnCode))handler
{
    [self beginSheetModalForWindow: sheetWindow
                     modalDelegate: self
                    didEndSelector: @selector(blockBasedAlertDidEnd:returnCode:contextInfo:)
                       contextInfo: (__bridge_retained void*)[handler copy] ];
}

-(void)blockBasedAlertDidEnd: (NSAlert *)alert
                  returnCode: (NSInteger)returnCode
                 contextInfo: (void *)contextInfo
{
    void(^handler)(NSInteger) = (__bridge_transfer void(^)(NSInteger)) contextInfo;
    if (handler) handler(returnCode);
}

@end

For more info, see my NSAlertBlockMethods Github repo.

like image 135
Jakob Egger Avatar answered Jan 14 '23 10:01

Jakob Egger