У меня есть проблема, которая, по-видимому, является преждевременным выпуском используемого объекта в приложении на основе ARC. Я пытаюсь создать папку на FTP-сервере. Соответствующие части кода приведены ниже; Сначала я опишу проблему.
проблема с кодом в том, что вывод отладки в
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
метод никогда не вызывается.
Вместо этого я просто получаю ошибку _EXC_BAD_ACCESS_.
Во время отладки я обнаружил две вещи:
ошибка появляется только при выполнении следующей строки кода (метод createDir):
[ftpStream open];
если это сообщение не отправлено, остальная часть кода на самом деле не имеет смысла - но он также не падает ...
Я отслеживал EXC_BAD_ACCESS с помощью NSZombieEnabled: при включенных объектах-зомби GDB выдает следующую информацию отладчика:
*** -[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;
/* FTP Upload fields */
NSInputStream *fileStream;
NSOutputStream *ftpStream;
// some more fields...
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];
// open stream
[ftpStream open];
CFRelease(writeStreamRef);
}
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
NSLog(@"aStream has an event: %i", eventCode);
switch (eventCode) {
// all cases handled properly
default:
// no event
NSLog(@"default mode; no event");
break;
}
}
РЕДАКТИРОВАТЬ : добавлен код создания, используемый в классе UploadDatasetVC:
FTPUploads *uploads = [[FTPUploads alloc] initWithTimeseriesID: timeseries_id
fromDatasetDir: datasetDir
withFiles: files
andCallbackObject: self];
[uploads createDir];