NSWriteStream打开导致访问不良

时间:2013-08-19 07:28:14

标签: iphone objective-c ios6 exc-bad-access

我编写了一个可以上传单个文件的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
//

1 个答案:

答案 0 :(得分:0)

尝试更改

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

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