2013-08-19 53 views
0

我写了一个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 
// 
+0

它可以禁用ARC单个文件通过添加-fno-objc-弧编译器标志为这些files.aft呃这样做,并再次测试你的代码... –

回答

0

尝试改变

self.networkStream = CFBridgingRelease(CFWriteStreamCreateWithFTPURL(NULL, (__bridge CFURLRef) _destinationURL)); 

self.networkStream = (__bridge NSSOutputStream *)CFWriteStreamCreateWithFTPURL(NULL, (__bridge CFURLRef) _destinationURL)); 
+0

试过你的建议,但它仍然失败。 3上传后,我在_WRiteCOmmand(_CFFTPNetConnectionContext ...) - > CFWriteStreamOpen - > [self.networkstream open]上得到了相同的EXC_BAD_ACCESS错误。 –

+0

我已经删除了我的ftp-upload实现,并集成了WhiteRaccoon实现(www.github.com/valentinradu/WhiteRaccoon),直到现在,没有问题...现在我正在寻找他的impl工作原理和我的不是 –

+0

你有没有找到坠机的原因?我也有同样的问题。 –