EXC_BAD_ACCESS calling block

UPDATE | I downloaded the sample project using the panel and crashed here: http://w3style.co.uk/~d11wtq/BlocksCrash.tar.gz (I know that the "Select ..." button does nothing, I have not implemented it yet )

UPDATE 2 | I just discovered that I don’t even need to call anything on newFilePanelto cause a crash, I just need to use it in the instructions.

This also causes a crash:

[newFilePanel beginSheetModalForWindow:[windowController window] completionHandler:^(NSInteger result) {
    newFilePanel; // Do nothing, just use the variable in an expression
}];

It seems that the last thing that was dumped to the console, sometimes this: "Unable to parse dyld_stub_objc_msgSend_stret.", And sometimes it: "Unable to access memory at address 0xa".

I created my own sheet (a subclass of NSPanel) that tries to provide an API similar to NSOpenPanel / NSSavePanel in that it represents itself as a sheet and calls the block when it is done.

Here's the interface:

//
//  EDNewFilePanel.h
//  MojiBaker
//
//  Created by Chris Corbyn on 29/12/10.
//  Copyright 2010 Chris Corbyn. All rights reserved.
//

#import <Cocoa/Cocoa.h>

@class EDNewFilePanel;

@interface EDNewFilePanel : NSPanel <NSTextFieldDelegate> {
    BOOL allowsRelativePaths;

    NSTextField *filenameInput;

    NSButton *relativePathSwitch;

    NSTextField *localPathLabel;
    NSTextField *localPathInput;
    NSButton *chooseButton;

    NSButton *createButton;
    NSButton *cancelButton;
}

@property (nonatomic) BOOL allowsRelativePaths;

+(EDNewFilePanel *)newFilePanel;

-(void)beginSheetModalForWindow:(NSWindow *)aWindow completionHandler:(void (^)(NSInteger result))handler;
-(void)setFileName:(NSString *)fileName;
-(NSString *)fileName;
-(void)setLocalPath:(NSString *)localPath;
-(NSString *)localPath;
-(BOOL)isRelative;

@end

And the key methods inside the implementation:

-(void)beginSheetModalForWindow:(NSWindow *)aWindow completionHandler:(void (^)(NSInteger result))handler {
    [NSApp beginSheet:self
       modalForWindow:aWindow
        modalDelegate:self
       didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
          contextInfo:(void *)[handler retain]];
}

-(void)dismissSheet:(id)sender {
    [NSApp endSheet:self returnCode:([sender tag] == 1) ? NSOKButton : NSCancelButton];
}

-(void)sheetDidEnd:(NSWindow *)aSheet returnCode:(NSInteger)result contextInfo:(void *)contextInfo {
    ((void (^)(NSUInteger result))contextInfo)(result);
    [self orderOut:self];
    [(void (^)(NSUInteger result))contextInfo release];
}

It all works when my block just doesn't work with an empty body. My block is called when the sheet is rejected.

EDNewFilePanel *newFilePanel = [EDNewFilePanel newFilePanel];
[newFilePanel setAllowsRelativePaths:[self hasSelectedItems]];
[newFilePanel setLocalPath:@"~/"];
[newFilePanel beginSheetModalForWindow:[windowController window] completionHandler:^(NSInteger result) {
    NSLog(@"I got invoked!");
}];

But as soon as I try to access the panel from inside the block, I crash with EXC_BAD_ACCESS. For example, this results in a crash:

EDNewFilePanel *newFilePanel = [EDNewFilePanel newFilePanel];
[newFilePanel setAllowsRelativePaths:[self hasSelectedItems]];
[newFilePanel setLocalPath:@"~/"];
[newFilePanel beginSheetModalForWindow:[windowController window] completionHandler:^(NSInteger result) {
    NSLog(@"I got invoked and the panel is %@!", newFilePanel);
}];

This is not clear from the debugger with the reason. The first element (zero 0) on the stack just says "??" and nothing is indicated there.

The following items (1 and 2) on the stack are calls -endSheet:returnCode:and, -dismissSheet:respectively. Looking through the variables in the debugger, nothing seems wrong / inaccessible.

, , , ( ), -retain .

?

+3
2

retain , release - , .

completionHandler beginSheet . , , .

, EXC_BAD_ACCESS, , [handler retain] beginSheet:. , - ( ):

[myObject doThingWithCompletionHandler:^{ NSLog(@"done!"); }];

-copy , . , , . , , . poof , , . , copy , , , .

+12

EDNewFilePanel __block:

__block EDNewFilePanel *newFilePanel = [EDNewFilePanel newFilePanel];

, , Panel . , .

-1

Source: https://habr.com/ru/post/1782730/


All Articles