Advanced-NSOperations/Earthquakes/Operations/ReachabilityCondition.swift
2022-02-16 22:16:09 -08:00

92 lines
3.1 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Copyright (C) 2015 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
This file shows an example of implementing the OperationCondition protocol.
*/
import Foundation
import SystemConfiguration
/**
This is a condition that performs a very high-level reachability check.
It does *not* perform a long-running reachability check, nor does it respond to changes in reachability.
Reachability is evaluated once when the operation to which this is attached is asked about its readiness.
*/
struct ReachabilityCondition: OperationCondition {
static let hostKey = "Host"
static let name = "Reachability"
static let isMutuallyExclusive = false
let host: NSURL
init(host: NSURL) {
self.host = host
}
func dependencyForOperation(operation: Operation) -> NSOperation? {
return nil
}
func evaluateForOperation(operation: Operation, completion: OperationConditionResult -> Void) {
ReachabilityController.requestReachability(host) { reachable in
if reachable {
completion(.Satisfied)
}
else {
let error = NSError(code: .ConditionFailed, userInfo: [
OperationConditionKey: self.dynamicType.name,
self.dynamicType.hostKey: self.host
])
completion(.Failed(error))
}
}
}
}
/// A private singleton that maintains a basic cache of `SCNetworkReachability` objects.
private class ReachabilityController {
static var reachabilityRefs = [String: SCNetworkReachability]()
static let reachabilityQueue = dispatch_queue_create("Operations.Reachability", DISPATCH_QUEUE_SERIAL)
static func requestReachability(url: NSURL, completionHandler: (Bool) -> Void) {
if let host = url.host {
dispatch_async(reachabilityQueue) {
var ref = self.reachabilityRefs[host]
if ref == nil {
let hostString = host as NSString
ref = SCNetworkReachabilityCreateWithName(nil, hostString.UTF8String)
}
if let ref = ref {
self.reachabilityRefs[host] = ref
var reachable = false
var flags: SCNetworkReachabilityFlags = []
if SCNetworkReachabilityGetFlags(ref, &flags) != false {
/*
Note that this is a very basic "is reachable" check.
Your app may choose to allow for other considerations,
such as whether or not the connection would require
VPN, a cellular connection, etc.
*/
reachable = flags.contains(.Reachable)
}
completionHandler(reachable)
}
else {
completionHandler(false)
}
}
}
else {
completionHandler(false)
}
}
}