我编写了一个可以上传单个文件的FTPUpload类。基于apple dev-site上的simpleFTP类,它是90%。现在在ios6.1下我得到了一个糟糕的访问权限。这仅在我第二次上传文件时发生。它发生在
上[ self.networkstream open ]
方法。在堆栈跟踪中,我看到CFWriteStreamOpen方法的访问不正确。我假设(纠正我,如果我错了)它的弧和垃圾收集器给我的问题。有人可以澄清为什么以及如何解决它。
Thx
的Wouter
//
// 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
//
答案 0 :(得分:0)
尝试更改
self.networkStream = CFBridgingRelease(CFWriteStreamCreateWithFTPURL(NULL, (__bridge CFURLRef) _destinationURL));
要
self.networkStream = (__bridge NSSOutputStream *)CFWriteStreamCreateWithFTPURL(NULL, (__bridge CFURLRef) _destinationURL));