0

CocoaAsyncSocket ライブラリを使用してデータを送受信するアプリを作成しようとしています。

アプリの最初のバージョンでは、ビュー コントローラーでソケットが作成/初期化され、正しく呼び出されるデリゲート メソッドも配置されます。

WakmanFirstViewController.m

#import "WakmanFirstViewController.h"
#import "GCDAsyncSocket.h"

@implementation WakmanFirstViewController

- (void)viewDidLoad
 {  
    [super viewDidLoad];

    asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];

    NSError *error = nil;

    if (![asyncSocket connectToHost:@"192.168.1.13" onPort:2000 error:&error]) {
        NSLog(@"Unable to connect to due to invalid configuration: %@",error);
    }

    NSData *requestData = [@"C" dataUsingEncoding:NSUTF8StringEncoding];
    [asyncSocket writeData:requestData withTimeout:-1.0 tag:0];
    [asyncSocket readDataWithTimeout:1 tag:0];
}

- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port {

    NSLog(@"socket:didConnectToHost:%@ port:%hu", host, port);
}

... (other delegate methods)

現在、ViewController からソケットの作成を削除し、Singleton クラスに配置して、他のビューからも同じ接続を使用できるようにしようとしています。

これを行うために、デリゲート メソッドも移動した新しいクラス (SocketConnection) を作成しました。

wakmanSocketConnection.h

#import <Foundation/Foundation.h>
#import "GCDAsyncSocket.h"

@interface SocketConnection : NSObject {
}

+ (GCDAsyncSocket *)getInstance;

@end

wakmanSocketConnection.m

#import "SocketConnection.h"

static GCDAsyncSocket *socket;

@implementation SocketConnection

+ (GCDAsyncSocket *)getInstance
{
    @synchronized(self) {

        if (socket == nil) {
            socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];           
        }

        if (![socket isConnected]) {
            NSError *error = nil;

            if (![socket connectToHost:@"192.168.1.13" onPort:2000 error:&error]){
                    NSLog(@"Error connecting: %@", error);
            }
        }
    }
    return socket;
}

- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port {
    NSLog(@"socket connected");
}

... (other delegate methods)

次に、Viewcontroller を変更しました。

WakmanFirstViewController.h

#import <UIKit/UIKit.h>
#import "SocketConnection.h"

@class GCDAsyncSocket;

@interface WakmanFirstViewController : UIViewController  {
    GCDAsyncSocket *socket; 
}

@end

WakmanFirstViewController.m

#import "WakmanFirstViewController.h"

@implementation WakmanFirstViewController

- (void)viewDidLoad
 {
    [super viewDidLoad];

    socket = [SocketConnection getInstance]; 

    NSData *requestData = [@"C" dataUsingEncoding:NSUTF8StringEncoding];
    [asyncSocket writeData:requestData withTimeout:-1.0 tag:0];
    [asyncSocket readDataWithTimeout:1 tag:0];
}

接続は確立されますが、問題はデリゲート メソッドが呼び出されないことです。

wakmanSocketConnection.mでは、デリゲートを self に設定して、メソッドをコピーしたクラスを参照するようにしました。

誰かが問題を見つけるのを手伝ってくれますか?

ありがとう、コラード

4

1 に答える 1

3

問題は、didReadData デリゲート メソッドが 1 回だけ呼び出され、呼び出してソケットをリッスンし続ける必要があることです。

[_socket readDataWithTimeout:-1 tag:0]; 

私の方法は次のようになります。

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    dispatch_async(dispatch_get_main_queue(), ^{
        @autoreleasepool {
            // DO STH
            [_socket readDataWithTimeout:-1 tag:0];
        }
    });
}

初期化方法:

- (id)init
{
    if (self = [super init]) 
    {
        _socketQueue = dispatch_queue_create("Socket TCP Queue", nil);
        _delegateQueue = dispatch_queue_create("Socket Delegate Queue", nil);
        _socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:_delegateQueue socketQueue:_socketQueue];

    }
    return self;
}

そして接続方法:

- (void)connectToServer:(NSString *)host port:(NSInteger)port
{
    self.host = host;
    self.port = port;

    NSError *error = nil;
    if (![_socket connectToHost:host onPort:port error:&error])
    {

    }
}

書き込み方法:

- (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag
{
    if ([self.socket isConnected]) {
        [self.socket writeData:data withTimeout:timeout tag:tag];
    }
}
于 2012-12-06T22:49:41.427 に答える