Skip to content

Instantly share code, notes, and snippets.

@madcato
Created March 12, 2018 08:21
Show Gist options
  • Save madcato/d5c6ed09ca2792707365055ed1302690 to your computer and use it in GitHub Desktop.
Save madcato/d5c6ed09ca2792707365055ed1302690 to your computer and use it in GitHub Desktop.
EoloSender is a class to send POST to a http server. If the request fails, it's stored. It tries to resend the request every 15 seconds. Methods must be called from applicationDidBecomeActive and applicationWillResignActive, see the code.
//
// EoloSender.swift
// OSFramework
//
// Created by Daniel Vela on 13/02/17.
// Copyright © 2016 Daniel Vela. All rights reserved.
//
import Foundation
public protocol EoloSenderInteractor {
func postJSON(url: String,
parameters: [String: Any],
onOK: @escaping (Any?) -> Void,
onError: @escaping (Int, String) -> Void)
func cancel()
}
/*!
EoloSender is a class to send POST to a http server. If the request
fails, it's stored. It tries to resend the request every 15 seconds.
Methods must be called from applicationDidBecomeActive and
applicationWillResignActive, see the code.
*/
public class EoloSender {
var fileName = "WebQueriesData"
var data: [SerializableWebQuery] = []
var running = false
var senderObject: EoloSenderInteractor
public init(senderObject: EoloSenderInteractor) {
self.senderObject = senderObject
}
public func append(_ url: String, parameters: [String: Any]) {
self.data.append(SerializableWebQuery(url: url,
parameters: parameters,
sender: self.senderObject))
startContinue()
}
// Call this method from applicationDidBecomeActive
public func appBecomeActive() {
let restoredObjects = Serializator().restoreObject(fileName: fileName)
if let restoredObjects = restoredObjects {
self.data = restoredObjects as? [SerializableWebQuery] ?? []
for object in self.data {
object.sender = self.senderObject
}
}
startContinue()
}
// Call this method from applicationWillResignActive
public func appBecomeInactive() {
Serializator().saveObject(object: self.data as AnyObject, fileName: fileName)
}
func startContinue() {
if running == false {
running = true
} else {
return
}
sendAQuery()
}
static let initialSecondsToWaitOnError: Double = 15.0
var secondsToWaitOnError = {
initialSecondsToWaitOnError
}()
func sendAQuery() {
DispatchQueue.global(qos: .background).async {
if self.data.count > 0 {
let webQuery = self.data.removeFirst()
webQuery.start({
// Nothing. The query was ok
// Continue with next one
self.sendAQuery()
self.secondsToWaitOnError = EoloSender.initialSecondsToWaitOnError
// print("Pairing registered", webQuery.parameters)
}, onError: {
// On error the query must be restored on the queue
DispatchQueue.global(qos: .background).async {
self.data.append(webQuery)
// and wait some seconds
Thread.sleep(forTimeInterval: self.secondsToWaitOnError)
self.sendAQuery()
}
// print("Pairing error", webQuery.parameters)
})
} else {
self.running = false
}
}
}
}
class SerializableWebQuery: NSObject, NSCoding {
var url: String
var parameters: [String: Any]
var sender: EoloSenderInteractor?
init(url: String, parameters: [String: Any], sender: EoloSenderInteractor) {
self.url = url
self.parameters = parameters
self.sender = sender
}
func start(_ onOK: @escaping () -> Void, onError: @escaping () -> Void ) {
sender?.postJSON(url: self.url,
parameters: self.parameters,
onOK: { (_) in
// Revome this object in Serrializable data
onOK()
},
onError: { (_, _) in
// Keep this object in seriliable data
onError()
})
}
func stop() {
sender?.cancel()
}
required init?(coder aDecoder: NSCoder) {
self.url = aDecoder.decodeObject(forKey: "url") as? String ?? ""
self.parameters = aDecoder.decodeObject(forKey: "parameters")
as? [String: Any] ?? [:]
}
func encode(with aCoder: NSCoder) {
self.stop()
aCoder.encode(self.url, forKey: "url")
aCoder.encode(self.parameters, forKey: "parameters")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment