0

So I need to add the objects from an NSArray that the user has chosen using an NSOpenPanel and put all the filenames into this array. Then I have an NSMutableArray called arguments that I am putting the arguments programmatically. Then I need to add these objects from the NSArray to the end of this NSMutableArray. So I use [NSMutableArray addObjectsFromArray:NSArray] and that keeps giving me an error.

This is what I'm doing with the code: AppDelegate.h

#import <Cocoa/Cocoa.h>

@interface ZipLockAppDelegate : NSObject <NSApplicationDelegate> {
    IBOutlet NSTextField *input;
    IBOutlet NSTextField *output;
    IBOutlet NSTextField *password;
    NSArray *filenames;
    NSMutableArray *arguments;
    NSArray *argumentsFinal;
}

@property (assign) IBOutlet NSWindow *window;
@property (retain) NSArray *filenames;
@property (copy) NSMutableArray *arguments;

- (IBAction)chooseInput:(id)sender;
- (IBAction)chooseOutput:(id)sender;
- (IBAction)createZip:(id)sender;

@end

AppDelegate.m

#import "ZipLockAppDelegate.h"

@implementation ZipLockAppDelegate

@synthesize window = _window;
@synthesize filenames;
@synthesize arguments;

- (IBAction)chooseInput:(id)sender {
    NSOpenPanel *openZip = [[NSOpenPanel alloc] init];
    [openZip setCanChooseFiles:YES];
    [openZip setCanChooseDirectories:YES];
    [openZip setCanCreateDirectories:NO];
    [openZip setAllowsMultipleSelection:YES];
    [openZip setTitle:@"Select All Files/Folders to be zipped"];
    int result = [openZip runModal];
    if (result == 1) {
        filenames = [openZip filenames];
    }
}

- (IBAction)createZip:(id)sender {
    [progress startAnimation:self];
    arguments = [NSMutableArray arrayWithObjects:@"-P", [password stringValue], [output stringValue], nil];
    [self.arguments addObjectsFromArray:filenames];
    argumentsFinal = [[NSArray alloc] initWithArray:self.arguments];
    NSTask *makeZip = [[NSTask alloc] init];
    [makeZip setLaunchPath:@"/usr/bin/zip"];
    [makeZip setArguments:argumentsFinal];
    [makeZip launch];
    [makeZip waitUntilExit];
    [progress stopAnimation:self];
}

And this is the error I keep getting in the log. I can't figure out why I'm getting this.

EXC_BAD_ACCESS(code=13,address=0x0)

This points to the line [arguments addObjectsFromArray:filenames];

I can only make out the first part about the selector and the instance but I don't know what it means. Help...

2
  • 1
    You should use -mutableCopy when you set your array, not -copy. Are you using ARC? Commented Mar 17, 2012 at 16:27
  • 1
    addObjectsFromArray: is the correct way to add objects from another array to the end of a mutable array. Also, argumentsFinal is unnecessary; every NSMutableArray is an NSArray, so you can just use self.arguments for the task's arguments. Commented Mar 17, 2012 at 18:28

3 Answers 3

1

Be consistent. To begin with, prefix all your instance variables with an underscore, not just some of them.

 // Change this...
@synthesize window = _window;
@synthesize filenames;
@synthesize arguments;

//...to this
@synthesize window = _window;
@synthesize filenames = _filenames;
@synthesize arguments = _arguments;

Then you won't be able to do this anymore:

arguments = [NSMutableArray arrayWithObjects:@"-P", [password stringValue], [output stringValue], nil];

Note that on the very next line, you're doing this:

[self.arguments addObjectsFromArray:filenames];

Again, being consistent in using properties rather than directly accessing instance variables will help you avoid these kinds of errors. So rewrite the previous line to use the property, like so:

self.arguments = [NSMutableArray arrayWithObjects:@"-P", [password stringValue], [output stringValue], nil];

The compiler translates self.arguments = someArg into [self setArguments:someArg]. In this case the setter method is needed to retain the object so that it won't be deallocated while the reference is still stored in the _arguments instance variable.

Sign up to request clarification or add additional context in comments.

2 Comments

I'm assuming window=_window is the template code and the rest is added.
THANK YOU this worked. Keeping consistent did help with the self.arguments
1

Have you tried debugging it to see if filenames is ever initialized? Looking at your crashlog, you are referencing a nil pointer. It seems either filenames or arguments is never initialized.

Also, try and set your arguments array to a retain type rather than copy.

You also seem to keep going back and forth with your references. If you don't want to keep typing self.arguments, create an ivar in your synthesize statement and just stick with that.

@synthesize filenames = _filenames;
@synthesize arguments = _arguments;

[_arguments addObjectsFromArray:_filenames];

1 Comment

The ivar is created by synthesize whether another name is specified or not. It has the same name as the property by default; @synthesize arguments; creates -(NSMutableArray *)arguments, -(void)setArguments:(NSMutableArray *)newArguments, and an ivar named arguments.
1

Your arguments object is an NSArray, not an NSMutableArray. You can only add objects to a mutable array, by definition. Try this:

arguments = [NSMutableArray arrayWithObjects:@"-P", [password stringValue], [output stringValue], nil];

3 Comments

Thank you this fixed that problem but now I have a new one. Now my app crashes and gives me EXC_BAD_ACCESS(code=13, address=0x0) and its pointing to the line [self.arguments addObjectsFromArray:filenames]; and I have no idea whats wrong
I assume chooseInput: was executed before createZip is invoked? Are you using ARC? If not then you may have to retain filename within chooseInput: .
I'm not using ARC and I do retain it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.