最新消息:20210917 已从crifan.com换到crifan.org

[已解决]swift中iOS app处于background时NSTimer.scheduledTimerWithTimeInterval不工作

iOS crifan 3841浏览 0评论

之前已经解决了:

[已解决]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”

三种方式使得iOS应用能够在后台进行数据更新和下载

Background Fetch

然后去试试:

其会自动给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

而且根据:

Background Execution

“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.”

-》

About iOS App Architecture

-》

Background Execution

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不工作

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
93 queries in 0.197 seconds, using 23.36MB memory