2013-08-19 79 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

你有沒有找到墜機的原因?我也有同樣的問題。 –