我寫了一個FTPUpload類,可以上傳單個文件。它基於apple dev-site上的simpleFTP類的90%。現在在ios6.1下,我得到了一個不好的訪問。這隻會在我第二次上傳文件時發生。它發生在NSWriteStream打開結果訪問不正確
[ self.networkstream open ]
方法。在堆棧跟蹤中,我看到CFWriteStreamOpen方法訪問不正確。我假設(糾正我,如果我錯了)它的弧和垃圾收集器,給我的問題。有人可以澄清爲什麼以及如何解決它。
THX
沃特
//
// FTPUploader.m
// ByteBlower
//
// Created by excentis on 27/06/13.
// Copyright (c) 2013 excentis. All rights reserved.
//
#import "FTPUploader.h"
#include <CFNetwork/CFNetwork.h>
enum {
kSendBufferSize = 32768
};
//
// Private interface
//
@interface FTPUploader()
@property (nonatomic, readwrite,retain) NSOutputStream * networkStream;
@property (nonatomic, readwrite,retain) NSInputStream * fileStream;
@property (copy) NSString * file;
@property (retain) NSURL * destinationURL;
@property (nonatomic, assign, readonly) uint8_t * buffer;
@property (nonatomic, assign, readwrite) size_t bufferOffset;
@property (nonatomic, assign, readwrite) size_t bufferLimit;
@end
//
// Implementation
//
@implementation FTPUploader
//
// Serialization
//
@synthesize delegate;
//
// Method Implementation
//
-(id) init
{
self = [ super init ];
if(self)
{
_networkStream = nil;
_fileStream = nil;
_buffer = malloc(kSendBufferSize * sizeof(uint8_t));
NSLog(@"alloc done");
}
return self;
}
-(void) dealloc
{
free(_buffer);
NSLog(@"Destruction");
if(_networkStream)
{
NSLog(@"close stream");
[_networkStream removeFromRunLoop:[NSRunLoop mainRunLoop]
forMode:NSDefaultRunLoopMode];
[ _networkStream close];
}
if(_fileStream)
{
NSLog(@"Close file");
[ _fileStream close];
}
}
-(void) upload: (NSString *) file destination:(NSURL *) destination username:(NSString *) username password:(NSString*) password
{
if(_fileStream != nil)
{
NSLog(@"Filestream not null at start");
}
if(_networkStream != nil)
{
NSLog(@"networkstream not null at start");
}
/**
* Sanity checks
**/
if(destination == nil)
{
NSException *e = [[NSException alloc] initWithName:@"urlMissing" reason:@"No url defined to upload" userInfo:nil];
@throw e;
}
_destinationURL = destination;
NSLog(@"Destination: %@",destination);
if(file == nil)
{
NSException * e = [[NSException alloc] initWithName:@"fileNameMissing" reason:@"Filename is nil" userInfo:nil];
@throw e;
}
NSLog(@"File: %@",file);
if([[NSFileManager defaultManager] fileExistsAtPath:file] == false)
{
NSException * e = [[NSException alloc] initWithName:@"fileMissing" reason:@"File is missing" userInfo:nil];
@throw e;
}
// Store the filepath
_file = file;
// Open a stream for the file we're going to send. We do not open this stream;
// NSURLConnection will do it for us.
_fileStream = [NSInputStream inputStreamWithFileAtPath:file];
if(self.fileStream == nil)
{
NSLog(@"filestream == nil...");
NSException * e = [[NSException alloc] initWithName:@"Filestream nil" reason:@"Filestream is nil" userInfo:nil];
@throw e;
}
//assert(self.fileStream != nil);
[self.fileStream open];
NSLog(@"Filestream open");
// Open a CFFTPStream for the URL.
self.networkStream = CFBridgingRelease(
CFWriteStreamCreateWithFTPURL(NULL, (__bridge CFURLRef) _destinationURL)
);
if(self.networkStream == nil)
{
NSLog(@"failed to bridge stream");
[ self.delegate uploadDone:false forFile:_file error:@"failed to create socket"];
return;
}
//assert(self.networkStream != nil);
NSLog(@"NetworkStream created");
if (username != nil) {
bool success = [self.networkStream setProperty:username forKey:(id)kCFStreamPropertyFTPUserName];
if(!success)
{
NSLog(@"set username failed");
}
success = [self.networkStream setProperty:password forKey:(id)kCFStreamPropertyFTPPassword];
if(!success)
{
NSLog(@"set pasword failed");
}
}
self.networkStream.delegate = self;
NSLog(@"Networkstream delegate set");
[self.networkStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
NSLog(@"Networkstream scheduled");
[self.networkStream open];
NSLog(@"Ready to upload");
}
// --- delegate code to handle the upload of the bytes
//
它可以禁用ARC單個文件通過添加-fno-objc-弧編譯器標誌爲這些files.aft呃這樣做,並再次測試你的代碼... –