Add PromiseKit dependency

- Added PromiseKit dependency
This commit is contained in:
2018-11-15 22:08:00 -04:00
parent 2689d86c18
commit be7b6b5881
541 changed files with 46282 additions and 0 deletions

View File

@@ -0,0 +1 @@
#import "SCNetworkReachability+AnyPromise.h"

View File

@@ -0,0 +1,18 @@
#import <PromiseKit/AnyPromise.h>
/**
Resolves as soon as the Internet is accessible. If it is already
accessible, resolves immediately.
To import `SCNetworkReachability`:
use_frameworks!
pod "PromiseKit/SystemConfiguration"
And then in your sources:
@import PromiseKit;
@return A void promise that fulfills when the Internet becomes accessible.
*/
AnyPromise *SCNetworkReachability();

View File

@@ -0,0 +1,116 @@
#import <arpa/inet.h>
#import <CoreFoundation/CoreFoundation.h>
#import <Foundation/Foundation.h>
#import <ifaddrs.h>
#import <netdb.h>
#import <PromiseKit/AnyPromise.h>
#import <sys/socket.h>
#import <SystemConfiguration/SystemConfiguration.h>
@interface JTSReachability: NSObject {
@public
PMKResolver resolve;
id retainCycle;
}
- (BOOL)reachable;
- (void)start;
@end
AnyPromise *SCNetworkReachability() {
JTSReachability *reach = [JTSReachability new];
if (reach.reachable)
return [AnyPromise promiseWithValue:nil];
reach->retainCycle = reach;
[reach start];
return [[AnyPromise alloc] initWithResolver:&reach->resolve];
}
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) {
JTSReachability *reachability = (__bridge JTSReachability *)info;
if (reachability.reachable) {
reachability->resolve(nil);
reachability->retainCycle = nil;
}
}
@implementation JTSReachability {
SCNetworkReachabilityRef reachabilityRef;
}
- (instancetype)init {
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
reachabilityRef = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)&zeroAddress);
return self;
}
- (void)start {
SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};
SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context);
SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
}
- (void)dealloc {
SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
CFRelease(reachabilityRef);
}
- (BOOL)reachable {
SCNetworkReachabilityFlags flags;
if (!SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
return NO;
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
return NO;
BOOL returnValue = NO;
if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
{
/*
If the target host is reachable and no connection is required then we'll assume (for now) that you're on Wi-Fi...
*/
returnValue = YES;
}
if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
{
/*
... and the connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs...
*/
if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
{
/*
... and no [user] intervention is needed...
*/
returnValue = YES;
}
}
#if TARGET_OS_IPHONE
if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
{
/*
... but WWAN connections are OK if the calling application is using the CFNetwork APIs.
*/
if (flags & kSCNetworkReachabilityFlagsConnectionRequired) {
returnValue = NO;
} else {
returnValue = YES;
}
}
#endif
return returnValue;
}
@end

View File

@@ -0,0 +1,62 @@
import SystemConfiguration
#if !PMKCocoaPods
import PromiseKit
#endif
public extension SCNetworkReachability {
enum PMKError: Error {
case couldNotInitializeReachability
}
static func promise() -> Promise<Void> {
do {
var zeroAddress = sockaddr()
zeroAddress.sa_len = UInt8(MemoryLayout<sockaddr>.size)
zeroAddress.sa_family = sa_family_t(AF_INET)
guard let ref = SCNetworkReachabilityCreateWithAddress(nil, &zeroAddress) else {
throw PMKError.couldNotInitializeReachability
}
var flags = SCNetworkReachabilityFlags()
if SCNetworkReachabilityGetFlags(ref, &flags), flags.contains(.reachable) {
return Promise()
}
return try Helper(ref: ref).pending.promise
} catch {
return Promise(error: error)
}
}
}
private func callback(reachability: SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutableRawPointer?) {
if let info = info, flags.contains(.reachable) {
Unmanaged<Helper>.fromOpaque(info).takeUnretainedValue().pending.resolver.fulfill(())
}
}
private class Helper {
let pending = Promise<Void>.pending()
let ref: SCNetworkReachability
init(ref: SCNetworkReachability) throws {
self.ref = ref
var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
context.info = UnsafeMutableRawPointer(Unmanaged<Helper>.passUnretained(self).toOpaque())
guard SCNetworkReachabilitySetCallback(ref, callback, &context) else {
throw SCNetworkReachability.PMKError.couldNotInitializeReachability
}
guard SCNetworkReachabilitySetDispatchQueue(ref, .main) else {
SCNetworkReachabilitySetCallback(ref, nil, nil)
throw SCNetworkReachability.PMKError.couldNotInitializeReachability
}
_ = pending.promise.ensure {
SCNetworkReachabilitySetCallback(self.ref, nil, nil)
SCNetworkReachabilitySetDispatchQueue(self.ref, nil)
}
}
}