macOS/Cocoa应用启动GCDWebServer后冻结问题求助
解决macOS Cocoa应用中GCDWebServer启动导致冻结的问题
嘿,我之前也踩过这个坑!你的问题根源很明确:GCDWebServer的run(withPort:bonjourName:)方法是同步阻塞式的,而你在主线程(applicationDidFinishLaunching是在主线程执行的)里调用它,直接把主线程的运行循环占死了——主线程没法处理UI事件、系统消息,自然就会出现“应用无响应”和沙滩球光标。
两种快速解决方案:
方案1:把服务器启动放到后台队列
利用GCD把run方法的调用转移到后台线程,这样主线程就能正常工作了:
class AppDelegate: NSObject, NSApplicationDelegate { // 把webServer声明为类属性,避免被提前释放 private let webServer = GCDWebServer() func applicationDidFinishLaunching(_ aNotification: Notification) { webServer.addHandler(forMethod: "GET", path: "/hello", request: GCDWebServerRequest.self) { request -> GCDWebServerResponse? in print(request) return GCDWebServerDataResponse(html:"<html><body><p>Hello World</p></body></html>") } // 后台队列启动服务器,不阻塞主线程 DispatchQueue.global(qos: .background).async { self.webServer.run(withPort: 8080, bonjourName: "Hello World Web Server") print("Visit \(self.webServer.serverURL) in your web browser") } } }
方案2:使用异步启动的start方法
如果你的GCDWebServer版本支持,直接用start(withPort:bonjourName:)方法更简洁——它会自动在后台线程启动服务器,不需要手动管理队列:
class AppDelegate: NSObject, NSApplicationDelegate { private let webServer = GCDWebServer() func applicationDidFinishLaunching(_ aNotification: Notification) { webServer.addHandler(forMethod: "GET", path: "/hello", request: GCDWebServerRequest.self) { request -> GCDWebServerResponse? in print(request) return GCDWebServerDataResponse(html:"<html><body><p>Hello World</p></body></html>") } // 异步启动,立即返回,不阻塞主线程 webServer.start(withPort: 8080, bonjourName: "Hello World Web Server") print("Visit \(webServer.serverURL) in your web browser") } }
额外注意点:
一定要把webServer声明为AppDelegate的类属性,而不是applicationDidFinishLaunching里的局部变量——如果是局部变量,方法执行完毕后对象会被ARC释放,服务器也会随之停止运行。
内容的提问来源于stack exchange,提问作者dtrenz
相关产品推荐
相关产品推荐

