異步函數調用 犯錯

前記,iOS用CFNetwork實現FTP下載類。


-(IBAction)dogdog:(id)sender{
    
    DLFTP *_ftp = [[DLFTP alloc] init];
    
    _ftp.mServerFile = @"www.dinglicom.com/aaa";
    _ftp.mLocalFile = @"/var/root/";
    [_ftp startDownload];
}


startDownload是異步的。故總下載不成功。因爲_ftp已經不存在了。

切記,切記,日後方不可這樣調用異步函數。

正確的:

@property(nonatomic, retain) DLFTP *ftp;
-(IBAction)dogdog:(id)sender{
    
    _ftp = [[DLFTP alloc] init];
    
    _ftp.mServerFile = @"www.dinglicom.com/aaa";
    _ftp.mLocalFile = @"/var/root/";
    [_ftp startDownload];
}

#import <Foundation/Foundation.h>

@interface DLFTP: NSObject <NSStreamDelegate>

@property(nonatomic, retain) NSString *mUser;
@property(nonatomic, retain) NSString *mPassword;
@property(nonatomic, retain) NSString *mServerFile;
@property(nonatomic, retain) NSString *mLocalFile;


@property (nonatomic, assign) BOOL isReceiving;
@property (nonatomic, strong) NSInputStream *   networkStream;
@property (nonatomic, strong) NSOutputStream *  fileStream;

- (void)receiveDidStart;
- (void)updateStatus:(NSString *)statusString;
- (void)receiveDidStopWithStatus:(NSString *)statusString;

-(void) startDownload;

-(void) cancelDownload;

//
//  DLFTP.m
//  SimpleFTPSample
//
//  Created by Walktour on 14-11-14.
//
//

#import "DLFTP.h"
#import <CFNetwork/CFNetwork.h>

@implementation DLFTP

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
    assert(aStream == self.networkStream);
    
    switch (eventCode) {
        case NSStreamEventOpenCompleted: {
            [self updateStatus:@"Opened connection"];
        } break;
        case NSStreamEventHasBytesAvailable: {
            NSInteger       bytesRead;
            uint8_t         buffer[32768];
            
            [self updateStatus:@"Receiving"];
            
            // Pull some data off the network.
            bytesRead = [self.networkStream read:buffer maxLength:sizeof(buffer)];
            if (bytesRead == -1) {
                [self stopReceiveWithStatus:@"Network read error"];
                
            } else if (bytesRead == 0) {
                [self stopReceiveWithStatus:nil];
            } else {
                NSInteger   bytesWritten;
                NSInteger   bytesWrittenSoFar;
                
                // Write to the file.
                bytesWrittenSoFar = 0;
                
                do {
                    bytesWritten = [self.fileStream write:&buffer[bytesWrittenSoFar] maxLength:(NSUInteger) (bytesRead - bytesWrittenSoFar)];
                    assert(bytesWritten != 0);
                    if (bytesWritten == -1) {
                        [self stopReceiveWithStatus:@"File write error"];
                        break;
                    } else {
                        bytesWrittenSoFar += bytesWritten;
                    }
                } while (bytesWrittenSoFar != bytesRead);
            }
        } break;
        case NSStreamEventHasSpaceAvailable: {
            assert(NO);     // should never happen for the output stream
        } break;
        case NSStreamEventErrorOccurred: {
            [self stopReceiveWithStatus:@"Stream open error"];
        } break;
        case NSStreamEventEndEncountered: {
            // ignore
        } break;
        default: {
            assert(NO);
        } break;
    }
}


-(void) startDownload{

    NSURL *_url = [NSURL URLWithString:@"ftp://www.gggggg.com"];
    
    if (_url != nil) {
        
        self.mLocalFile = [self getPermitFileName];
        self.fileStream = [NSOutputStream outputStreamToFileAtPath:self.mLocalFile append:YES];
        if (self.fileStream == nil) {
            return;
        }
        
        [self.fileStream open];
        
//        self.networkStream = CFBridgingRelease(CFReadStreamCreateWithFTPURL(NULL, (__bridge CFURLRef) _url));
        CFReadStreamRef ftpStream;
        NSURL *url;
        
        //獲得地址
        url = [NSURL URLWithString:@"ftp://www.dinglicom.com/aaa"];
        ftpStream = CFReadStreamCreateWithFTPURL(NULL, (CFURLRef) url);
        self.networkStream = (NSInputStream *) ftpStream;
        
        if (self.networkStream == nil) {
            return;
        }
        
        self.networkStream.delegate = self;
        self.mUser = @"test";
        self.mPassword = @"test";
        [self.networkStream setProperty:self.mUser forKey: (id)kCFStreamPropertyFTPUserName];
        [self.networkStream setProperty:self.mPassword forKey: (id)kCFStreamPropertyFTPPassword];
        [self.networkStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [self.networkStream open];
        [self receiveDidStart];
        NSLog(@"start download %@", _url);

    }
}

-(void) cancelDownload{

}

- (void)stopReceiveWithStatus:(NSString *)statusString
// Shuts down the connection and displays the result (statusString == nil)
// or the error status (otherwise).
{
    if (self.networkStream != nil) {
        [self.networkStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        self.networkStream.delegate = nil;
        [self.networkStream close];
        self.networkStream = nil;
    }
    if (self.fileStream != nil) {
        [self.fileStream close];
        self.fileStream = nil;
    }
    [self receiveDidStopWithStatus:statusString];
    self.mLocalFile = nil;
}


#pragma mark-

- (void)receiveDidStart
{
    // Clear the current image so that we get a nice visual cue if the receive fails.
}


- (void)updateStatus:(NSString *)statusString
{
    NSLog(@"status String %@", statusString);
}

- (void)receiveDidStopWithStatus:(NSString *)statusString
{
    if (statusString == nil) {
        NSLog(@"download success.");
    }
}

-(NSString *) getPermitFileName{
    
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    return [[paths objectAtIndex:0] stringByAppendingPathComponent:@"tmpWFile"];
}


@end



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章