現在、チャットクライアントをSwiftで作っています。チャット相手のクライアントはJavascriptで実装済みです。
サーバー側は、Python(Django)で作っていて、クライアントからAPI経由で各種のリクエストを処理しています。
Swift側はAlamofireとSwiftyJSONでAPIを叩いています。
これまでは、すべてのAPIリクエストが正常に処理されていたのですが、チャット実装にともなって、相手から
チャットが更新されたイベントを受け取ったときに、更新されたチャット内容をロードするためにAPIを叩こうと
すると、処理が永久ループにハマってしまい、抜け出すことができずにいます。
こちらがチャットをロードするコードになります。
Swift
1func reloadChatData() { 2 let jsonData = loadChat(_registration_id: RData.getRegistrationId()) 3 4 if(jsonData["status"].string! == "success") { 5 for chat in jsonData["chat"].arrayValue { 6 if (chat["chat_from"] == "D") { 7 let chat = ChatEntity(text: chat["chat"].string!, time: "", userType: .You) 8 chats.append(chat) 9 } 10 else { 11 let chat = ChatEntity(text: chat["chat"].string!, time: "", userType: .I) 12 chats.append(chat) 13 } 14 } 15 } 16 tableView.reloadData() 17 18} 19 20func loadChat(_registration_id: String) -> JSON { 21 let _commonURL = CommmonURL() 22 var _load_chat_url = _commonURL.SERVER_HOSTNAME + _commonURL.LOAD_CHAT_ENTRY_POINT 23 24 _load_chat_url = addParameter(url: _load_chat_url, named: "registration_id", value: _registration_id) 25 let response = runQuery(_load_chat_url) 26 let data: Data? = String(describing: response.rawValue).data(using: .utf8) 27 let responseJson = JSON(data!) as JSON 28 return responseJson 29} 30 31private func runQuery(_ _url: String) -> JSON { 32 var responseData: JSON = JSON.null 33 let urlString = _url 34 var keepAlive = true 35 36 Alamofire.request(urlString, method: .get, parameters: nil, encoding: JSONEncoding.default).responseJSON(completionHandler: { response in 37 responseData = JSON(response.result.value!) 38 keepAlive = false 39 print("**") // ********** When I call runQuery from websocket event listener function, the code don't reach this line. ********** 40 }) 41 42 print(keepAlive) 43 let runLoop = RunLoop.current 44 while keepAlive && 45 runLoop.run(mode: RunLoopMode.defaultRunLoopMode, before: Date(timeIntervalSinceNow: 0.1)) { 46 } 47 48 return responseData 49}
上記のreloadChatData()をViewControllerの任意の場所(WebSocketのイベント待受以外の場所)から実行すると、正常にチャットデータが返ってきます。
しかし、下記のコードからreloadChatData()を呼び出すと、runQuery()のkeepAliveがFalseにならずに永久ループにハマってしまいます。
サーバーのログでは、正常にクライアントにレスポンスを返しています。
Swift
1override func viewDidLoad() { 2 3 manager = SocketManager(socketURL: URL(string: SocketURL)!, config: [.log(true), .compress]) 4 socketIOClient = manager.defaultSocket 5 6 socketIOClient.on(clientEvent: .connect) {data, ack in 7 print(data) 8 9 // Connect Event is fired... 10 let data : Dictionary<String, String> = ["value": RData.getRegistrationId()] 11 self.socketIOClient.emit("join_room", data) 12 print("socket connected") 13 } 14 15 socketIOClient.on(clientEvent: .error) { (data, eck) in 16 print(data) 17 print("socket error") 18 } 19 20 socketIOClient.on(clientEvent: .disconnect) { (data, eck) in 21 print(data) 22 print("socket disconnect") 23 } 24 25 socketIOClient.on(clientEvent: SocketClientEvent.reconnect) { (data, eck) in 26 print(data) 27 print("socket reconnect") 28 } 29 30 socketIOClient.on("server_to_client") { data, emitter in 31 print("Get Message from Another Client...") 32 33 // ********** FAILED ********** 34 self.reloadChatData() 35 } 36 37 socketIOClient.connect() 38 39}
相手(Javascriptクライアント)からチャットを送ると、Xcodeのコンソールには、
print("Get Message from Another Client...")
が出力されます。
WebSocketでデータを受信したときだけの問題なので、なんらかreloadChatData()関数を呼び出す方法に問題があると思うのですが、解決の糸口がつかめません。
どのように実装すればよいのかアドバイスをいただけないでしょうか?
よろしくお願いします。

回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/05/06 13:54
2018/05/08 02:12