Last active
April 5, 2017 07:54
-
-
Save sharplet/34a4e893181469c20626f6abe0a2cdeb to your computer and use it in GitHub Desktop.
Simple GCD-based actors in Swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Dispatch | |
/// Wraps some `Base` type so that all method calls become | |
/// "message sends", e.g., `async { $0.foo() }` or `sync { $0.bar() }`. | |
public final class Actor<Base> { | |
private var instance: Base | |
private let queue: DispatchQueue | |
public init(_ instance: Base, target: DispatchQueue? = nil) { | |
self.instance = instance | |
self.queue = DispatchQueue(label: "me.sharplet.MethodActor.\(Actor.self).queue", target: target) | |
} | |
public func async(_ message: @escaping (inout Base) -> Void) { | |
queue.async { | |
message(&self.instance) | |
} | |
} | |
public func asyncAfter(deadline: DispatchTime, _ message: @escaping (inout Base) -> Void) { | |
queue.asyncAfter(deadline: deadline) { | |
message(&self.instance) | |
} | |
} | |
public func asyncAfter(wallDeadline: DispatchWallTime, _ message: @escaping (inout Base) -> Void) { | |
queue.asyncAfter(wallDeadline: wallDeadline) { | |
message(&self.instance) | |
} | |
} | |
public func sync<Result>(_ message: (inout Base) throws -> Result) rethrows -> Result { | |
return try queue.sync { | |
try message(&instance) | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// A simple app delegate that shows the network activity | |
/// indicator for 1 second whenever the app becomes active. | |
@UIApplicationMain | |
final class AppDelegate: UIResponder, UIApplicationDelegate { | |
var window: UIWindow? | |
func applicationDidBecomeActive(_ application: UIApplication) { | |
let indicator: Actor<NetworkActivityIndicator> = NetworkActivityIndicator.shared | |
indicator.async { $0.startActivity() } | |
indicator.asyncAfter(deadline: .now() + .seconds(1)) { $0.stopActivity() } | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
/// A shared actor to manage the network activity indicator. | |
/// The initialiser is private to enforce use of `NetworkActivityIndicator.shared`. | |
struct NetworkActivityIndicator { | |
static let shared = Actor(NetworkActivityIndicator(), target: .main) | |
private let application = UIApplication.shared | |
private var counter: Int | |
private init() { | |
counter = 0 | |
} | |
mutating func startActivity() { | |
counter += 1 | |
updateIndicator() | |
} | |
mutating func stopActivity() { | |
counter -= 1 | |
updateIndicator() | |
} | |
private func updateIndicator() { | |
application.isNetworkActivityIndicatorVisible = isActive | |
} | |
var isActive: Bool { | |
return counter > 0 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment