I have a problem that seems to be a premature release of an object used in an ARC application. I am trying to create a folder on an FTP server. Below are the relevant parts of the code; I will first describe the problem.
the problem with the code is that the debug output in
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
the method is never called.
Instead, I just get the _EXC_BAD_ACCESS_ error. During debugging, I learned two things:
if this message is not sent, the rest of the code doesn't really make sense - but it doesn't crash ...
I tracked EXC_BAD_ACCESS using NSZombieEnabled: with zombie objects enabled, GDB creates the following debug information:
*** -[FTPUploads respondsToSelector:]: message sent to deallocated instance 0x9166590
0x9166590 - FTPUploads.
, , .
? ?
:
FTPUploads.h :
#import <Foundation/Foundation.h>
enum UploadMode {
UploadModeCreateDir,
UploadModeUploadeData
};
@class UploadDatasetVC;
@interface FTPUploads : NSObject<NSStreamDelegate> {
@private
NSString *uploadDir;
NSString *ftpUser;
NSString *ftpPass;
NSString *datasetDir;
NSArray *files;
NSInputStream *fileStream;
NSOutputStream *ftpStream;
enum UploadMode uploadMode;
UploadDatasetVC *callback;
}
- (id) initWithTimeseriesID: (int) aTimeseriesID
fromDatasetDir: (NSString *) aDir
withFiles: (NSArray *) filesArg
andCallbackObject: (UploadDatasetVC *) aCallback;
- (void) createDir;
@end
FTPUploads.m
#import "FTPUploads.h"
#import "UploadDatasetVC"
@implementation FTPUploads
- (id) initWithTimeseriesID: (int) aTimeseriesID
fromDatasetDir: (NSString *) aDir
withFiles: (NSArray *) filesArg
andCallbackObject: (UploadDatasetVC *) aCallback {
self = [super init];
if (self) {
uploadDir = [NSString stringWithFormat: @"ftp://aServer.org/%i/", aTimeseriesID];
ftpUser = @"aUser";
ftpPass = @"aPass";
datasetDir = aDir;
files = filesArg;
bufferOffset = 0;
bufferLimit = 0;
index = 0;
callback = aCallback;
}
return self;
}
- (void) createDir {
uploadMode = UploadModeCreateDir;
NSURL *destinationDirURL = [NSURL URLWithString: uploadDir];
CFWriteStreamRef writeStreamRef = CFWriteStreamCreateWithFTPURL(NULL, (__bridge CFURLRef) destinationDirURL);
assert(writeStreamRef != NULL);
ftpStream = (__bridge_transfer NSOutputStream *) writeStreamRef;
[ftpStream setProperty: ftpUser forKey: (id)kCFStreamPropertyFTPUserName];
[ftpStream setProperty: ftpPass forKey: (id)kCFStreamPropertyFTPPassword];
ftpStream.delegate = self;
[ftpStream scheduleInRunLoop: [NSRunLoop currentRunLoop] forMode: NSDefaultRunLoopMode];
[ftpStream open];
CFRelease(writeStreamRef);
}
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
NSLog(@"aStream has an event: %i", eventCode);
switch (eventCode) {
default:
NSLog(@"default mode; no event");
break;
}
}
EDIT: , UploadDatasetVC:
FTPUploads *uploads = [[FTPUploads alloc] initWithTimeseriesID: timeseries_id
fromDatasetDir: datasetDir
withFiles: files
andCallbackObject: self];
[uploads createDir];