我在Swift中构建一个使用Objective-C编写的GCDAsyncSocket的框架。
我收到的错误是:
Couldn't start socket: Error Domain=GCDAsyncSocketErrorDomain Code=1 "Attempting to accept without a delegate. Set a delegate first." UserInfo=0x61000026b940 {NSLocalizedDescription=Attempting to accept without a delegate. Set a delegate first.}
我尝试在init方法中设置委托(如下所示),并尝试在初始化后使用setDelegate方法设置委托。
在调试时,我已经验证调用了setDelegate代码,并且传入的值(self
)实际上包含一个引用。
更新:当我修改GCDAsyncSocket.m以从委托声明中删除__weak
关键字时,它可以工作,但我仍然不明白为什么我应该这样做。
该行为:__weak id delegate
,更改为id delegate
以下是导致问题的类:
class Server: GCDAsyncSocketDelegate
{
let boundHost:String?
let port:UInt16
var socket:GCDAsyncSocket?
init(boundHost: String?, port: UInt16)
{
if boundHost {
self.boundHost = boundHost!
}
self.port = port
println("Server created with host: \(self.boundHost) and port: \(self.port).")
}
convenience init(port:UInt16) {
self.init(boundHost: nil, port: port)
}
func startServer() -> Bool
{
if !socket
{
socket = GCDAsyncSocket(delegate: self, delegateQueue: dispatch_get_main_queue())
}
var error:NSError?
if !socket!.acceptOnInterface(boundHost, port: port, error: &error)
{
println("Couldn't start socket: \(error)")
return false;
}
else
{
println("Listening on \(port).")
return true
}
}
func stopServer() -> Bool
{
if socket
{
socket!.disconnect()
return true
}
return false
}
func socket(sock:GCDAsyncSocket!, didAcceptNewSocket newSocket:GCDAsyncSocket!)
{
println("New socket received: \(newSocket)")
}
}
答案 0 :(得分:3)
这是GCDAsyncSocket和Swift代码中的委托的问题(也可以应用于其他委托方案)。
您在这里遇到的是:
Swift为GCDAsyncSocket()的调用创建了对self的引用
Objective-C对它做了些什么,但把它当作__weak来处理,基本上没有创建Swift需要关注的额外引用。
Swift完成对GCDAsyncSocket()的调用,ARC删除对self的引用,因为没有其他引用。 Swift不知道Objective-C仍然需要它。
当委托被声明为__weak时,它也会在Objective-C部分中消失。
GCDAsyncSocket已经没有委托,并抱怨它。
解决方案:
将NSObject作为超类添加到Swift类中,然后在类中保留“self”到init()中的某个全局类变量。然后ARC看到参考,一切都很好。这将在Swift方面为Object的生命周期创建一个引用,Objective-C中的__weak将按预期工作。
或者从GCDAsyncSocket中删除__weak并在Swift类的Deinit()方法中添加socket.Delegate(nil)。这将在Objective-C端创建一个引用,防止Swift端的ARC将其解除分离,直到您手动执行。
GCDAsyncSocket尝试不泄漏内存。在一个纯粹的Objective-C项目中,这可以正常工作,但是当使用Swift中的Objective-C时,如果它们在Objective-C中声明为__weak,则需要在Swift端保留委托。