【问题标题】:AsyncSocket delegate not invoked未调用 AsyncSocket 委托
【发布时间】:2012-12-06 22:42:23
【问题描述】:

我正在尝试编写一个应用程序来通过 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,因此它应该引用我复制方法的类。

有人可以帮我找出问题吗?

谢谢, 科拉多

【问题讨论】:

    标签: ios delegates cocoaasyncsocket


    【解决方案1】:

    问题是 didReadData 委托方法只被调用一次,你必须通过调用来保持监听套接字:

    [_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];
        }
    }
    

    【讨论】:

    • 感谢您的回答,但我不明白两件事:1. 如果这是问题所在,为什么应用程序的第一个版本(VievController 中包含委托方法)运行良好?代码完全相同。 2.除了接收数据的方法,好像还有方法: - (void)soc​​ket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port{ NSLog(@"socket connected"); } 不工作,因为我在日志中没有看到“套接字已连接”(但连接已建立,因为我在另一边收到了字母“C”。)谢谢
    • 你的单例模式是错误的,你应该在 GCDAsyncSocket 的 getInstance 中返回 SocketConnection 指针!您没有创建 SocketConnection 类,因此委托将为 nil。
    • 再次感谢,我会听从您的建议。
    • 你有没有解决过这个@Corrado,我正在寻找类似的东西
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-06
    • 2014-03-18
    • 2019-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多