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,5 @@
*.xcodeproj/**/xcuserdata/
*.xcscmblueprint
/Carthage
/.build
.DS_Store

View File

@@ -0,0 +1,84 @@
branches:
only:
- master
stages:
- lint
- carthage
- test
jobs:
include:
- &pod
stage: lint
osx_image: xcode8.3
env: SWIFT=3.1
name: pod lib lint --swift-version=3.1
os: osx
language: objective-c
before_install:
gem install cocoapods --prerelease --version 1.6.0.beta.1
install:
carthage bootstrap --no-build PromiseKit
script: |
cd Carthage/Checkouts/PromiseKit
mv .github/PromiseKit.podspec .
rm -rf Extensions/CoreLocation/Sources
cp -R ../../../Sources Extensions/CoreLocation
pod lib lint --subspec=PromiseKit/CoreLocation --fail-fast --swift-version=$SWIFT
- <<: *pod
osx_image: xcode9.2
env: SWIFT=3.2
name: pod lib lint --swift-version=3.2
- <<: *pod
osx_image: xcode9.4
env: SWIFT=3.3
name: pod lib lint --swift-version=3.3
- <<: *pod
osx_image: xcode10
env: SWIFT=3.4
name: pod lib lint --swift-version=3.4
- <<: *pod
osx_image: xcode9.2
env: SWIFT=4.0
name: pod lib lint --swift-version=4.0
- <<: *pod
osx_image: xcode9.4
env: SWIFT=4.1
name: pod lib lint --swift-version=4.1
- <<: *pod
osx_image: xcode10
env: SWIFT=4.2
name: pod lib lint --swift-version=4.2
- stage: carthage
osx_image: xcode10
name: Carthage / watchOS
os: osx
language: objective-c
script:
carthage bootstrap --platform watchOS
cache:
directories:
- Carthage
- &test
stage: test
osx_image: xcode10
name: macOS Tests
env: DST='arch=x86_64' PLAT=macOS
os: osx
language: objective-c
cache:
directories:
- Carthage
before_install:
carthage bootstrap --cache-builds --no-use-binaries --platform $PLAT
install:
xcodebuild -scheme PMKCoreLocation -target PMKCoreLocation -quiet -destination "$DST" SWIFT_TREAT_WARNINGS_AS_ERRORS=YES build
script:
xcodebuild -scheme PMKCoreLocation -quiet -destination "$DST" test
- <<: *test
env: DST='OS=12.0,name=iPhone SE' PLAT=iOS
name: iOS Tests
- <<: *test
env: DST='OS=12.0,name=Apple TV' PLAT=tvOS
name: tvOS Tests

View File

@@ -0,0 +1 @@
github "mxcl/PromiseKit" ~> 6.0

View File

@@ -0,0 +1 @@
github "mxcl/PromiseKit" "6.5.0"

View File

@@ -0,0 +1,7 @@
// Created by Kevin Ballard on 12/14/15.
// Copyright © 2015 Postmates. All rights reserved.
FRAMEWORK_SEARCH_PATHS[sdk=macosx*] = $(SRCROOT)/Carthage/Build/Mac/ $(inherited)
FRAMEWORK_SEARCH_PATHS[sdk=iphone*] = $(SRCROOT)/Carthage/Build/iOS/ $(inherited)
FRAMEWORK_SEARCH_PATHS[sdk=watch*] = $(SRCROOT)/Carthage/Build/watchOS/ $(inherited)
FRAMEWORK_SEARCH_PATHS[sdk=appletv*] = $(SRCROOT)/Carthage/Build/tvOS/ $(inherited)

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@@ -0,0 +1,473 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
63199F0C1D5FF25C007E8A0E /* CLGeocoder+AnyPromise.h in Headers */ = {isa = PBXBuildFile; fileRef = 63199F061D5FF25C007E8A0E /* CLGeocoder+AnyPromise.h */; settings = {ATTRIBUTES = (Public, ); }; };
63199F0D1D5FF25C007E8A0E /* CLGeocoder+AnyPromise.m in Sources */ = {isa = PBXBuildFile; fileRef = 63199F071D5FF25C007E8A0E /* CLGeocoder+AnyPromise.m */; };
63199F0E1D5FF25C007E8A0E /* CLGeocoder+Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63199F081D5FF25C007E8A0E /* CLGeocoder+Promise.swift */; };
63199F0F1D5FF25C007E8A0E /* CLLocationManager+AnyPromise.h in Headers */ = {isa = PBXBuildFile; fileRef = 63199F091D5FF25C007E8A0E /* CLLocationManager+AnyPromise.h */; settings = {ATTRIBUTES = (Public, ); }; };
63199F101D5FF25C007E8A0E /* CLLocationManager+AnyPromise.m in Sources */ = {isa = PBXBuildFile; fileRef = 63199F0A1D5FF25C007E8A0E /* CLLocationManager+AnyPromise.m */; };
63199F111D5FF25C007E8A0E /* CLLocationManager+Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63199F0B1D5FF25C007E8A0E /* CLLocationManager+Promise.swift */; };
63199F161D5FF7B9007E8A0E /* CLGeocoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63199F141D5FF7B9007E8A0E /* CLGeocoderTests.swift */; };
63199F171D5FF7B9007E8A0E /* CLLocationManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63199F151D5FF7B9007E8A0E /* CLLocationManagerTests.swift */; };
6358AB7A1D5D4B6700B9B157 /* PMKCoreLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 6358AB791D5D4B6700B9B157 /* PMKCoreLocation.h */; settings = {ATTRIBUTES = (Public, ); }; };
63C7FFF71D5C020D003BAE60 /* PMKCoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63C7FFA71D5BEE09003BAE60 /* PMKCoreLocation.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
63C7FFF81D5C020D003BAE60 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 63C7FF9E1D5BEE09003BAE60 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 63C7FFA61D5BEE09003BAE60;
remoteInfo = PMKCoreLocation;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
63199F061D5FF25C007E8A0E /* CLGeocoder+AnyPromise.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "CLGeocoder+AnyPromise.h"; path = "Sources/CLGeocoder+AnyPromise.h"; sourceTree = SOURCE_ROOT; };
63199F071D5FF25C007E8A0E /* CLGeocoder+AnyPromise.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "CLGeocoder+AnyPromise.m"; path = "Sources/CLGeocoder+AnyPromise.m"; sourceTree = SOURCE_ROOT; };
63199F081D5FF25C007E8A0E /* CLGeocoder+Promise.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "CLGeocoder+Promise.swift"; path = "Sources/CLGeocoder+Promise.swift"; sourceTree = SOURCE_ROOT; };
63199F091D5FF25C007E8A0E /* CLLocationManager+AnyPromise.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "CLLocationManager+AnyPromise.h"; path = "Sources/CLLocationManager+AnyPromise.h"; sourceTree = SOURCE_ROOT; };
63199F0A1D5FF25C007E8A0E /* CLLocationManager+AnyPromise.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "CLLocationManager+AnyPromise.m"; path = "Sources/CLLocationManager+AnyPromise.m"; sourceTree = SOURCE_ROOT; };
63199F0B1D5FF25C007E8A0E /* CLLocationManager+Promise.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "CLLocationManager+Promise.swift"; path = "Sources/CLLocationManager+Promise.swift"; sourceTree = SOURCE_ROOT; };
63199F141D5FF7B9007E8A0E /* CLGeocoderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CLGeocoderTests.swift; path = Tests/CLGeocoderTests.swift; sourceTree = SOURCE_ROOT; };
63199F151D5FF7B9007E8A0E /* CLLocationManagerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CLLocationManagerTests.swift; path = Tests/CLLocationManagerTests.swift; sourceTree = SOURCE_ROOT; };
6358AB791D5D4B6700B9B157 /* PMKCoreLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PMKCoreLocation.h; path = Sources/PMKCoreLocation.h; sourceTree = SOURCE_ROOT; };
63C700091D5C0253003BAE60 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
63C7FFA71D5BEE09003BAE60 /* PMKCoreLocation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PMKCoreLocation.framework; sourceTree = BUILT_PRODUCTS_DIR; };
63C7FFF21D5C020D003BAE60 /* PMKCLTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PMKCLTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
63CCF8121D5C0C4E00503216 /* Cartfile */ = {isa = PBXFileReference; lastKnownFileType = text; path = Cartfile; sourceTree = "<group>"; };
63CCF8171D5C11B500503216 /* Carthage.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Carthage.xcconfig; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
63C7FFA31D5BEE09003BAE60 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
63C7FFEF1D5C020D003BAE60 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
63C7FFF71D5C020D003BAE60 /* PMKCoreLocation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
63C7FF9D1D5BEE09003BAE60 = {
isa = PBXGroup;
children = (
63C700091D5C0253003BAE60 /* Info.plist */,
63CCF8121D5C0C4E00503216 /* Cartfile */,
63CCF8171D5C11B500503216 /* Carthage.xcconfig */,
63C7FFA91D5BEE09003BAE60 /* Sources */,
63C7FFF31D5C020D003BAE60 /* Tests */,
63C7FFA81D5BEE09003BAE60 /* Products */,
);
sourceTree = "<group>";
};
63C7FFA81D5BEE09003BAE60 /* Products */ = {
isa = PBXGroup;
children = (
63C7FFA71D5BEE09003BAE60 /* PMKCoreLocation.framework */,
63C7FFF21D5C020D003BAE60 /* PMKCLTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
63C7FFA91D5BEE09003BAE60 /* Sources */ = {
isa = PBXGroup;
children = (
6358AB791D5D4B6700B9B157 /* PMKCoreLocation.h */,
63199F061D5FF25C007E8A0E /* CLGeocoder+AnyPromise.h */,
63199F071D5FF25C007E8A0E /* CLGeocoder+AnyPromise.m */,
63199F081D5FF25C007E8A0E /* CLGeocoder+Promise.swift */,
63199F091D5FF25C007E8A0E /* CLLocationManager+AnyPromise.h */,
63199F0A1D5FF25C007E8A0E /* CLLocationManager+AnyPromise.m */,
63199F0B1D5FF25C007E8A0E /* CLLocationManager+Promise.swift */,
);
path = Sources;
sourceTree = SOURCE_ROOT;
};
63C7FFF31D5C020D003BAE60 /* Tests */ = {
isa = PBXGroup;
children = (
63199F141D5FF7B9007E8A0E /* CLGeocoderTests.swift */,
63199F151D5FF7B9007E8A0E /* CLLocationManagerTests.swift */,
);
path = Tests;
sourceTree = SOURCE_ROOT;
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
63C7FFA41D5BEE09003BAE60 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
63199F0F1D5FF25C007E8A0E /* CLLocationManager+AnyPromise.h in Headers */,
63199F0C1D5FF25C007E8A0E /* CLGeocoder+AnyPromise.h in Headers */,
6358AB7A1D5D4B6700B9B157 /* PMKCoreLocation.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
63C7FFA61D5BEE09003BAE60 /* PMKCoreLocation */ = {
isa = PBXNativeTarget;
buildConfigurationList = 63C7FFAF1D5BEE09003BAE60 /* Build configuration list for PBXNativeTarget "PMKCoreLocation" */;
buildPhases = (
63C7FFA21D5BEE09003BAE60 /* Sources */,
63C7FFA31D5BEE09003BAE60 /* Frameworks */,
63C7FFA41D5BEE09003BAE60 /* Headers */,
);
buildRules = (
);
dependencies = (
);
name = PMKCoreLocation;
productName = "PMK+UIKit";
productReference = 63C7FFA71D5BEE09003BAE60 /* PMKCoreLocation.framework */;
productType = "com.apple.product-type.framework";
};
63C7FFF11D5C020D003BAE60 /* PMKCLTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 63C7FFFA1D5C020D003BAE60 /* Build configuration list for PBXNativeTarget "PMKCLTests" */;
buildPhases = (
63C7FFEE1D5C020D003BAE60 /* Sources */,
63C7FFEF1D5C020D003BAE60 /* Frameworks */,
639447051D5D011300DDAE3C /* Embed Carthage Frameworks */,
);
buildRules = (
);
dependencies = (
63C7FFF91D5C020D003BAE60 /* PBXTargetDependency */,
);
name = PMKCLTests;
productName = PMKTests/NS;
productReference = 63C7FFF21D5C020D003BAE60 /* PMKCLTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
63C7FF9E1D5BEE09003BAE60 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0800;
LastUpgradeCheck = 0930;
ORGANIZATIONNAME = "Max Howell";
TargetAttributes = {
63C7FFA61D5BEE09003BAE60 = {
CreatedOnToolsVersion = 8.0;
LastSwiftMigration = 0900;
ProvisioningStyle = Automatic;
};
63C7FFF11D5C020D003BAE60 = {
CreatedOnToolsVersion = 8.0;
LastSwiftMigration = 0900;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = 63C7FFA11D5BEE09003BAE60 /* Build configuration list for PBXProject "PMKCoreLocation" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 63C7FF9D1D5BEE09003BAE60;
productRefGroup = 63C7FFA81D5BEE09003BAE60 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
63C7FFA61D5BEE09003BAE60 /* PMKCoreLocation */,
63C7FFF11D5C020D003BAE60 /* PMKCLTests */,
);
};
/* End PBXProject section */
/* Begin PBXShellScriptBuildPhase section */
639447051D5D011300DDAE3C /* Embed Carthage Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
PromiseKit,
);
name = "Embed Carthage Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "case \"$PLATFORM_NAME\" in\nmacosx) plat=Mac;;\niphone*) plat=iOS;;\nwatch*) plat=watchOS;;\nappletv*) plat=tvOS;;\n*) echo \"error: Unknown PLATFORM_NAME: $PLATFORM_NAME\"; exit 1;;\nesac\nfor (( n = 0; n < SCRIPT_INPUT_FILE_COUNT; n++ )); do\nVAR=SCRIPT_INPUT_FILE_$n\nframework=$(basename \"${!VAR}\")\nexport SCRIPT_INPUT_FILE_$n=\"$SRCROOT\"/Carthage/Build/$plat/\"$framework\".framework\ndone\n\n/usr/local/bin/carthage copy-frameworks || exit\n\nfor (( n = 0; n < SCRIPT_INPUT_FILE_COUNT; n++ )); do\nVAR=SCRIPT_INPUT_FILE_$n\nsource=${!VAR}.dSYM\ndest=${BUILT_PRODUCTS_DIR}/$(basename \"$source\")\nditto \"$source\" \"$dest\" || exit\ndone";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
63C7FFA21D5BEE09003BAE60 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
63199F0E1D5FF25C007E8A0E /* CLGeocoder+Promise.swift in Sources */,
63199F101D5FF25C007E8A0E /* CLLocationManager+AnyPromise.m in Sources */,
63199F0D1D5FF25C007E8A0E /* CLGeocoder+AnyPromise.m in Sources */,
63199F111D5FF25C007E8A0E /* CLLocationManager+Promise.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
63C7FFEE1D5C020D003BAE60 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
63199F161D5FF7B9007E8A0E /* CLGeocoderTests.swift in Sources */,
63199F171D5FF7B9007E8A0E /* CLLocationManagerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
63C7FFF91D5C020D003BAE60 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 63C7FFA61D5BEE09003BAE60 /* PMKCoreLocation */;
targetProxy = 63C7FFF81D5C020D003BAE60 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
63C7FFAD1D5BEE09003BAE60 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 63CCF8171D5C11B500503216 /* Carthage.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.promisekit.CoreLocation;
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos watchsimulator watchos macosx appletvsimulator appletvos";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = "1,2,3,4";
TVOS_DEPLOYMENT_TARGET = 9.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
WATCHOS_DEPLOYMENT_TARGET = 3.0;
};
name = Debug;
};
63C7FFAE1D5BEE09003BAE60 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 63CCF8171D5C11B500503216 /* Carthage.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_BUNDLE_IDENTIFIER = org.promisekit.CoreLocation;
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos watchsimulator watchos macosx appletvsimulator appletvos";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = "1,2,3,4";
TVOS_DEPLOYMENT_TARGET = 9.0;
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
WATCHOS_DEPLOYMENT_TARGET = 3.0;
};
name = Release;
};
63C7FFB01D5BEE09003BAE60 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_MODULES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_MODULE_NAME = "${TARGET_NAME}";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
63C7FFB11D5BEE09003BAE60 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_MODULES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_MODULE_NAME = "${TARGET_NAME}";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Release;
};
63C7FFFB1D5C020D003BAE60 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
GCC_WARN_INHIBIT_ALL_WARNINGS = YES;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SUPPRESS_WARNINGS = YES;
SWIFT_VERSION = 4.0;
};
name = Debug;
};
63C7FFFC1D5C020D003BAE60 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
GCC_WARN_INHIBIT_ALL_WARNINGS = YES;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_SUPPRESS_WARNINGS = YES;
SWIFT_VERSION = 4.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
63C7FFA11D5BEE09003BAE60 /* Build configuration list for PBXProject "PMKCoreLocation" */ = {
isa = XCConfigurationList;
buildConfigurations = (
63C7FFAD1D5BEE09003BAE60 /* Debug */,
63C7FFAE1D5BEE09003BAE60 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
63C7FFAF1D5BEE09003BAE60 /* Build configuration list for PBXNativeTarget "PMKCoreLocation" */ = {
isa = XCConfigurationList;
buildConfigurations = (
63C7FFB01D5BEE09003BAE60 /* Debug */,
63C7FFB11D5BEE09003BAE60 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
63C7FFFA1D5C020D003BAE60 /* Build configuration list for PBXNativeTarget "PMKCLTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
63C7FFFB1D5C020D003BAE60 /* Debug */,
63C7FFFC1D5C020D003BAE60 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 63C7FF9E1D5BEE09003BAE60 /* Project object */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:/Users/mxcl/Desktop/PMK+UIKit/PMKFoundation.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key>
<false/>
</dict>
</plist>

View File

@@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0930"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "NO">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "NO"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "63C7FFA61D5BEE09003BAE60"
BuildableName = "PMKCoreLocation.framework"
BlueprintName = "PMKCoreLocation"
ReferencedContainer = "container:PMKCoreLocation.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "NO"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "63C7FFF11D5C020D003BAE60"
BuildableName = "PMKCLTests.xctest"
BlueprintName = "PMKCLTests"
ReferencedContainer = "container:PMKCoreLocation.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "63C7FFF11D5C020D003BAE60"
BuildableName = "PMKCLTests.xctest"
BlueprintName = "PMKCLTests"
ReferencedContainer = "container:PMKCoreLocation.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "63C7FFA61D5BEE09003BAE60"
BuildableName = "PMKCoreLocation.framework"
BlueprintName = "PMKCoreLocation"
ReferencedContainer = "container:PMKCoreLocation.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "63C7FFA61D5BEE09003BAE60"
BuildableName = "PMKCoreLocation.framework"
BlueprintName = "PMKCoreLocation"
ReferencedContainer = "container:PMKCoreLocation.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "63C7FFA61D5BEE09003BAE60"
BuildableName = "PMKCoreLocation.framework"
BlueprintName = "PMKCoreLocation"
ReferencedContainer = "container:PMKCoreLocation.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -0,0 +1,34 @@
# PromiseKit CoreLocation Extensions ![Build Status]
This project adds promises to Apples MapKit framework.
## CocoaPods
```ruby
pod "PromiseKit/CoreLocation", "~> 6.0"
```
The extensions are built into `PromiseKit.framework` thus nothing else is needed.
## Carthage
```ruby
github "PromiseKit/CoreLocation" ~> 3.0
```
The extensions are built into their own framework:
```swift
// swift
import PromiseKit
import PMKCoreLocation
```
```objc
// objc
@import PromiseKit;
@import PMKCoreLocation;
```
[Build Status]: https://travis-ci.org/PromiseKit/CoreLocation.svg?branch=master

View File

@@ -0,0 +1,40 @@
#import <CoreLocation/CLGeocoder.h>
#import <PromiseKit/AnyPromise.h>
/**
To import the `CLGecoder` category:
use_frameworks!
pod "PromiseKit/CoreLocation"
And then in your sources:
@import PromiseKit;
*/
@interface CLGeocoder (PromiseKit)
/**
Submits a reverse-geocoding request for the specified location.
@param location The location object containing the coordinate data to look up.
@return A promise that thens two parameters:
1. The first placemark that resides at the specified location.
2. The array of *all* placemarks that reside at the specified location.
*/
- (AnyPromise *)reverseGeocode:(CLLocation *)location NS_REFINED_FOR_SWIFT;
/**
Submits a forward-geocoding request using the specified address dictionary or address string.
@param addressDictionaryOrAddressString The address dictionary or address string to look up.
@return A promise that thens two parameters:
1. The first placemark that resides at the specified address.
2. The array of *all* placemarks that reside at the specified address.
*/
- (AnyPromise *)geocode:(id)addressDictionaryOrAddressString NS_REFINED_FOR_SWIFT;
@end

View File

@@ -0,0 +1,47 @@
#import "CLGeocoder+AnyPromise.h"
#import <CoreLocation/CLError.h>
#import <CoreLocation/CLErrorDomain.h>
#import <PromiseKit/AnyPromise.h>
@implementation CLGeocoder (PromiseKit)
- (AnyPromise *)reverseGeocode:(CLLocation *)location {
return [AnyPromise promiseWithResolverBlock:^(PMKResolver resolve) {
[self reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
resolve(error ?: PMKManifold(placemarks.firstObject, placemarks));
}];
}];
}
- (AnyPromise *)geocode:(id)address {
return [AnyPromise promiseWithResolverBlock:^(PMKResolver resolve) {
id handler = ^(NSArray *placemarks, NSError *error) {
resolve(error ?: PMKManifold(placemarks.firstObject, placemarks));
};
if ([address isKindOfClass:[NSDictionary class]]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[self geocodeAddressDictionary:address completionHandler:handler];
#pragma clang diagnostic pop
} else {
[self geocodeAddressString:address completionHandler:handler];
}
}];
}
@end
@implementation CLGeocoder (PMKDeprecated)
+ (AnyPromise *)reverseGeocode:(CLLocation *)location {
return [[CLGeocoder new] reverseGeocode:location];
}
+ (AnyPromise *)geocode:(id)input {
return [[CLGeocoder new] geocode:input];
}
@end

View File

@@ -0,0 +1,73 @@
import CoreLocation.CLGeocoder
#if !PMKCocoaPods
import PromiseKit
#endif
#if os(iOS) || os(watchOS) || os(OSX)
import class Contacts.CNPostalAddress
#endif
/**
To import the `CLGeocoder` category:
use_frameworks!
pod "PromiseKit/CoreLocation"
And then in your sources:
import PromiseKit
*/
extension CLGeocoder {
/// Submits a reverse-geocoding request for the specified location.
public func reverseGeocode(location: CLLocation) -> Promise<[CLPlacemark]> {
return Promise { seal in
reverseGeocodeLocation(location, completionHandler: seal.resolve)
}
}
/// Submits a forward-geocoding request using the specified address dictionary.
@available(iOS, deprecated: 11.0)
public func geocode(_ addressDictionary: [String: String]) -> Promise<[CLPlacemark]> {
return Promise { seal in
geocodeAddressDictionary(addressDictionary, completionHandler: seal.resolve)
}
}
/// Submits a forward-geocoding request using the specified address string.
public func geocode(_ addressString: String) -> Promise<[CLPlacemark]> {
return Promise { seal in
geocodeAddressString(addressString, completionHandler: seal.resolve)
}
}
/// Submits a forward-geocoding request using the specified address string within the specified region.
public func geocode(_ addressString: String, region: CLRegion?) -> Promise<[CLPlacemark]> {
return Promise { seal in
geocodeAddressString(addressString, in: region, completionHandler: seal.resolve)
}
}
#if !os(tvOS) && swift(>=3.2)
/// Submits a forward-geocoding request using the specified postal address.
@available(iOS 11.0, OSX 10.13, watchOS 4.0, *)
public func geocodePostalAddress(_ postalAddress: CNPostalAddress) -> Promise<[CLPlacemark]> {
return Promise { seal in
geocodePostalAddress(postalAddress, completionHandler: seal.resolve)
}
}
/// Submits a forward-geocoding requesting using the specified locale and postal address
@available(iOS 11.0, OSX 10.13, watchOS 4.0, *)
public func geocodePostalAddress(_ postalAddress: CNPostalAddress, preferredLocale locale: Locale?) -> Promise<[CLPlacemark]> {
return Promise { seal in
geocodePostalAddress(postalAddress, preferredLocale: locale, completionHandler: seal.resolve)
}
}
#endif
}
// TODO still not possible in Swift 3.2
//extension CLError: CancellableError {
// public var isCancelled: Bool {
// return self == .geocodeCanceled
// }
//}

View File

@@ -0,0 +1,46 @@
#import <CoreLocation/CLLocationManager.h>
#import <PromiseKit/AnyPromise.h>
/**
To import the `CLLocationManager` category:
use_frameworks!
pod "PromiseKit/CoreLocation"
And then in your sources:
@import PromiseKit;
*/
@interface CLLocationManager (PromiseKit)
/**
Determines the devices location waiting until the positional accuracy
of the measured locations is better than 500 meters.
If your app has not yet asked the user for locational determination
permissions, PromiseKit calls `+requestWhenInUseAuthorization`, if
you need always permissions, you must call this yourself before
any use of this method, or the promise will be rejected.
@return A promise that thens two parameters:
1. The most recent `CLLocation`.
2. An array of all recent `CLLocations`.
*/
+ (AnyPromise *)promise NS_REFINED_FOR_SWIFT;
/**
Determines the devices location using the provided block to determine
when locations become acceptably accurate.
With this variant you can wait for good accuracy or acceptable accuracy
(at your own discretion) if the `CLLocationManager` is taking too
long. For example, the user is not outside so you will never get 10 meter
accuracy, but it would be nice to wait a little just in case.
- see +promise
*/
+ (AnyPromise *)until:(BOOL(^)(CLLocation *))isLocationGoodBlock NS_REFINED_FOR_SWIFT;
@end

View File

@@ -0,0 +1,72 @@
#import <CoreLocation/CLLocationManagerDelegate.h>
#import "CLLocationManager+AnyPromise.h"
#import <CoreLocation/CLError.h>
#if !(TARGET_OS_TV && (TARGET_OS_EMBEDDED || TARGET_OS_SIMULATOR))
@interface PMKLocationManager : CLLocationManager <CLLocationManagerDelegate> {
@public
PMKResolver resolve;
id retainCycle;
BOOL (^block)(CLLocation *);
}
@end
@implementation PMKLocationManager
#define PMKLocationManagerCleanup() \
[manager stopUpdatingLocation]; \
retainCycle = self.delegate = nil;
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
NSMutableArray *okd = [NSMutableArray new];
for (id location in locations)
if (block(location))
[okd addObject:location];
if (okd.count) {
resolve(PMKManifold(okd.lastObject, okd));
PMKLocationManagerCleanup();
}
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
// Apple docs say to ignore this error
if (error.code != kCLErrorLocationUnknown) {
resolve(error);
PMKLocationManagerCleanup();
}
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
[manager startUpdatingLocation];
}
@end
@implementation CLLocationManager (PromiseKit)
+ (AnyPromise *)promise {
return [self until:^BOOL(CLLocation *location){
return location.horizontalAccuracy <= 500 && location.verticalAccuracy <= 500;
}];
}
+ (AnyPromise *)until:(BOOL(^)(CLLocation *))block {
PMKLocationManager *manager = [PMKLocationManager new];
manager.delegate = manager;
manager->block = block;
manager->retainCycle = manager;
#if TARGET_OS_IPHONE
if ([manager respondsToSelector:@selector(requestWhenInUseAuthorization)])
[manager requestWhenInUseAuthorization];
#endif
[manager startUpdatingLocation];
return [[AnyPromise alloc] initWithResolver:&manager->resolve];
}
@end
#endif

View File

@@ -0,0 +1,307 @@
import CoreLocation.CLLocationManager
#if !PMKCocoaPods
import PromiseKit
#endif
/**
To import the `CLLocationManager` category:
use_frameworks!
pod "PromiseKit/CoreLocation"
And then in your sources:
import PromiseKit
*/
extension CLLocationManager {
/// The type of location permission we are asking for
public enum RequestAuthorizationType {
/// Determine the authorization from the applications plist
case automatic
/// Request always-authorization
case always
/// Request when-in-use-authorization
case whenInUse
}
public enum PMKError: Error {
case notAuthorized
}
/**
Request the current location.
- Note: to obtain a single location use `Promise.lastValue`
- Parameters:
- authorizationType: requestAuthorizationType: We read your Info plist and try to
determine the authorization type we should request automatically. If you
want to force one or the other, change this parameter from its default
value.
- block: A block by which to perform any filtering of the locations that are
returned. In order to only retrieve accurate locations, only return true if the
locations horizontal accuracy < 50
- Returns: A new promise that fulfills with the most recent CLLocation that satisfies
the provided block if it exists. If the block does not exist, simply return the
last location.
*/
public class func requestLocation(authorizationType: RequestAuthorizationType = .automatic, satisfying block: ((CLLocation) -> Bool)? = nil) -> Promise<[CLLocation]> {
func std() -> Promise<[CLLocation]> {
return LocationManager(satisfying: block).promise
}
func auth() -> Promise<Void> {
#if os(macOS)
return Promise()
#else
func auth(type: PMKCLAuthorizationType) -> Promise<Void> {
return AuthorizationCatcher(type: type).promise.done(on: nil) {
switch $0 {
case .restricted, .denied:
throw PMKError.notAuthorized
default:
break
}
}
}
switch authorizationType {
case .automatic:
switch Bundle.main.permissionType {
case .always, .both:
return auth(type: .always)
case .whenInUse:
return auth(type: .whenInUse)
}
case .whenInUse:
return auth(type: .whenInUse)
case .always:
return auth(type: .always)
}
#endif
}
switch CLLocationManager.authorizationStatus() {
case .authorizedAlways, .authorizedWhenInUse:
return std()
case .notDetermined:
return auth().then(std)
case .denied, .restricted:
return Promise(error: PMKError.notAuthorized)
}
}
@available(*, deprecated: 5.0, renamed: "requestLocation")
public class func promise(_ requestAuthorizationType: RequestAuthorizationType = .automatic, satisfying block: ((CLLocation) -> Bool)? = nil) -> Promise<[CLLocation]> {
return requestLocation(authorizationType: requestAuthorizationType, satisfying: block)
}
}
private class LocationManager: CLLocationManager, CLLocationManagerDelegate {
let (promise, seal) = Promise<[CLLocation]>.pending()
let satisfyingBlock: ((CLLocation) -> Bool)?
@objc fileprivate func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let block = satisfyingBlock {
let satisfiedLocations = locations.filter(block)
if !satisfiedLocations.isEmpty {
seal.fulfill(satisfiedLocations)
} else {
#if os(tvOS)
requestLocation()
#endif
}
} else {
seal.fulfill(locations)
}
}
init(satisfying block: ((CLLocation) -> Bool)? = nil) {
satisfyingBlock = block
super.init()
delegate = self
#if !os(tvOS)
startUpdatingLocation()
#else
requestLocation()
#endif
_ = self.promise.ensure {
self.stopUpdatingLocation()
}
}
@objc func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
let (domain, code) = { ($0.domain, $0.code) }(error as NSError)
if code == CLError.locationUnknown.rawValue && domain == kCLErrorDomain {
// Apple docs say you should just ignore this error
} else {
seal.reject(error)
}
}
}
#if !os(macOS)
extension CLLocationManager {
/**
Request CoreLocation authorization from the user
- Note: By default we try to determine the authorization type you want by inspecting your Info.plist
- Note: This method will not perform upgrades from when-in-use to always unless you specify `.always` for the value of `type`.
*/
@available(iOS 8, tvOS 9, watchOS 2, *)
public class func requestAuthorization(type requestedAuthorizationType: RequestAuthorizationType = .automatic) -> Guarantee<CLAuthorizationStatus> {
let currentStatus = CLLocationManager.authorizationStatus()
func std(type: PMKCLAuthorizationType) -> Guarantee<CLAuthorizationStatus> {
if currentStatus == .notDetermined {
return AuthorizationCatcher(type: type).promise
} else {
return .value(currentStatus)
}
}
switch requestedAuthorizationType {
case .always:
func iOS11Check() -> Guarantee<CLAuthorizationStatus> {
switch currentStatus {
case .notDetermined, .authorizedWhenInUse:
return AuthorizationCatcher(type: .always).promise
default:
return .value(currentStatus)
}
}
#if PMKiOS11
// ^^ define PMKiOS11 if you deploy against the iOS 11 SDK
// otherwise the warning you get below cannot be removed
return iOS11Check()
#else
if #available(iOS 11, *) {
return iOS11Check()
} else {
return std(type: .always)
}
#endif
case .whenInUse:
return std(type: .whenInUse)
case .automatic:
if currentStatus == .notDetermined {
switch Bundle.main.permissionType {
case .both, .whenInUse:
return AuthorizationCatcher(type: .whenInUse).promise
case .always:
return AuthorizationCatcher(type: .always).promise
}
} else {
return .value(currentStatus)
}
}
}
}
@available(iOS 8, *)
private class AuthorizationCatcher: CLLocationManager, CLLocationManagerDelegate {
let (promise, fulfill) = Guarantee<CLAuthorizationStatus>.pending()
var retainCycle: AuthorizationCatcher?
let initialAuthorizationState = CLLocationManager.authorizationStatus()
init(type: PMKCLAuthorizationType) {
super.init()
func ask(type: PMKCLAuthorizationType) {
delegate = self
retainCycle = self
switch type {
case .always:
#if os(tvOS)
fallthrough
#else
requestAlwaysAuthorization()
#endif
case .whenInUse:
requestWhenInUseAuthorization()
}
promise.done { _ in
self.retainCycle = nil
}
}
func iOS11Check() {
switch (initialAuthorizationState, type) {
case (.notDetermined, .always), (.authorizedWhenInUse, .always), (.notDetermined, .whenInUse):
ask(type: type)
default:
fulfill(initialAuthorizationState)
}
}
#if PMKiOS11
// ^^ define PMKiOS11 if you deploy against the iOS 11 SDK
// otherwise the warning you get below cannot be removed
iOS11Check()
#else
if #available(iOS 11, *) {
iOS11Check()
} else {
if initialAuthorizationState == .notDetermined {
ask(type: type)
} else {
fulfill(initialAuthorizationState)
}
}
#endif
}
@objc fileprivate func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
// `didChange` is a lie; it fires this immediately with the current status.
if status != initialAuthorizationState {
fulfill(status)
}
}
}
#endif
private extension Bundle {
enum PermissionType {
case both
case always
case whenInUse
}
var permissionType: PermissionType {
func hasInfoPlistKey(_ key: String) -> Bool {
let value = object(forInfoDictionaryKey: key) as? String ?? ""
return !value.isEmpty
}
if hasInfoPlistKey("NSLocationAlwaysAndWhenInUseUsageDescription") {
return .both
}
if hasInfoPlistKey("NSLocationAlwaysUsageDescription") {
return .always
}
if hasInfoPlistKey("NSLocationWhenInUseUsageDescription") {
return .whenInUse
}
if #available(iOS 11, *) {
NSLog("PromiseKit: warning: `NSLocationAlwaysAndWhenInUseUsageDescription` key not set")
} else {
NSLog("PromiseKit: warning: `NSLocationWhenInUseUsageDescription` key not set")
}
// won't work, but we warned the user above at least
return .whenInUse
}
}
private enum PMKCLAuthorizationType {
case always
case whenInUse
}

View File

@@ -0,0 +1,2 @@
#import "CLLocationManager+AnyPromise.h"
#import "CLGeocoder+AnyPromise.h"

View File

@@ -0,0 +1,102 @@
import PMKCoreLocation
import CoreLocation
import PromiseKit
import XCTest
#if os(iOS) || os(watchOS) || os(OSX)
import class Contacts.CNPostalAddress
#endif
class CLGeocoderTests: XCTestCase {
func test_reverseGeocodeLocation() {
class MockGeocoder: CLGeocoder {
override func reverseGeocodeLocation(_ location: CLLocation, completionHandler: @escaping CLGeocodeCompletionHandler) {
after(.seconds(0)).done {
completionHandler([dummyPlacemark], nil)
}
}
}
let ex = expectation(description: "")
MockGeocoder().reverseGeocode(location: CLLocation()).done { x in
XCTAssertEqual(x, [dummyPlacemark])
ex.fulfill()
}
waitForExpectations(timeout: 1)
}
func test_geocodeAddressDictionary() {
class MockGeocoder: CLGeocoder {
override func geocodeAddressDictionary(_ addressDictionary: [AnyHashable : Any], completionHandler: @escaping CLGeocodeCompletionHandler) {
after(.seconds(0)).done {
completionHandler([dummyPlacemark], nil)
}
}
}
let ex = expectation(description: "")
MockGeocoder().geocode([:]).done { x in
XCTAssertEqual(x, [dummyPlacemark])
ex.fulfill()
}
waitForExpectations(timeout: 1)
}
func test_geocodeAddressString() {
class MockGeocoder: CLGeocoder {
override func geocodeAddressString(_ addressString: String, completionHandler: @escaping CLGeocodeCompletionHandler) {
after(.seconds(0)).done {
completionHandler([dummyPlacemark], nil)
}
}
}
let ex = expectation(description: "")
MockGeocoder().geocode("").done { x in
XCTAssertEqual(x, [dummyPlacemark])
ex.fulfill()
}
waitForExpectations(timeout: 1)
}
#if !os(tvOS) && swift(>=3.2)
func test_geocodePostalAddress() {
guard #available(iOS 11.0, OSX 10.13, watchOS 4.0, *) else { return }
class MockGeocoder: CLGeocoder {
override func geocodePostalAddress(_ postalAddress: CNPostalAddress, completionHandler: @escaping CLGeocodeCompletionHandler) {
after(.seconds(0)).done {
completionHandler([dummyPlacemark], nil)
}
}
}
let ex = expectation(description: "")
MockGeocoder().geocodePostalAddress(CNPostalAddress()).done { x in
XCTAssertEqual(x, [dummyPlacemark])
ex.fulfill()
}
waitForExpectations(timeout: 1)
}
func test_geocodePostalAddressLocale() {
guard #available(iOS 11.0, OSX 10.13, watchOS 4.0, *) else { return }
class MockGeocoder: CLGeocoder {
override func geocodePostalAddress(_ postalAddress: CNPostalAddress, preferredLocale locale: Locale?, completionHandler: @escaping CLGeocodeCompletionHandler) {
after(.seconds(0)).done {
completionHandler([dummyPlacemark], nil)
}
}
}
let ex = expectation(description: "")
MockGeocoder().geocodePostalAddress(CNPostalAddress(), preferredLocale: nil).done { x in
XCTAssertEqual(x, [dummyPlacemark])
ex.fulfill()
}
waitForExpectations(timeout: 1)
}
#endif
}
private let dummyPlacemark = CLPlacemark()

View File

@@ -0,0 +1,95 @@
import PMKCoreLocation
import CoreLocation
import PromiseKit
import XCTest
#if !os(tvOS)
class Test_CLLocationManager_Swift: XCTestCase {
func test_fulfills_with_multiple_locations() {
swizzle(CLLocationManager.self, #selector(CLLocationManager.startUpdatingLocation)) {
swizzle(CLLocationManager.self, #selector(CLLocationManager.authorizationStatus), isClassMethod: true) {
let ex = expectation(description: "")
CLLocationManager.requestLocation().done { x in
XCTAssertEqual(x, dummy)
ex.fulfill()
}
waitForExpectations(timeout: 1)
}
}
}
func test_fufillsWithSatisfyingBlock() {
swizzle(CLLocationManager.self, #selector(CLLocationManager.startUpdatingLocation)) {
swizzle(CLLocationManager.self, #selector(CLLocationManager.authorizationStatus), isClassMethod: true) {
let ex = expectation(description: "")
let block: ((CLLocation) -> Bool) = { location in
return location.coordinate.latitude == dummy.last?.coordinate.latitude
}
CLLocationManager.requestLocation(satisfying: block).done({ locations in
locations.forEach { XCTAssert(block($0) == true, "Block should be successful for returned values") }
ex.fulfill()
})
waitForExpectations(timeout: 1)
}
}
}
#if os(iOS)
func test_requestAuthorization() {
let ex = expectation(description: "")
CLLocationManager.requestAuthorization().done {
XCTAssertEqual($0, CLAuthorizationStatus.restricted)
ex.fulfill()
}
waitForExpectations(timeout: 1, handler: nil)
}
#endif
}
/////////////////////////////////////////////////////////////// resources
private let dummy = [CLLocation(latitude: 0, longitude: 0), CLLocation(latitude: 10, longitude: 20)]
extension CLLocationManager {
@objc func pmk_startUpdatingLocation() {
after(.milliseconds(100)).done {
self.delegate!.locationManager?(self, didUpdateLocations: dummy)
}
}
@objc static func pmk_authorizationStatus() -> CLAuthorizationStatus {
#if os(macOS)
return .authorized
#else
return .authorizedWhenInUse
#endif
}
}
/////////////////////////////////////////////////////////////// utilities
import ObjectiveC
func swizzle(_ foo: AnyClass, _ from: Selector, isClassMethod: Bool = false, body: () -> Void) {
let originalMethod: Method
let swizzledMethod: Method
if isClassMethod {
originalMethod = class_getClassMethod(foo, from)!
swizzledMethod = class_getClassMethod(foo, Selector("pmk_\(from)"))!
} else {
originalMethod = class_getInstanceMethod(foo, from)!
swizzledMethod = class_getInstanceMethod(foo, Selector("pmk_\(from)"))!
}
method_exchangeImplementations(originalMethod, swizzledMethod)
body()
method_exchangeImplementations(swizzledMethod, originalMethod)
}
#endif

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.private.tcc.allow</key>
<array>
<string>kTCCServiceAddressBook</string>
<string>kTCCServiceCalendar</string>
<string>kTCCServicePhotos</string>
</array>
</dict>
</plist>