之前已经解决了:
[已解决]swift中timer NSTimer.scheduledTimerWithTimeInterval不工作
但是发现:
当使用iPhone真机去测试时,
按Home键,会到iPhone主界面后,
后台的NSTimer就不工作了。。。
swift app background timer not work
iphone – Scheduled NSTimer when app is in background? – Stack Overflow
Swift how to use NSTimer background? – Stack Overflow
Energy Efficiency Guide for iOS Apps: Work Less in the Background
Background Modes Tutorial: Getting Started
搜:
UIApplicationBackgroundFetchIntervalMinimum how long
UIApplicationBackgroundFetchIntervalMinimum 多长时间
ios – What is actaully the value of UIApplicationBackgroundFetchIntervalMinimum? – Stack Overflow
“ in practice it is around 10 minutes for iOS 6”
然后去试试:
其会自动给info.plist中添加相应的配置,无需你手动添加:
<key>UIBackgroundModes</key> <array> <string>fetch</string> </array> |
代码:
//every 10 minutes to re-connect the websocket again to keep connect alive //let WebsocketKeepConnectIntervalInSec:NSTimeInterval = NSTimeInterval(60*10) //10 minutes let WebsocketKeepConnectIntervalInSec:NSTimeInterval = NSTimeInterval(15) func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // Override point for customization after application launch. // UIApplication.sharedApplication().setMinimumBackgroundFetchInterval(WebsocketKeepConnectIntervalInSec) UIApplication.sharedApplication().setMinimumBackgroundFetchInterval(UIApplicationBackgroundFetchIntervalMinimum) return true } // Support for background fetch func application(application: UIApplication, performFetchWithCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) { let curTime = NSDate() print("performFetchWithCompletionHandler curTime=\(curTime)") print("gCurUserItem hasLogined=\(gCurUserItem.hasLogined) wsInited=\(gCurUserItem.wsInited)") if gCurUserItem.hasLogined && gCurUserItem.wsInited { SingletonMainVC().websocketKeepConnect() } } func websocketKeepConnect(){ let curTime = NSDate() print("websocketKeepConnect curTime=\(curTime)") // print("wsKeepConnectTimer=\(self.wsKeepConnectTimer)") print("gCurUserItem.hasLogined=\(gCurUserItem.hasLogined)") print("gCurUserItem.wsInited=\(gCurUserItem.wsInited)") if gCurUserItem.hasLogined && gCurUserItem.wsInited { print("before keep connect: webSocket.isConnected=\(webSocket.isConnected)") //no matter is connected or not, force connect it to send noop to server to keep websocket alive webSocket.connect() print("after keep connect: webSocket.isConnected=\(webSocket.isConnected)") } } |
连上iPhone真机去测试:
结果:
2016-03-03 15:08:07.070 JianDao[293:29811] Warning: Application delegate received call to -application:performFetchWithCompletionHandler: but the completion handler was never called. |
就可以正常输出了:
performFetchWithCompletionHandler curTime=2016-03-03 07:11:51 +0000 gCurUserItem hasLogined=true wsInited=true websocketKeepConnect curTime=2016-03-03 07:11:51 +0000 gCurUserItem.hasLogined=true gCurUserItem.wsInited=true before keep connect: webSocket.isConnected=true after keep connect: webSocket.isConnected=true performFetchWithCompletionHandler curTime=2016-03-03 07:11:52 +0000 gCurUserItem hasLogined=true wsInited=true websocketKeepConnect curTime=2016-03-03 07:11:52 +0000 gCurUserItem.hasLogined=true gCurUserItem.wsInited=true before keep connect: webSocket.isConnected=true after keep connect: webSocket.isConnected=true |
但是实际上,iPhone真机等待足够长时间,还是没有执行到上述的background的fetch
而且根据:
“Be prepared to handle connection failures in your network-based sockets. The system may tear down socket connections while your app is suspended for any number of reasons. As long as your socket-based code is prepared for other types of network failures, such as a lost signal or network transition, this should not lead to any unusual problems. When your app resumes, if it encounters a failure upon using a socket, simply reestablish the connection.”
Technical Note TN2277: Networking and Multitasking
“Multitasking, introduced with iOS 4, adds a new level of complexity for network apps. When iOS puts your app into the background, it may shortly thereafter suspend the app. When the app is suspended, no code within the app’s process executes. This makes it impossible for the app to handle incoming network data. Furthermore, while the app is suspended the system may choose to reclaim resources out from underneath a network socket used by the app, thereby closing the network connection represented by that socket.”
-》
-》
iOS会在进入后台后,由于(各种,未知的原因)把socket干掉断开
-》导致我此处就是断开了。。。
performFetchWithCompletionHandler curTime=2016-03-03 07:28:41 +0000 gCurUserItem hasLogined=true wsInited=true websocketKeepConnect curTime=2016-03-03 07:28:41 +0000 gCurUserItem.hasLogined=true gCurUserItem.wsInited=true before keep connect: webSocket.isConnected=false after keep connect: webSocket.isConnected=false websocketDidDisconnect error=Optional("未能完成该操该操\344\275作。Socket is not connected") Reconnect: webSocket=<JianDao.WebSocket: 0x127166a60> performFetchWithCompletionHandler curTime=2016-03-03 07:29:06 +0000 gCurUserItem hasLogined=true wsInited=true websocketKeepConnect curTime=2016-03-03 07:29:06 +0000 gCurUserItem.hasLogined=true gCurUserItem.wsInited=true before keep connect: webSocket.isConnected=true after keep connect: webSocket.isConnected=true websocketDidConnect: socket=<JianDao.WebSocket: 0x127166a60> websocketDidDisconnect error=Optional("未能完成该操作。Socket is not connected") Reconnect: webSocket=<JianDao.WebSocket: 0x127166a60> performFetchWithCompletionHandler curTime=2016-03-03 07:30:08 +0000 gCurUserItem hasLogined=true wsInited=true websocketKeepConnect curTime=2016-03-03 07:30:08 +0000 gCurUserItem.hasLogined=true gCurUserItem.wsInited=true before keep connect: webSocket.isConnected=false after keep connect: webSocket.isConnected=false websocketDidConnect: socket=<JianDao.WebSocket: 0x127166a60> |
然后就导致消息无法及时收发了。。。
然后调试的现象是:
只要app被(按了Home 键)退到后台运行
结果就是:
远端及时通过websocket发送消息后
app是无法及时立刻收到消息的
只有(点击app变成,切换到前台,当前激活状态)才能即刻,收到刚才漏掉的消息
[总结]
此处已经解决了:
iOS app在background的时候,不应该用timer做事情,而应该换用background fetch
但是却还是无法实现此处需要的功能
因为iOS app进入background后,
(web) socket:在一段时间之后(比如几分钟),就被中断了。
就无法继续接受来自服务器的消息了。
所以要去解决:
[未解决]当iOS app处于后台时仍能够及时收到远端服务器发来的及时消息
转载请注明:在路上 » [已解决]swift中iOS app处于background时NSTimer.scheduledTimerWithTimeInterval不工作