├── .gitignore ├── .travis.yml ├── Cartfile ├── Example ├── NADocumentPicker.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ ├── NADocumentPicker-Example.xcscheme │ │ └── NADocumentPicker-Test.xcscheme ├── NADocumentPicker.xcworkspace │ └── contents.xcworkspacedata ├── NADocumentPicker │ ├── AppDelegate.swift │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ ├── ViewController.swift │ ├── iCloudException@1x.png │ ├── iCloudException@2x.png │ ├── iCloudFix@1x.png │ └── iCloudFix@2x.png ├── NADocumentPicker_Example.entitlements ├── Podfile ├── Podfile.lock ├── Pods │ ├── BrightFutures │ │ ├── LICENSE │ │ ├── README.md │ │ └── Sources │ │ │ └── BrightFutures │ │ │ ├── Async.swift │ │ │ ├── AsyncType+Debug.swift │ │ │ ├── AsyncType+ResultType.swift │ │ │ ├── AsyncType.swift │ │ │ ├── Dispatch+BrightFutures.swift │ │ │ ├── Errors.swift │ │ │ ├── ExecutionContext.swift │ │ │ ├── Future.swift │ │ │ ├── InvalidationToken.swift │ │ │ ├── MutableAsyncType+ResultType.swift │ │ │ ├── MutableAsyncType.swift │ │ │ ├── NSOperationQueue+BrightFutures.swift │ │ │ ├── Promise.swift │ │ │ ├── Result+BrightFutures.swift │ │ │ ├── ResultProtocol.swift │ │ │ └── SequenceType+BrightFutures.swift │ ├── Local Podspecs │ │ └── NADocumentPicker.podspec.json │ ├── Manifest.lock │ ├── Pods.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── Target Support Files │ │ ├── BrightFutures │ │ ├── BrightFutures-Info.plist │ │ ├── BrightFutures-dummy.m │ │ ├── BrightFutures-prefix.pch │ │ ├── BrightFutures-umbrella.h │ │ ├── BrightFutures.modulemap │ │ ├── BrightFutures.xcconfig │ │ └── Info.plist │ │ ├── NADocumentPicker │ │ ├── Info.plist │ │ ├── NADocumentPicker-Info.plist │ │ ├── NADocumentPicker-dummy.m │ │ ├── NADocumentPicker-prefix.pch │ │ ├── NADocumentPicker-umbrella.h │ │ ├── NADocumentPicker.modulemap │ │ └── NADocumentPicker.xcconfig │ │ ├── Pods-NADocumentPicker_Example │ │ ├── Info.plist │ │ ├── Pods-NADocumentPicker_Example-Info.plist │ │ ├── Pods-NADocumentPicker_Example-acknowledgements.markdown │ │ ├── Pods-NADocumentPicker_Example-acknowledgements.plist │ │ ├── Pods-NADocumentPicker_Example-dummy.m │ │ ├── Pods-NADocumentPicker_Example-frameworks.sh │ │ ├── Pods-NADocumentPicker_Example-resources.sh │ │ ├── Pods-NADocumentPicker_Example-umbrella.h │ │ ├── Pods-NADocumentPicker_Example.debug.xcconfig │ │ ├── Pods-NADocumentPicker_Example.modulemap │ │ └── Pods-NADocumentPicker_Example.release.xcconfig │ │ └── Pods-NADocumentPicker_Tests │ │ ├── Info.plist │ │ ├── Pods-NADocumentPicker_Tests-Info.plist │ │ ├── Pods-NADocumentPicker_Tests-acknowledgements.markdown │ │ ├── Pods-NADocumentPicker_Tests-acknowledgements.plist │ │ ├── Pods-NADocumentPicker_Tests-dummy.m │ │ ├── Pods-NADocumentPicker_Tests-frameworks.sh │ │ ├── Pods-NADocumentPicker_Tests-resources.sh │ │ ├── Pods-NADocumentPicker_Tests-umbrella.h │ │ ├── Pods-NADocumentPicker_Tests.debug.xcconfig │ │ ├── Pods-NADocumentPicker_Tests.modulemap │ │ └── Pods-NADocumentPicker_Tests.release.xcconfig └── Tests │ ├── Info.plist │ └── Tests.swift ├── LICENSE ├── NADocumentPicker.podspec ├── Package.swift ├── Pod ├── Assets │ └── .gitkeep └── Classes │ ├── .gitkeep │ └── NADocumentPicker.swift ├── README.md └── _Pods.xcodeproj /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | # 6 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 7 | 8 | ## Build generated 9 | build/ 10 | DerivedData 11 | 12 | ## Various settings 13 | *.pbxuser 14 | !default.pbxuser 15 | *.mode1v3 16 | !default.mode1v3 17 | *.mode2v3 18 | !default.mode2v3 19 | *.perspectivev3 20 | !default.perspectivev3 21 | xcuserdata 22 | 23 | ## Other 24 | *.xccheckout 25 | profile 26 | *.moved-aside 27 | *.xcuserstate 28 | *.xcscmblueprint 29 | 30 | ## Obj-C/Swift specific 31 | *.hmap 32 | *.ipa 33 | 34 | ## Playgrounds 35 | timeline.xctimeline 36 | playground.xcworkspace 37 | 38 | # Swift Package Manager 39 | # 40 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 41 | # Packages/ 42 | .build/ 43 | 44 | # CocoaPods 45 | # 46 | # We recommend against adding the Pods directory to your .gitignore. However 47 | # you should judge for yourself, the pros and cons are mentioned at: 48 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 49 | # 50 | # Pods/ 51 | 52 | # Carthage 53 | # 54 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 55 | # Carthage/Checkouts 56 | 57 | Carthage/Build 58 | 59 | # fastlane 60 | # 61 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 62 | # screenshots whenever they are needed. 63 | # For more information about the recommended setup visit: 64 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md 65 | 66 | fastlane/report.xml 67 | fastlane/screenshots 68 | IDEWorkspaceChecks.plist 69 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # references: 2 | # * http://www.objc.io/issue-6/travis-ci.html 3 | # * https://github.com/supermarin/xcpretty#usage 4 | 5 | language: objective-c 6 | osx_image: xcode10.1 7 | podfile: Example/Podfile 8 | before_install: 9 | - rvm install 2.1.5 10 | - gem install cocoapods # Since Travis is not always on latest version 11 | - pod install --project-directory=Example 12 | 13 | script: 14 | - set -o pipefail && xcodebuild -workspace Example/NADocumentPicker.xcworkspace -scheme NADocumentPicker -configuration Debug -destination 'platform=iOS Simulator,name=iPhone 8,OS=11.0' -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO 15 | - pod lib lint 16 | -------------------------------------------------------------------------------- /Cartfile: -------------------------------------------------------------------------------- 1 | github "Thomvis/BrightFutures" ~> 8 2 | -------------------------------------------------------------------------------- /Example/NADocumentPicker.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0AAC10F8BE5A4EF79EB03D83 /* Pods_NADocumentPicker_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A4D030C8FD73BE8167EA4B31 /* Pods_NADocumentPicker_Example.framework */; }; 11 | 602D82036B2CE295E9990068 /* Pods_NADocumentPicker_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B30C443872967EEF8BB6A317 /* Pods_NADocumentPicker_Tests.framework */; }; 12 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; }; 13 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* ViewController.swift */; }; 14 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; }; 15 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; 16 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; 17 | 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* Tests.swift */; }; 18 | 848ED5781C905EF800EC5B59 /* iCloudException@1x.png in Resources */ = {isa = PBXBuildFile; fileRef = 848ED5741C905EF800EC5B59 /* iCloudException@1x.png */; }; 19 | 848ED5791C905EF800EC5B59 /* iCloudException@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 848ED5751C905EF800EC5B59 /* iCloudException@2x.png */; }; 20 | 848ED57A1C905EF800EC5B59 /* iCloudFix@1x.png in Resources */ = {isa = PBXBuildFile; fileRef = 848ED5761C905EF800EC5B59 /* iCloudFix@1x.png */; }; 21 | 848ED57B1C905EF800EC5B59 /* iCloudFix@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 848ED5771C905EF800EC5B59 /* iCloudFix@2x.png */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXContainerItemProxy section */ 25 | 840917DC1F151B9000238024 /* PBXContainerItemProxy */ = { 26 | isa = PBXContainerItemProxy; 27 | containerPortal = 607FACC81AFB9204008FA782 /* Project object */; 28 | proxyType = 1; 29 | remoteGlobalIDString = 607FACCF1AFB9204008FA782; 30 | remoteInfo = NADocumentPicker_Example; 31 | }; 32 | /* End PBXContainerItemProxy section */ 33 | 34 | /* Begin PBXFileReference section */ 35 | 162E060299001E6BC12C827D /* Pods-NADocumentPicker_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NADocumentPicker_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-NADocumentPicker_Tests/Pods-NADocumentPicker_Tests.release.xcconfig"; sourceTree = ""; }; 36 | 607FACD01AFB9204008FA782 /* NADocumentPicker_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NADocumentPicker_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 37 | 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 38 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 39 | 607FACD71AFB9204008FA782 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 40 | 607FACDA1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 41 | 607FACDC1AFB9204008FA782 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 42 | 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 43 | 607FACE51AFB9204008FA782 /* NADocumentPicker_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NADocumentPicker_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | 607FACEB1AFB9204008FA782 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; 46 | 6C429464C31F57D64E84CF74 /* Pods-NADocumentPicker_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NADocumentPicker_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-NADocumentPicker_Tests/Pods-NADocumentPicker_Tests.debug.xcconfig"; sourceTree = ""; }; 47 | 848ED5741C905EF800EC5B59 /* iCloudException@1x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iCloudException@1x.png"; sourceTree = ""; }; 48 | 848ED5751C905EF800EC5B59 /* iCloudException@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iCloudException@2x.png"; sourceTree = ""; }; 49 | 848ED5761C905EF800EC5B59 /* iCloudFix@1x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iCloudFix@1x.png"; sourceTree = ""; }; 50 | 848ED5771C905EF800EC5B59 /* iCloudFix@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iCloudFix@2x.png"; sourceTree = ""; }; 51 | 848ED57E1C906AC500EC5B59 /* NADocumentPicker_Example.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = NADocumentPicker_Example.entitlements; sourceTree = ""; }; 52 | 8FD5DC03191474A44BB14DCC /* NADocumentPicker.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = NADocumentPicker.podspec; path = ../NADocumentPicker.podspec; sourceTree = ""; }; 53 | 90CADC6D5FFB29903F4CCD7C /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 54 | A4D030C8FD73BE8167EA4B31 /* Pods_NADocumentPicker_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NADocumentPicker_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 55 | B30C443872967EEF8BB6A317 /* Pods_NADocumentPicker_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NADocumentPicker_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 56 | B9D36CF362A36853CD2B4587 /* Pods-NADocumentPicker_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NADocumentPicker_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-NADocumentPicker_Example/Pods-NADocumentPicker_Example.debug.xcconfig"; sourceTree = ""; }; 57 | BBDE5AEBFE67B7D3245E1240 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 58 | DD12931040B61DBAE6692EDB /* Pods-NADocumentPicker_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NADocumentPicker_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-NADocumentPicker_Example/Pods-NADocumentPicker_Example.release.xcconfig"; sourceTree = ""; }; 59 | /* End PBXFileReference section */ 60 | 61 | /* Begin PBXFrameworksBuildPhase section */ 62 | 607FACCD1AFB9204008FA782 /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | 0AAC10F8BE5A4EF79EB03D83 /* Pods_NADocumentPicker_Example.framework in Frameworks */, 67 | ); 68 | runOnlyForDeploymentPostprocessing = 0; 69 | }; 70 | 607FACE21AFB9204008FA782 /* Frameworks */ = { 71 | isa = PBXFrameworksBuildPhase; 72 | buildActionMask = 2147483647; 73 | files = ( 74 | 602D82036B2CE295E9990068 /* Pods_NADocumentPicker_Tests.framework in Frameworks */, 75 | ); 76 | runOnlyForDeploymentPostprocessing = 0; 77 | }; 78 | /* End PBXFrameworksBuildPhase section */ 79 | 80 | /* Begin PBXGroup section */ 81 | 607FACC71AFB9204008FA782 = { 82 | isa = PBXGroup; 83 | children = ( 84 | 848ED57E1C906AC500EC5B59 /* NADocumentPicker_Example.entitlements */, 85 | 607FACF51AFB993E008FA782 /* Podspec Metadata */, 86 | 607FACD21AFB9204008FA782 /* Example for NADocumentPicker */, 87 | 607FACE81AFB9204008FA782 /* Tests */, 88 | 607FACD11AFB9204008FA782 /* Products */, 89 | 91E43332BCA9A879DD89507A /* Pods */, 90 | 951F3FD42AEED247392D0411 /* Frameworks */, 91 | ); 92 | sourceTree = ""; 93 | }; 94 | 607FACD11AFB9204008FA782 /* Products */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | 607FACD01AFB9204008FA782 /* NADocumentPicker_Example.app */, 98 | 607FACE51AFB9204008FA782 /* NADocumentPicker_Tests.xctest */, 99 | ); 100 | name = Products; 101 | sourceTree = ""; 102 | }; 103 | 607FACD21AFB9204008FA782 /* Example for NADocumentPicker */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */, 107 | 607FACD71AFB9204008FA782 /* ViewController.swift */, 108 | 607FACD91AFB9204008FA782 /* Main.storyboard */, 109 | 607FACDC1AFB9204008FA782 /* Images.xcassets */, 110 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */, 111 | 607FACD31AFB9204008FA782 /* Supporting Files */, 112 | ); 113 | name = "Example for NADocumentPicker"; 114 | path = NADocumentPicker; 115 | sourceTree = ""; 116 | }; 117 | 607FACD31AFB9204008FA782 /* Supporting Files */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 848ED5741C905EF800EC5B59 /* iCloudException@1x.png */, 121 | 848ED5751C905EF800EC5B59 /* iCloudException@2x.png */, 122 | 848ED5761C905EF800EC5B59 /* iCloudFix@1x.png */, 123 | 848ED5771C905EF800EC5B59 /* iCloudFix@2x.png */, 124 | 607FACD41AFB9204008FA782 /* Info.plist */, 125 | ); 126 | name = "Supporting Files"; 127 | sourceTree = ""; 128 | }; 129 | 607FACE81AFB9204008FA782 /* Tests */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | 607FACEB1AFB9204008FA782 /* Tests.swift */, 133 | 607FACE91AFB9204008FA782 /* Supporting Files */, 134 | ); 135 | path = Tests; 136 | sourceTree = ""; 137 | }; 138 | 607FACE91AFB9204008FA782 /* Supporting Files */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | 607FACEA1AFB9204008FA782 /* Info.plist */, 142 | ); 143 | name = "Supporting Files"; 144 | sourceTree = ""; 145 | }; 146 | 607FACF51AFB993E008FA782 /* Podspec Metadata */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | 8FD5DC03191474A44BB14DCC /* NADocumentPicker.podspec */, 150 | BBDE5AEBFE67B7D3245E1240 /* README.md */, 151 | 90CADC6D5FFB29903F4CCD7C /* LICENSE */, 152 | ); 153 | name = "Podspec Metadata"; 154 | sourceTree = ""; 155 | }; 156 | 91E43332BCA9A879DD89507A /* Pods */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | B9D36CF362A36853CD2B4587 /* Pods-NADocumentPicker_Example.debug.xcconfig */, 160 | DD12931040B61DBAE6692EDB /* Pods-NADocumentPicker_Example.release.xcconfig */, 161 | 6C429464C31F57D64E84CF74 /* Pods-NADocumentPicker_Tests.debug.xcconfig */, 162 | 162E060299001E6BC12C827D /* Pods-NADocumentPicker_Tests.release.xcconfig */, 163 | ); 164 | name = Pods; 165 | sourceTree = ""; 166 | }; 167 | 951F3FD42AEED247392D0411 /* Frameworks */ = { 168 | isa = PBXGroup; 169 | children = ( 170 | A4D030C8FD73BE8167EA4B31 /* Pods_NADocumentPicker_Example.framework */, 171 | B30C443872967EEF8BB6A317 /* Pods_NADocumentPicker_Tests.framework */, 172 | ); 173 | name = Frameworks; 174 | sourceTree = ""; 175 | }; 176 | /* End PBXGroup section */ 177 | 178 | /* Begin PBXNativeTarget section */ 179 | 607FACCF1AFB9204008FA782 /* NADocumentPicker_Example */ = { 180 | isa = PBXNativeTarget; 181 | buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "NADocumentPicker_Example" */; 182 | buildPhases = ( 183 | A5B2AED4339E79D1AE4A596C /* [CP] Check Pods Manifest.lock */, 184 | 607FACCC1AFB9204008FA782 /* Sources */, 185 | 607FACCD1AFB9204008FA782 /* Frameworks */, 186 | 607FACCE1AFB9204008FA782 /* Resources */, 187 | A80D0982EED2125C1E1CD5B3 /* [CP] Embed Pods Frameworks */, 188 | ); 189 | buildRules = ( 190 | ); 191 | dependencies = ( 192 | ); 193 | name = NADocumentPicker_Example; 194 | productName = NADocumentPicker; 195 | productReference = 607FACD01AFB9204008FA782 /* NADocumentPicker_Example.app */; 196 | productType = "com.apple.product-type.application"; 197 | }; 198 | 607FACE41AFB9204008FA782 /* NADocumentPicker_Tests */ = { 199 | isa = PBXNativeTarget; 200 | buildConfigurationList = 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "NADocumentPicker_Tests" */; 201 | buildPhases = ( 202 | 96386964A268A1232D412346 /* [CP] Check Pods Manifest.lock */, 203 | 607FACE11AFB9204008FA782 /* Sources */, 204 | 607FACE21AFB9204008FA782 /* Frameworks */, 205 | 607FACE31AFB9204008FA782 /* Resources */, 206 | ); 207 | buildRules = ( 208 | ); 209 | dependencies = ( 210 | 840917DD1F151B9000238024 /* PBXTargetDependency */, 211 | ); 212 | name = NADocumentPicker_Tests; 213 | productName = Tests; 214 | productReference = 607FACE51AFB9204008FA782 /* NADocumentPicker_Tests.xctest */; 215 | productType = "com.apple.product-type.bundle.unit-test"; 216 | }; 217 | /* End PBXNativeTarget section */ 218 | 219 | /* Begin PBXProject section */ 220 | 607FACC81AFB9204008FA782 /* Project object */ = { 221 | isa = PBXProject; 222 | attributes = { 223 | LastSwiftUpdateCheck = 0720; 224 | LastUpgradeCheck = 1020; 225 | ORGANIZATIONNAME = CocoaPods; 226 | TargetAttributes = { 227 | 607FACCF1AFB9204008FA782 = { 228 | CreatedOnToolsVersion = 6.3.1; 229 | DevelopmentTeam = Q32H5S9R95; 230 | LastSwiftMigration = 1020; 231 | ProvisioningStyle = Automatic; 232 | SystemCapabilities = { 233 | com.apple.iCloud = { 234 | enabled = 1; 235 | }; 236 | }; 237 | }; 238 | 607FACE41AFB9204008FA782 = { 239 | CreatedOnToolsVersion = 6.3.1; 240 | DevelopmentTeam = Q32H5S9R95; 241 | LastSwiftMigration = 1020; 242 | TestTargetID = 607FACCF1AFB9204008FA782; 243 | }; 244 | }; 245 | }; 246 | buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "NADocumentPicker" */; 247 | compatibilityVersion = "Xcode 3.2"; 248 | developmentRegion = en; 249 | hasScannedForEncodings = 0; 250 | knownRegions = ( 251 | en, 252 | Base, 253 | ); 254 | mainGroup = 607FACC71AFB9204008FA782; 255 | productRefGroup = 607FACD11AFB9204008FA782 /* Products */; 256 | projectDirPath = ""; 257 | projectRoot = ""; 258 | targets = ( 259 | 607FACCF1AFB9204008FA782 /* NADocumentPicker_Example */, 260 | 607FACE41AFB9204008FA782 /* NADocumentPicker_Tests */, 261 | ); 262 | }; 263 | /* End PBXProject section */ 264 | 265 | /* Begin PBXResourcesBuildPhase section */ 266 | 607FACCE1AFB9204008FA782 /* Resources */ = { 267 | isa = PBXResourcesBuildPhase; 268 | buildActionMask = 2147483647; 269 | files = ( 270 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */, 271 | 848ED5791C905EF800EC5B59 /* iCloudException@2x.png in Resources */, 272 | 848ED5781C905EF800EC5B59 /* iCloudException@1x.png in Resources */, 273 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */, 274 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */, 275 | 848ED57B1C905EF800EC5B59 /* iCloudFix@2x.png in Resources */, 276 | 848ED57A1C905EF800EC5B59 /* iCloudFix@1x.png in Resources */, 277 | ); 278 | runOnlyForDeploymentPostprocessing = 0; 279 | }; 280 | 607FACE31AFB9204008FA782 /* Resources */ = { 281 | isa = PBXResourcesBuildPhase; 282 | buildActionMask = 2147483647; 283 | files = ( 284 | ); 285 | runOnlyForDeploymentPostprocessing = 0; 286 | }; 287 | /* End PBXResourcesBuildPhase section */ 288 | 289 | /* Begin PBXShellScriptBuildPhase section */ 290 | 96386964A268A1232D412346 /* [CP] Check Pods Manifest.lock */ = { 291 | isa = PBXShellScriptBuildPhase; 292 | buildActionMask = 2147483647; 293 | files = ( 294 | ); 295 | inputPaths = ( 296 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 297 | "${PODS_ROOT}/Manifest.lock", 298 | ); 299 | name = "[CP] Check Pods Manifest.lock"; 300 | outputPaths = ( 301 | "$(DERIVED_FILE_DIR)/Pods-NADocumentPicker_Tests-checkManifestLockResult.txt", 302 | ); 303 | runOnlyForDeploymentPostprocessing = 0; 304 | shellPath = /bin/sh; 305 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 306 | showEnvVarsInLog = 0; 307 | }; 308 | A5B2AED4339E79D1AE4A596C /* [CP] Check Pods Manifest.lock */ = { 309 | isa = PBXShellScriptBuildPhase; 310 | buildActionMask = 2147483647; 311 | files = ( 312 | ); 313 | inputPaths = ( 314 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 315 | "${PODS_ROOT}/Manifest.lock", 316 | ); 317 | name = "[CP] Check Pods Manifest.lock"; 318 | outputPaths = ( 319 | "$(DERIVED_FILE_DIR)/Pods-NADocumentPicker_Example-checkManifestLockResult.txt", 320 | ); 321 | runOnlyForDeploymentPostprocessing = 0; 322 | shellPath = /bin/sh; 323 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 324 | showEnvVarsInLog = 0; 325 | }; 326 | A80D0982EED2125C1E1CD5B3 /* [CP] Embed Pods Frameworks */ = { 327 | isa = PBXShellScriptBuildPhase; 328 | buildActionMask = 2147483647; 329 | files = ( 330 | ); 331 | inputPaths = ( 332 | "${PODS_ROOT}/Target Support Files/Pods-NADocumentPicker_Example/Pods-NADocumentPicker_Example-frameworks.sh", 333 | "${BUILT_PRODUCTS_DIR}/BrightFutures/BrightFutures.framework", 334 | "${BUILT_PRODUCTS_DIR}/NADocumentPicker/NADocumentPicker.framework", 335 | ); 336 | name = "[CP] Embed Pods Frameworks"; 337 | outputPaths = ( 338 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BrightFutures.framework", 339 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/NADocumentPicker.framework", 340 | ); 341 | runOnlyForDeploymentPostprocessing = 0; 342 | shellPath = /bin/sh; 343 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NADocumentPicker_Example/Pods-NADocumentPicker_Example-frameworks.sh\"\n"; 344 | showEnvVarsInLog = 0; 345 | }; 346 | /* End PBXShellScriptBuildPhase section */ 347 | 348 | /* Begin PBXSourcesBuildPhase section */ 349 | 607FACCC1AFB9204008FA782 /* Sources */ = { 350 | isa = PBXSourcesBuildPhase; 351 | buildActionMask = 2147483647; 352 | files = ( 353 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */, 354 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, 355 | ); 356 | runOnlyForDeploymentPostprocessing = 0; 357 | }; 358 | 607FACE11AFB9204008FA782 /* Sources */ = { 359 | isa = PBXSourcesBuildPhase; 360 | buildActionMask = 2147483647; 361 | files = ( 362 | 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */, 363 | ); 364 | runOnlyForDeploymentPostprocessing = 0; 365 | }; 366 | /* End PBXSourcesBuildPhase section */ 367 | 368 | /* Begin PBXTargetDependency section */ 369 | 840917DD1F151B9000238024 /* PBXTargetDependency */ = { 370 | isa = PBXTargetDependency; 371 | target = 607FACCF1AFB9204008FA782 /* NADocumentPicker_Example */; 372 | targetProxy = 840917DC1F151B9000238024 /* PBXContainerItemProxy */; 373 | }; 374 | /* End PBXTargetDependency section */ 375 | 376 | /* Begin PBXVariantGroup section */ 377 | 607FACD91AFB9204008FA782 /* Main.storyboard */ = { 378 | isa = PBXVariantGroup; 379 | children = ( 380 | 607FACDA1AFB9204008FA782 /* Base */, 381 | ); 382 | name = Main.storyboard; 383 | sourceTree = ""; 384 | }; 385 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */ = { 386 | isa = PBXVariantGroup; 387 | children = ( 388 | 607FACDF1AFB9204008FA782 /* Base */, 389 | ); 390 | name = LaunchScreen.xib; 391 | sourceTree = ""; 392 | }; 393 | /* End PBXVariantGroup section */ 394 | 395 | /* Begin XCBuildConfiguration section */ 396 | 607FACED1AFB9204008FA782 /* Debug */ = { 397 | isa = XCBuildConfiguration; 398 | buildSettings = { 399 | ALWAYS_SEARCH_USER_PATHS = NO; 400 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 401 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 402 | CLANG_CXX_LIBRARY = "libc++"; 403 | CLANG_ENABLE_MODULES = YES; 404 | CLANG_ENABLE_OBJC_ARC = YES; 405 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 406 | CLANG_WARN_BOOL_CONVERSION = YES; 407 | CLANG_WARN_COMMA = YES; 408 | CLANG_WARN_CONSTANT_CONVERSION = YES; 409 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 410 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 411 | CLANG_WARN_EMPTY_BODY = YES; 412 | CLANG_WARN_ENUM_CONVERSION = YES; 413 | CLANG_WARN_INFINITE_RECURSION = YES; 414 | CLANG_WARN_INT_CONVERSION = YES; 415 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 416 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 417 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 418 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 419 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 420 | CLANG_WARN_STRICT_PROTOTYPES = YES; 421 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 422 | CLANG_WARN_UNREACHABLE_CODE = YES; 423 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 424 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 425 | COPY_PHASE_STRIP = NO; 426 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 427 | DEFINES_MODULE = YES; 428 | ENABLE_STRICT_OBJC_MSGSEND = YES; 429 | ENABLE_TESTABILITY = YES; 430 | GCC_C_LANGUAGE_STANDARD = gnu99; 431 | GCC_DYNAMIC_NO_PIC = NO; 432 | GCC_NO_COMMON_BLOCKS = YES; 433 | GCC_OPTIMIZATION_LEVEL = 0; 434 | GCC_PREPROCESSOR_DEFINITIONS = ( 435 | "DEBUG=1", 436 | "$(inherited)", 437 | ); 438 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 439 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 440 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 441 | GCC_WARN_UNDECLARED_SELECTOR = YES; 442 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 443 | GCC_WARN_UNUSED_FUNCTION = YES; 444 | GCC_WARN_UNUSED_VARIABLE = YES; 445 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 446 | MTL_ENABLE_DEBUG_INFO = YES; 447 | ONLY_ACTIVE_ARCH = YES; 448 | PRODUCT_MODULE_NAME = "$(PRODUCT_NAME)"; 449 | SDKROOT = iphoneos; 450 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 451 | SWIFT_VERSION = 4.2; 452 | }; 453 | name = Debug; 454 | }; 455 | 607FACEE1AFB9204008FA782 /* Release */ = { 456 | isa = XCBuildConfiguration; 457 | buildSettings = { 458 | ALWAYS_SEARCH_USER_PATHS = NO; 459 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 460 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 461 | CLANG_CXX_LIBRARY = "libc++"; 462 | CLANG_ENABLE_MODULES = YES; 463 | CLANG_ENABLE_OBJC_ARC = YES; 464 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 465 | CLANG_WARN_BOOL_CONVERSION = YES; 466 | CLANG_WARN_COMMA = YES; 467 | CLANG_WARN_CONSTANT_CONVERSION = YES; 468 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 469 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 470 | CLANG_WARN_EMPTY_BODY = YES; 471 | CLANG_WARN_ENUM_CONVERSION = YES; 472 | CLANG_WARN_INFINITE_RECURSION = YES; 473 | CLANG_WARN_INT_CONVERSION = YES; 474 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 475 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 476 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 477 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 478 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 479 | CLANG_WARN_STRICT_PROTOTYPES = YES; 480 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 481 | CLANG_WARN_UNREACHABLE_CODE = YES; 482 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 483 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 484 | COPY_PHASE_STRIP = NO; 485 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 486 | DEFINES_MODULE = YES; 487 | ENABLE_NS_ASSERTIONS = NO; 488 | ENABLE_STRICT_OBJC_MSGSEND = YES; 489 | ENABLE_TESTABILITY = NO; 490 | GCC_C_LANGUAGE_STANDARD = gnu99; 491 | GCC_NO_COMMON_BLOCKS = YES; 492 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 493 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 494 | GCC_WARN_UNDECLARED_SELECTOR = YES; 495 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 496 | GCC_WARN_UNUSED_FUNCTION = YES; 497 | GCC_WARN_UNUSED_VARIABLE = YES; 498 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 499 | MTL_ENABLE_DEBUG_INFO = NO; 500 | PRODUCT_MODULE_NAME = "$(PRODUCT_NAME)"; 501 | SDKROOT = iphoneos; 502 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 503 | SWIFT_VERSION = 4.2; 504 | VALIDATE_PRODUCT = YES; 505 | }; 506 | name = Release; 507 | }; 508 | 607FACF01AFB9204008FA782 /* Debug */ = { 509 | isa = XCBuildConfiguration; 510 | baseConfigurationReference = B9D36CF362A36853CD2B4587 /* Pods-NADocumentPicker_Example.debug.xcconfig */; 511 | buildSettings = { 512 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 513 | CODE_SIGN_ENTITLEMENTS = NADocumentPicker_Example.entitlements; 514 | CODE_SIGN_IDENTITY = "iPhone Developer"; 515 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 516 | DEVELOPMENT_TEAM = Q32H5S9R95; 517 | INFOPLIST_FILE = NADocumentPicker/Info.plist; 518 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 519 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 520 | MODULE_NAME = ExampleApp; 521 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; 522 | PRODUCT_NAME = "$(TARGET_NAME)"; 523 | PROVISIONING_PROFILE = ""; 524 | PROVISIONING_PROFILE_SPECIFIER = ""; 525 | SWIFT_VERSION = 5.0; 526 | TARGETED_DEVICE_FAMILY = "1,2"; 527 | }; 528 | name = Debug; 529 | }; 530 | 607FACF11AFB9204008FA782 /* Release */ = { 531 | isa = XCBuildConfiguration; 532 | baseConfigurationReference = DD12931040B61DBAE6692EDB /* Pods-NADocumentPicker_Example.release.xcconfig */; 533 | buildSettings = { 534 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 535 | CODE_SIGN_ENTITLEMENTS = NADocumentPicker_Example.entitlements; 536 | CODE_SIGN_IDENTITY = "iPhone Developer"; 537 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 538 | DEVELOPMENT_TEAM = Q32H5S9R95; 539 | INFOPLIST_FILE = NADocumentPicker/Info.plist; 540 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 541 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 542 | MODULE_NAME = ExampleApp; 543 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; 544 | PRODUCT_NAME = "$(TARGET_NAME)"; 545 | PROVISIONING_PROFILE = ""; 546 | PROVISIONING_PROFILE_SPECIFIER = ""; 547 | SWIFT_VERSION = 5.0; 548 | TARGETED_DEVICE_FAMILY = "1,2"; 549 | }; 550 | name = Release; 551 | }; 552 | 607FACF31AFB9204008FA782 /* Debug */ = { 553 | isa = XCBuildConfiguration; 554 | baseConfigurationReference = 6C429464C31F57D64E84CF74 /* Pods-NADocumentPicker_Tests.debug.xcconfig */; 555 | buildSettings = { 556 | BUNDLE_LOADER = "$(TEST_HOST)"; 557 | DEVELOPMENT_TEAM = Q32H5S9R95; 558 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 559 | GCC_PREPROCESSOR_DEFINITIONS = ( 560 | "DEBUG=1", 561 | "$(inherited)", 562 | ); 563 | INFOPLIST_FILE = Tests/Info.plist; 564 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 565 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; 566 | PRODUCT_NAME = "$(TARGET_NAME)"; 567 | SWIFT_VERSION = 5.0; 568 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NADocumentPicker_Example.app/NADocumentPicker_Example"; 569 | }; 570 | name = Debug; 571 | }; 572 | 607FACF41AFB9204008FA782 /* Release */ = { 573 | isa = XCBuildConfiguration; 574 | baseConfigurationReference = 162E060299001E6BC12C827D /* Pods-NADocumentPicker_Tests.release.xcconfig */; 575 | buildSettings = { 576 | BUNDLE_LOADER = "$(TEST_HOST)"; 577 | DEVELOPMENT_TEAM = Q32H5S9R95; 578 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 579 | INFOPLIST_FILE = Tests/Info.plist; 580 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 581 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; 582 | PRODUCT_NAME = "$(TARGET_NAME)"; 583 | SWIFT_VERSION = 5.0; 584 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NADocumentPicker_Example.app/NADocumentPicker_Example"; 585 | }; 586 | name = Release; 587 | }; 588 | /* End XCBuildConfiguration section */ 589 | 590 | /* Begin XCConfigurationList section */ 591 | 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "NADocumentPicker" */ = { 592 | isa = XCConfigurationList; 593 | buildConfigurations = ( 594 | 607FACED1AFB9204008FA782 /* Debug */, 595 | 607FACEE1AFB9204008FA782 /* Release */, 596 | ); 597 | defaultConfigurationIsVisible = 0; 598 | defaultConfigurationName = Release; 599 | }; 600 | 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "NADocumentPicker_Example" */ = { 601 | isa = XCConfigurationList; 602 | buildConfigurations = ( 603 | 607FACF01AFB9204008FA782 /* Debug */, 604 | 607FACF11AFB9204008FA782 /* Release */, 605 | ); 606 | defaultConfigurationIsVisible = 0; 607 | defaultConfigurationName = Release; 608 | }; 609 | 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "NADocumentPicker_Tests" */ = { 610 | isa = XCConfigurationList; 611 | buildConfigurations = ( 612 | 607FACF31AFB9204008FA782 /* Debug */, 613 | 607FACF41AFB9204008FA782 /* Release */, 614 | ); 615 | defaultConfigurationIsVisible = 0; 616 | defaultConfigurationName = Release; 617 | }; 618 | /* End XCConfigurationList section */ 619 | }; 620 | rootObject = 607FACC81AFB9204008FA782 /* Project object */; 621 | } 622 | -------------------------------------------------------------------------------- /Example/NADocumentPicker.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/NADocumentPicker.xcodeproj/xcshareddata/xcschemes/NADocumentPicker-Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 78 | 80 | 86 | 87 | 88 | 89 | 90 | 91 | 97 | 99 | 105 | 106 | 107 | 108 | 110 | 111 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /Example/NADocumentPicker.xcodeproj/xcshareddata/xcschemes/NADocumentPicker-Test.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 78 | 79 | 80 | 81 | 87 | 88 | 90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /Example/NADocumentPicker.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/NADocumentPicker/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // NADocumentPicker 4 | // 5 | // Created by Nick Ager on 03/09/2016. 6 | // Copyright (c) 2016 Nick Ager. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | func applicationWillResignActive(_ application: UIApplication) { 22 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 23 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 24 | } 25 | 26 | func applicationDidEnterBackground(_ application: UIApplication) { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | func applicationWillEnterForeground(_ application: UIApplication) { 32 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 33 | } 34 | 35 | func applicationDidBecomeActive(_ application: UIApplication) { 36 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 37 | } 38 | 39 | func applicationWillTerminate(_ application: UIApplication) { 40 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /Example/NADocumentPicker/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 24 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Example/NADocumentPicker/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 30 | 40 | 41 | 42 | 43 | 44 | 45 | See also: 46 | 47 | * NADocumentPicker on Github for details of the entitlements you need to add to your application - 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | * Blog post on 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /Example/NADocumentPicker/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Example/NADocumentPicker/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationPortraitUpsideDown 38 | UIInterfaceOrientationLandscapeRight 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Example/NADocumentPicker/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // NADocumentPicker 4 | // 5 | // Created by Nick Ager on 03/09/2016. 6 | // Copyright (c) 2016 Nick Ager. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import NADocumentPicker 11 | import BrightFutures 12 | 13 | class ViewController: UIViewController { 14 | 15 | @IBOutlet var filePickedLabel: UILabel! 16 | 17 | @IBAction func pickerButtonPressed(_ sender: UIButton) { 18 | let urlPickedfuture = NADocumentPicker.show(from: sender, parentViewController: self) 19 | 20 | urlPickedfuture.onSuccess { url in 21 | self.filePickedLabel.text = "URL: \(url)" 22 | }.onFailure { (error) in 23 | self.filePickedLabel.text = "No document picked, return code: '\(error)'" 24 | } 25 | } 26 | 27 | } 28 | 29 | -------------------------------------------------------------------------------- /Example/NADocumentPicker/iCloudException@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NickAger/NADocumentPicker/382d746a347fdde42a85db6101dcfa4fdb52b9e0/Example/NADocumentPicker/iCloudException@1x.png -------------------------------------------------------------------------------- /Example/NADocumentPicker/iCloudException@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NickAger/NADocumentPicker/382d746a347fdde42a85db6101dcfa4fdb52b9e0/Example/NADocumentPicker/iCloudException@2x.png -------------------------------------------------------------------------------- /Example/NADocumentPicker/iCloudFix@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NickAger/NADocumentPicker/382d746a347fdde42a85db6101dcfa4fdb52b9e0/Example/NADocumentPicker/iCloudFix@1x.png -------------------------------------------------------------------------------- /Example/NADocumentPicker/iCloudFix@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NickAger/NADocumentPicker/382d746a347fdde42a85db6101dcfa4fdb52b9e0/Example/NADocumentPicker/iCloudFix@2x.png -------------------------------------------------------------------------------- /Example/NADocumentPicker_Example.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.icloud-container-identifiers 6 | 7 | iCloud.$(CFBundleIdentifier) 8 | 9 | com.apple.developer.icloud-services 10 | 11 | CloudDocuments 12 | 13 | com.apple.developer.ubiquity-container-identifiers 14 | 15 | iCloud.$(CFBundleIdentifier) 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | platform :ios, '12.0' 3 | 4 | target 'NADocumentPicker_Example' do 5 | use_frameworks! 6 | 7 | pod 'BrightFutures' 8 | pod 'NADocumentPicker', :path => '../' 9 | 10 | target 'NADocumentPicker_Tests' do 11 | inherit! :search_paths 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - BrightFutures (8.0.0) 3 | - NADocumentPicker (3.2.0): 4 | - BrightFutures 5 | 6 | DEPENDENCIES: 7 | - BrightFutures 8 | - NADocumentPicker (from `../`) 9 | 10 | SPEC REPOS: 11 | https://github.com/cocoapods/specs.git: 12 | - BrightFutures 13 | 14 | EXTERNAL SOURCES: 15 | NADocumentPicker: 16 | :path: "../" 17 | 18 | SPEC CHECKSUMS: 19 | BrightFutures: f8427b46feabaf73c5e71ace7d86d65dfbb47696 20 | NADocumentPicker: a64ddaf309b54e6addc014ad49d1acdb3ea5f86e 21 | 22 | PODFILE CHECKSUM: b5e57d6297223ed12f8280f4f9db125458d525da 23 | 24 | COCOAPODS: 1.7.0.beta.2 25 | -------------------------------------------------------------------------------- /Example/Pods/BrightFutures/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Thomas Visser 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Example/Pods/BrightFutures/README.md: -------------------------------------------------------------------------------- 1 | BrightFutures 2 | ============= 3 | 4 | How do you leverage the power of Swift to write great asynchronous code? BrightFutures is our answer. 5 | 6 | BrightFutures implements proven [functional concepts](http://en.wikipedia.org/wiki/Futures_and_promises) in Swift to provide a powerful alternative to completion blocks and support typesafe error handling in asynchronous code. 7 | 8 | The goal of BrightFutures is to be *the* idiomatic Swift implementation of futures and promises. 9 | Our Big Hairy Audacious Goal (BHAG) is to be copy-pasted into the Swift standard library. 10 | 11 | The stability of BrightFutures has been proven through extensive use in production. It is currently being used in several apps, with a combined total of almost 500k monthly active users. If you use BrightFutures in production, we'd love to hear about it! 12 | 13 | ## Latest news 14 | [![Join the chat at https://gitter.im/Thomvis/BrightFutures](https://badges.gitter.im/Thomvis/BrightFutures.svg)](https://gitter.im/Thomvis/BrightFutures?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Travis CI build status badge](https://travis-ci.org/Thomvis/BrightFutures.svg?branch=master)](https://travis-ci.org/Thomvis/BrightFutures) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![CocoaPods version](https://img.shields.io/cocoapods/v/BrightFutures.svg)](https://cocoapods.org/pods/BrightFutures) [![CocoaPods](https://img.shields.io/cocoapods/metrics/doc-percent/BrightFutures.svg?maxAge=2592000)](http://cocoadocs.org/docsets/BrightFutures) 15 | 16 | BrightFutures 8.0 is now available! This update adds Swift 5 compatibility. 17 | 18 | ## Installation 19 | ### [CocoaPods](http://cocoapods.org/) 20 | 21 | 1. Add the following to your [Podfile](http://guides.cocoapods.org/using/the-podfile.html): 22 | 23 | ```rb 24 | pod 'BrightFutures' 25 | ``` 26 | 27 | 2. Integrate your dependencies using frameworks: add `use_frameworks!` to your Podfile. 28 | 3. Run `pod install`. 29 | 30 | ### [Carthage](https://github.com/Carthage/Carthage) 31 | 32 | 1. Add the following to your [Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile): 33 | 34 | ``` 35 | github "Thomvis/BrightFutures" 36 | ``` 37 | 38 | 2. Run `carthage update` and follow the steps as described in Carthage's [README](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application). 39 | 40 | ## Documentation 41 | - This README covers almost all features of BrightFutures 42 | - The [tests](Tests/BrightFuturesTests) contain (trivial) usage examples for every feature (97% test coverage) 43 | - The primary author, Thomas Visser, gave [a talk](https://www.youtube.com/watch?v=lgJT2KMMEmU) at the April 2015 CocoaHeadsNL meetup 44 | - The [Highstreet Watch App](https://github.com/GetHighstreet/HighstreetWatchApp) was an Open Source WatchKit app that made extensive use of an earlier version of BrightFutures 45 | 46 | ## Examples 47 | We write a lot of asynchronous code. Whether we're waiting for something to come in from the network or want to perform an expensive calculation off the main thread and then update the UI, we often do the 'fire and callback' dance. Here's a typical snippet of asynchronous code: 48 | 49 | ```swift 50 | User.logIn(username, password) { user, error in 51 | if !error { 52 | Posts.fetchPosts(user, success: { posts in 53 | // do something with the user's posts 54 | }, failure: handleError) 55 | } else { 56 | handleError(error) // handeError is a custom function to handle errors 57 | } 58 | } 59 | ``` 60 | 61 | Now let's see what BrightFutures can do for you: 62 | 63 | ```swift 64 | User.logIn(username, password).flatMap { user in 65 | Posts.fetchPosts(user) 66 | }.onSuccess { posts in 67 | // do something with the user's posts 68 | }.onFailure { error in 69 | // either logging in or fetching posts failed 70 | } 71 | ``` 72 | 73 | Both `User.logIn` and `Posts.fetchPosts` now immediately return a `Future`. A future can either fail with an error or succeed with a value, which can be anything from an Int to your custom struct, class or tuple. You can keep a future around and register for callbacks for when the future succeeds or fails at your convenience. 74 | 75 | When the future returned from `User.logIn` fails, e.g. the username and password did not match, `flatMap` and `onSuccess` are skipped and `onFailure` is called with the error that occurred while logging in. If the login attempt succeeded, the resulting user object is passed to `flatMap`, which 'turns' the user into an array of his or her posts. If the posts could not be fetched, `onSuccess` is skipped and `onFailure` is called with the error that occurred when fetching the posts. If the posts could be fetched successfully, `onSuccess` is called with the user's posts. 76 | 77 | This is just the tip of the proverbial iceberg. A lot more examples and techniques can be found in this readme, by browsing through the tests or by checking out the official companion framework [FutureProofing](https://github.com/Thomvis/FutureProofing). 78 | 79 | ## Wrapping expressions 80 | If you already have a function (or really any expression) that you just want to execute asynchronously and have a Future to represent its result, you can easily wrap it in an `asyncValue` block: 81 | 82 | ```swift 83 | DispatchQueue.global().asyncValue { 84 | fibonacci(50) 85 | }.onSuccess { num in 86 | // value is 12586269025 87 | } 88 | ``` 89 | 90 | `asyncValue` is defined in an extension on GCD's `DispatchQueue`. While this is really short and simple, it is equally limited. In many cases, you will need a way to indicate that the task failed. To do this, instead of returning the value, you can return a Result. Results can indicate either a success or a failure: 91 | 92 | ```swift 93 | enum ReadmeError: Error { 94 | case RequestFailed, TimeServiceError 95 | } 96 | 97 | let f = DispatchQueue.global().asyncResult { () -> Result in 98 | if let now = serverTime() { 99 | return .success(now) 100 | } 101 | 102 | return .failure(ReadmeError.TimeServiceError) 103 | } 104 | 105 | f.onSuccess { value in 106 | // value will the NSDate from the server 107 | } 108 | ``` 109 | 110 | The future block needs an explicit type because the Swift compiler is not able to deduce the type of multi-statement blocks. 111 | 112 | Instead of wrapping existing expressions, it is often a better idea to use a Future as the return type of a method so all call sites can benefit. This is explained in the next section. 113 | 114 | ## Providing Futures 115 | Now let's assume the role of an API author who wants to use BrightFutures. A Future is designed to be read-only, except for the site where the Future is created. This is achieved via an initialiser on Future that takes a closure, the completion scope, in which you can complete the Future. The completion scope has one parameter that is also a closure which is invoked to set the value (or error) in the Future. 116 | 117 | ```swift 118 | func asyncCalculation() -> Future { 119 | return Future { complete in 120 | DispatchQueue.global().async { 121 | // do a complicated task and then hand the result to the promise: 122 | complete(.success("forty-two")) 123 | } 124 | } 125 | } 126 | ``` 127 | 128 | `Never` indicates that the `Future` cannot fail. This is guaranteed by the type system, since `Never` has no initializers. As an alternative to the completion scope, you could also create a `Promise`, which is the writeable equivalent of a Future, and store it somewhere for later use. 129 | 130 | ## Callbacks 131 | You can be informed of the result of a `Future` by registering callbacks: `onComplete`, `onSuccess` and `onFailure`. The order in which the callbacks are executed upon completion of the future is not guaranteed, but it is guaranteed that the callbacks are executed serially. It is not safe to add a new callback from within a callback of the same future. 132 | 133 | ## Chaining callbacks 134 | 135 | Using the `andThen` function on a `Future`, the order of callbacks can be explicitly defined. The closure passed to `andThen` is meant to perform side-effects and does not influence the result. `andThen` returns a new Future with the same result as this future that completes after the closure has been executed. 136 | 137 | ```swift 138 | var answer = 10 139 | 140 | let _ = Future(value: 4).andThen { result in 141 | switch result { 142 | case .success(let val): 143 | answer *= val 144 | case .failure(_): 145 | break 146 | } 147 | }.andThen { result in 148 | if case .success(_) = result { 149 | answer += 2 150 | } 151 | } 152 | 153 | // answer will be 42 (not 48) 154 | ``` 155 | 156 | ## Functional Composition 157 | 158 | ### map 159 | 160 | `map` returns a new Future that contains the error from this Future if this Future failed, or the return value from the given closure that was applied to the value of this Future. 161 | 162 | ```swift 163 | fibonacciFuture(10).map { number -> String in 164 | if number > 5 { 165 | return "large" 166 | } 167 | return "small" 168 | }.map { sizeString in 169 | sizeString == "large" 170 | }.onSuccess { numberIsLarge in 171 | // numberIsLarge is true 172 | } 173 | ``` 174 | 175 | ### flatMap 176 | 177 | `flatMap` is used to map the result of a future to the value of a new Future. 178 | 179 | ```swift 180 | fibonacciFuture(10).flatMap { number in 181 | fibonacciFuture(number) 182 | }.onSuccess { largeNumber in 183 | // largeNumber is 139583862445 184 | } 185 | ``` 186 | 187 | ### zip 188 | 189 | ```swift 190 | let f = Future(value: 1) 191 | let f1 = Future(value: 2) 192 | 193 | f.zip(f1).onSuccess { a, b in 194 | // a is 1, b is 2 195 | } 196 | ``` 197 | 198 | ### filter 199 | ```swift 200 | Future(value: 3) 201 | .filter { $0 > 5 } 202 | .onComplete { result in 203 | // failed with error NoSuchElementError 204 | } 205 | 206 | Future(value: "Swift") 207 | .filter { $0.hasPrefix("Sw") } 208 | .onComplete { result in 209 | // succeeded with value "Swift" 210 | } 211 | ``` 212 | 213 | ## Recovering from errors 214 | If a `Future` fails, use `recover` to offer a default or alternative value and continue the callback chain. 215 | 216 | ```swift 217 | // imagine a request failed 218 | Future(error: .RequestFailed) 219 | .recover { _ in // provide an offline default 220 | return 5 221 | }.onSuccess { value in 222 | // value is 5 if the request failed or 10 if the request succeeded 223 | } 224 | ``` 225 | 226 | In addition to `recover`, `recoverWith` can be used to provide a Future that will provide the value to recover with. 227 | 228 | ## Utility Functions 229 | BrightFutures also comes with a number of utility functions that simplify working with multiple futures. These are implemented as free (i.e. global) functions to work around current limitations of Swift. 230 | 231 | ## Fold 232 | The built-in `fold` function allows you to turn a list of values into a single value by performing an operation on every element in the list that *consumes* it as it is added to the resulting value. A trivial usecase for fold would be to calculate the sum of a list of integers. 233 | 234 | Folding a list of Futures is not very convenient with the built-in `fold` function, which is why BrightFutures provides one that works especially well for our use case. BrightFutures' `fold` turns a list of Futures into a single Future that contains the resulting value. This allows us to, for example, calculate the sum of the first 10 Future-wrapped elements of the fibonacci sequence: 235 | 236 | ```swift 237 | let fibonacciSequence = [fibonacciFuture(1), fibonacciFuture(2), ..., fibonacciFuture(10)] 238 | 239 | // 1+1+2+3+5+8+13+21+34+55 240 | fibonacciSequence.fold(0, f: { $0 + $1 }).onSuccess { sum in 241 | // sum is 143 242 | } 243 | ``` 244 | 245 | ## Sequence 246 | With `sequence`, you can turn a list of Futures into a single Future that contains a list of the results from those futures. 247 | 248 | ```swift 249 | let fibonacciSequence = [fibonacciFuture(1), fibonacciFuture(2), ..., fibonacciFuture(10)] 250 | 251 | fibonacciSequence.sequence().onSuccess { fibNumbers in 252 | // fibNumbers is an array of Ints: [1, 1, 2, 3, etc.] 253 | } 254 | ``` 255 | 256 | ## Traverse 257 | `traverse` combines `map` and `fold` in one convenient function. `traverse` takes a list of values and a closure that takes a single value from that list and turns it into a Future. The result of `traverse` is a single Future containing an array of the values from the Futures returned by the given closure. 258 | 259 | ```swift 260 | (1...10).traverse { 261 | i in fibonacciFuture(i) 262 | }.onSuccess { fibNumbers in 263 | // fibNumbers is an array of Ints: [1, 1, 2, 3, etc.] 264 | } 265 | ``` 266 | 267 | ## Delay 268 | `delay` returns a new Future that will complete after waiting for the given interval with the result of the previous Future. 269 | To simplify working with `DispatchTime` and `DispatchTimeInterval`, we recommend to use this [extension](https://gist.github.com/Thomvis/b378f926b6e1a48973f694419ed73aca). 270 | 271 | ```swift 272 | Future(value: 3).delay(2.seconds).andThen { result in 273 | // execute after two additional seconds 274 | } 275 | ``` 276 | 277 | ## Default Threading Model 278 | BrightFutures tries its best to provide a simple and sensible default threading model. In theory, all threads are created equally and BrightFutures shouldn't care about which thread it is on. In practice however, the main thread is _more equal than others_, because it has a special place in our hearts and because you'll often want to be on it to do UI updates. 279 | 280 | A lot of the methods on `Future` accept an optional _execution context_ and a block, e.g. `onSuccess`, `map`, `recover` and many more. The block is executed (when the future is completed) in the given execution context, which in practice is a GCD queue. When the context is not explicitly provided, the following rules will be followed to determine the execution context that is used: 281 | 282 | - if the method is called from the main thread, the block is executed on the main queue 283 | - if the method is not called from the main thread, the block is executed on a global queue 284 | 285 | If you want to have custom threading behavior, skip do do not the section. next [:wink:](https://twitter.com/nedbat/status/194452404794691584) 286 | 287 | ## Custom execution contexts 288 | The default threading behavior can be overridden by providing explicit execution contexts. You can choose from any of the built-in contexts or easily create your own. Default contexts include: any dispatch queue, any `NSOperationQueue` and the `ImmediateExecutionContext` for when you don't want to switch threads/queues. 289 | 290 | ```swift 291 | let f = Future { complete in 292 | DispatchQueue.global().async { 293 | complete(.success(fibonacci(10))) 294 | } 295 | } 296 | 297 | f.onComplete(DispatchQueue.main.context) { value in 298 | // update the UI, we're on the main thread 299 | } 300 | ``` 301 | 302 | Even though the future is completed from the global queue, the completion closure will be called on the main queue. 303 | 304 | ## Invalidation tokens 305 | An invalidation token can be used to invalidate a callback, preventing it from being executed upon completion of the future. This is particularly useful in cases where the context in which a callback is executed changes often and quickly, e.g. in reusable views such as table views and collection view cells. An example of the latter: 306 | 307 | ```swift 308 | class MyCell : UICollectionViewCell { 309 | var token = InvalidationToken() 310 | 311 | public override func prepareForReuse() { 312 | super.prepareForReuse() 313 | token.invalidate() 314 | token = InvalidationToken() 315 | } 316 | 317 | public func setModel(model: Model) { 318 | ImageLoader.loadImage(model.image).onSuccess(token.validContext) { [weak self] UIImage in 319 | self?.imageView.image = UIImage 320 | } 321 | } 322 | } 323 | ``` 324 | 325 | By invalidating the token on every reuse, we prevent that the image of the previous model is set after the next model has been set. 326 | 327 | Invalidation tokens _do not_ cancel the task that the future represents. That is a different problem. With invalidation tokens, the result is merely ignored. Invalidating a token after the original future completed does nothing. 328 | 329 | If you are looking for a way to cancel a running task, you could look into using [NSProgress](https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSProgress_Class/Reference/Reference.html). 330 | 331 | ## Credits 332 | 333 | BrightFutures' primary author is [Thomas Visser](https://twitter.com/thomvis). He is lead iOS Engineer at [Highstreet](http://www.highstreetapp.com/). We welcome any feedback and pull requests. Get your name on [this list](https://github.com/Thomvis/BrightFutures/graphs/contributors)! 334 | 335 | BrightFutures was inspired by Facebook's [BFTasks](https://github.com/BoltsFramework/Bolts-iOS), the Promises & Futures implementation in [Scala](http://docs.scala-lang.org/overviews/core/futures.html) and Max Howell's [PromiseKit](https://github.com/mxcl/PromiseKit). 336 | 337 | ## License 338 | 339 | BrightFutures is available under the MIT license. See the LICENSE file for more info. 340 | -------------------------------------------------------------------------------- /Example/Pods/BrightFutures/Sources/BrightFutures/Async.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Async.swift 3 | // BrightFutures 4 | // 5 | // Created by Thomas Visser on 09/07/15. 6 | // Copyright © 2015 Thomas Visser. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /// Implementation of the `AsyncType` protocol 12 | /// `Async` represents the result of an asynchronous operation 13 | /// and is typically returned from a method that initiates that 14 | /// asynchronous operation. 15 | /// Clients of that method receive the `Async` and can use it 16 | /// to register a callback for when the result of the asynchronous 17 | /// operation comes in. 18 | /// 19 | /// This class is often not used directly. Instead, its subclass 20 | /// `Future` is used. 21 | open class Async: AsyncType { 22 | 23 | typealias CompletionCallback = (Value) -> Void 24 | 25 | /// The actual result of the operation that the receiver represents or 26 | /// `.None` if the operation is not yet completed. 27 | public fileprivate(set) var result: Value? { 28 | willSet { 29 | assert(result == nil) 30 | } 31 | 32 | didSet { 33 | assert(result != nil) 34 | runCallbacks() 35 | } 36 | } 37 | 38 | /// This queue is used for all callback related administrative tasks 39 | /// to prevent that a callback is added to a completed future and never 40 | /// executed or perhaps excecuted twice. 41 | fileprivate let queue = DispatchQueue(label: "Internal Async Queue") 42 | 43 | /// Upon completion of the future, all callbacks are asynchronously scheduled to their 44 | /// respective execution contexts (which is either given by the client or returned from 45 | /// DefaultThreadingModel). Inside the context, this semaphore will be used 46 | /// to make sure that all callbacks are executed serially. 47 | fileprivate let callbackExecutionSemaphore = DispatchSemaphore(value: 1); 48 | fileprivate var callbacks = [CompletionCallback]() 49 | 50 | /// Creates an uncompleted `Async` 51 | public required init() { 52 | 53 | } 54 | 55 | /// Creates an `Async` that is completed with the given result 56 | public required init(result: Value) { 57 | self.result = result 58 | } 59 | 60 | /// Creates an `Async` that will be completed with the given result after the specified delay 61 | public required init(result: Value, delay: DispatchTimeInterval) { 62 | DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + delay) { 63 | self.complete(result) 64 | } 65 | } 66 | 67 | /// Creates an `Async` that is completed when the given other `Async` is completed 68 | public required init(other: A) where A.Value == Value { 69 | completeWith(other) 70 | } 71 | 72 | /// Creates an `Async` that can be completed by calling the `result` closure passed to 73 | /// the `resolver`. Example: 74 | /// 75 | /// Async { res in 76 | /// Queue.async { 77 | /// // do some work 78 | /// res(42) // complete the async with result '42' 79 | /// } 80 | /// } 81 | /// 82 | public required init(resolver: (_ result: @escaping (Value) -> Void) -> Void) { 83 | resolver { val in 84 | self.complete(val) 85 | } 86 | } 87 | 88 | private func runCallbacks() { 89 | guard let result = self.result else { 90 | assert(false, "can only run callbacks on a completed future") 91 | return 92 | } 93 | 94 | for callback in self.callbacks { 95 | callback(result) 96 | } 97 | 98 | self.callbacks.removeAll() 99 | } 100 | 101 | /// Adds the given closure as a callback for when the Async completes. The closure is executed on the given context. 102 | /// If no context is given, the behavior is defined by the default threading model (see README.md) 103 | /// Returns self 104 | @discardableResult 105 | open func onComplete(_ context: @escaping ExecutionContext = DefaultThreadingModel(), callback: @escaping (Value) -> Void) -> Self { 106 | let wrappedCallback : (Value) -> Void = { [weak self] value in 107 | let s = self 108 | context { 109 | s?.callbackExecutionSemaphore.context { 110 | callback(value) 111 | } 112 | return 113 | } 114 | } 115 | 116 | queue.sync { 117 | if let value = self.result { 118 | wrappedCallback(value) 119 | } else { 120 | self.callbacks.append(wrappedCallback) 121 | 122 | } 123 | } 124 | 125 | return self 126 | } 127 | 128 | } 129 | 130 | extension Async: MutableAsyncType { 131 | @discardableResult 132 | func tryComplete(_ value: Value) -> Bool{ 133 | return queue.sync { 134 | guard self.result == nil else { 135 | return false 136 | } 137 | 138 | self.result = value 139 | return true 140 | } 141 | } 142 | } 143 | 144 | extension Async: CustomStringConvertible, CustomDebugStringConvertible { 145 | public var description: String { 146 | return "Async<\(Value.self)>(\(String(describing: self.result)))" 147 | } 148 | 149 | public var debugDescription: String { 150 | return description 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /Example/Pods/BrightFutures/Sources/BrightFutures/AsyncType+Debug.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AsyncType+Debug.swift 3 | // BrightFutures 4 | // 5 | // Created by Oleksii on 23/09/2016. 6 | // Copyright © 2016 Thomas Visser. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol LoggerType { 12 | func log(message: String) 13 | func message(for value: Value, with identifier: String?, file: String, line: UInt, function: String) -> String 14 | } 15 | 16 | public extension LoggerType { 17 | func message(for value: Value, with identifier: String?, file: String, line: UInt, function: String) -> String { 18 | let messageBody: String 19 | 20 | if let identifier = identifier { 21 | messageBody = "Future \(identifier)" 22 | } else { 23 | let fileName = (file as NSString).lastPathComponent 24 | messageBody = "\(fileName) at line \(line), func: \(function) - future" 25 | } 26 | 27 | return "\(messageBody) completed" 28 | } 29 | } 30 | 31 | public struct Logger: LoggerType { 32 | public init() { 33 | } 34 | 35 | public func log(message: String) { 36 | print(message) 37 | } 38 | } 39 | 40 | public extension AsyncType { 41 | func debug(_ identifier: String? = nil, logger: LoggerType = Logger(), file: String = #file, line: UInt = #line, function: String = #function, context c: @escaping ExecutionContext = DefaultThreadingModel()) -> Self { 42 | return andThen(context: c, callback: { result in 43 | let message = logger.message(for: result, with: identifier, file: file, line: line, function: function) 44 | logger.log(message: message) 45 | }) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Example/Pods/BrightFutures/Sources/BrightFutures/AsyncType+ResultType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Async+ResultType.swift 3 | // BrightFutures 4 | // 5 | // Created by Thomas Visser on 10/07/15. 6 | // Copyright © 2015 Thomas Visser. All rights reserved. 7 | // 8 | 9 | public extension AsyncType where Value: ResultProtocol { 10 | /// `true` if the future completed with success, or `false` otherwise 11 | var isSuccess: Bool { 12 | return result?.analysis(ifSuccess: { _ in return true }, ifFailure: { _ in return false }) ?? false 13 | } 14 | 15 | /// `true` if the future failed, or `false` otherwise 16 | var isFailure: Bool { 17 | return result?.analysis(ifSuccess: { _ in return false }, ifFailure: { _ in return true }) ?? false 18 | } 19 | 20 | var value: Value.Value? { 21 | return result?.result.value 22 | } 23 | 24 | var error: Value.Error? { 25 | return result?.result.error 26 | } 27 | 28 | /// Adds the given closure as a callback for when the future succeeds. The closure is executed on the given context. 29 | /// If no context is given, the behavior is defined by the default threading model (see README.md) 30 | /// Returns self 31 | @discardableResult 32 | func onSuccess(_ context: @escaping ExecutionContext = DefaultThreadingModel(), callback: @escaping (Value.Value) -> Void) -> Self { 33 | self.onComplete(context) { result in 34 | result.analysis(ifSuccess: callback, ifFailure: { _ in }) 35 | } 36 | 37 | return self 38 | } 39 | 40 | /// Adds the given closure as a callback for when the future fails. The closure is executed on the given context. 41 | /// If no context is given, the behavior is defined by the default threading model (see README.md) 42 | /// Returns self 43 | @discardableResult 44 | func onFailure(_ context: @escaping ExecutionContext = DefaultThreadingModel(), callback: @escaping (Value.Error) -> Void) -> Self { 45 | self.onComplete(context) { result in 46 | result.analysis(ifSuccess: { _ in }, ifFailure: callback) 47 | } 48 | return self 49 | } 50 | 51 | /// Enables the the chaining of two future-wrapped asynchronous operations where the second operation depends on the success value of the first. 52 | /// Like map, the given closure (that returns the second operation) is only executed if the first operation (this future) is successful. 53 | /// If a regular `map` was used, the result would be a `Future>`. The implementation of this function uses `map`, but then flattens the result 54 | /// before returning it. 55 | /// 56 | /// If this future fails, the returned future will fail with the same error. 57 | /// If this future succeeds, the returned future will complete with the future returned from the given closure. 58 | /// 59 | /// The closure is executed on the given context. If no context is given, the behavior is defined by the default threading model (see README.md) 60 | func flatMap(_ context: @escaping ExecutionContext, f: @escaping (Value.Value) -> Future) -> Future { 61 | return map(context, f: f).flatten() 62 | } 63 | 64 | /// See `flatMap(context c: ExecutionContext, f: T -> Future) -> Future` 65 | /// The given closure is executed according to the default threading model (see README.md) 66 | func flatMap(_ f: @escaping (Value.Value) -> Future) -> Future { 67 | return flatMap(DefaultThreadingModel(), f: f) 68 | } 69 | 70 | /// Transforms the given closure returning `Result` to a closure returning `Future` and then calls 71 | /// `flatMap(context c: ExecutionContext, f: T -> Future) -> Future` 72 | func flatMap(_ context: @escaping ExecutionContext, f: @escaping (Value.Value) -> Result) -> Future { 73 | return self.flatMap(context) { value in 74 | return Future(result: f(value)) 75 | } 76 | } 77 | 78 | /// See `flatMap(context c: ExecutionContext, f: T -> Result) -> Future` 79 | /// The given closure is executed according to the default threading model (see README.md) 80 | func flatMap(_ f: @escaping (Value.Value) -> Result) -> Future { 81 | return flatMap(DefaultThreadingModel(), f: f) 82 | } 83 | 84 | /// See `map(context c: ExecutionContext, f: (T) -> U) -> Future` 85 | /// The given closure is executed according to the default threading model (see README.md) 86 | func map(_ f: @escaping (Value.Value) -> U) -> Future { 87 | return self.map(DefaultThreadingModel(), f: f) 88 | } 89 | 90 | /// Returns a future that succeeds with the value returned from the given closure when it is invoked with the success value 91 | /// from this future. If this future fails, the returned future fails with the same error. 92 | /// The closure is executed on the given context. If no context is given, the behavior is defined by the default threading model (see README.md) 93 | func map(_ context: @escaping ExecutionContext, f: @escaping (Value.Value) -> U) -> Future { 94 | let res = Future() 95 | 96 | self.onComplete(context, callback: { (result: Value) in 97 | result.analysis( 98 | ifSuccess: { res.success(f($0)) }, 99 | ifFailure: { res.failure($0) }) 100 | }) 101 | 102 | return res 103 | } 104 | 105 | /// Returns a future that completes with this future if this future succeeds or with the value returned from the given closure 106 | /// when it is invoked with the error that this future failed with. 107 | /// The closure is executed on the given context. If no context is given, the behavior is defined by the default threading model (see README.md) 108 | func recover(context c: @escaping ExecutionContext = DefaultThreadingModel(), task: @escaping (Value.Error) -> Value.Value) -> Future { 109 | return self.recoverWith(context: c) { error -> Future in 110 | return Future(value: task(error)) 111 | } 112 | } 113 | 114 | /// Returns a future that completes with this future if this future succeeds or with the value returned from the given closure 115 | /// when it is invoked with the error that this future failed with. 116 | /// This function should be used in cases where there are two asynchronous operations where the second operation (returned from the given closure) 117 | /// should only be executed if the first (this future) fails. 118 | /// The closure is executed on the given context. If no context is given, the behavior is defined by the default threading model (see README.md) 119 | func recoverWith(context c: @escaping ExecutionContext = DefaultThreadingModel(), task: @escaping (Value.Error) -> Future) -> Future { 120 | let res = Future() 121 | 122 | self.onComplete(c) { result in 123 | result.analysis( 124 | ifSuccess: { res.success($0) }, 125 | ifFailure: { res.completeWith(task($0)) }) 126 | } 127 | 128 | return res 129 | } 130 | 131 | /// See `mapError(context c: ExecutionContext, f: E -> E1) -> Future` 132 | /// The given closure is executed according to the default threading model (see README.md) 133 | func mapError(_ f: @escaping (Value.Error) -> E1) -> Future { 134 | return mapError(DefaultThreadingModel(), f: f) 135 | } 136 | 137 | /// Returns a future that fails with the error returned from the given closure when it is invoked with the error 138 | /// from this future. If this future succeeds, the returned future succeeds with the same value and the closure is not executed. 139 | /// The closure is executed on the given context. 140 | func mapError(_ context: @escaping ExecutionContext, f: @escaping (Value.Error) -> E1) -> Future { 141 | let res = Future() 142 | 143 | self.onComplete(context) { result in 144 | result.analysis( 145 | ifSuccess: { res.success($0) } , 146 | ifFailure: { res.failure(f($0)) }) 147 | } 148 | 149 | return res 150 | } 151 | 152 | /// Returns a future that succeeds with a tuple consisting of the success value of this future and the success value of the given future 153 | /// If either of the two futures fail, the returned future fails with the failure of this future or that future (in this order) 154 | func zip(_ that: Future) -> Future<(Value.Value,U), Value.Error> { 155 | return flatMap(ImmediateExecutionContext) { thisVal -> Future<(Value.Value,U), Value.Error> in 156 | return that.map(ImmediateExecutionContext) { thatVal in 157 | return (thisVal, thatVal) 158 | } 159 | } 160 | } 161 | 162 | /// Returns a future that succeeds with the value that this future succeeds with if it passes the test 163 | /// (i.e. the given closure returns `true` when invoked with the success value) or an error with code 164 | /// `ErrorCode.noSuchElement` if the test failed. 165 | /// If this future fails, the returned future fails with the same error. 166 | func filter(_ p: @escaping (Value.Value) -> Bool) -> Future> { 167 | return self.mapError(ImmediateExecutionContext) { error in 168 | return BrightFuturesError(external: error) 169 | }.flatMap(ImmediateExecutionContext) { value -> Result> in 170 | if p(value) { 171 | return .success(value) 172 | } else { 173 | return .failure(.noSuchElement) 174 | } 175 | } 176 | } 177 | 178 | /// Returns a new future with the new type. 179 | /// The value or error will be casted using `as!` and may cause a runtime error 180 | func forceType() -> Future { 181 | return self.map(ImmediateExecutionContext) { 182 | $0 as! U 183 | }.mapError(ImmediateExecutionContext) { 184 | $0 as! E1 185 | } 186 | } 187 | 188 | /// Returns a new future that completes with this future, but returns Void on success 189 | func asVoid() -> Future { 190 | return self.map(ImmediateExecutionContext) { _ in return () } 191 | } 192 | } 193 | 194 | public extension AsyncType where Value: ResultProtocol, Value.Value: AsyncType, Value.Value.Value: ResultProtocol, Value.Error == Value.Value.Value.Error { 195 | /// Returns a future that fails with the error from the outer or inner future or succeeds with the value from the inner future 196 | /// if both futures succeed. 197 | func flatten() -> Future { 198 | let f = Future() 199 | 200 | onComplete(ImmediateExecutionContext) { res in 201 | res.analysis(ifSuccess: { innerFuture -> () in 202 | innerFuture.onComplete(ImmediateExecutionContext) { (res:Value.Value.Value) in 203 | res.analysis(ifSuccess: { f.success($0) }, ifFailure: { err in f.failure(err) }) 204 | } 205 | }, ifFailure: { f.failure($0) }) 206 | } 207 | 208 | return f 209 | } 210 | 211 | } 212 | 213 | public extension AsyncType where Value: ResultProtocol, Value.Error == Never { 214 | /// 'promotes' a `Future` with error type `Never` to a `Future` with an error type of choice. 215 | /// This allows the `Future` to be used more easily in combination with other futures 216 | /// for operations such as `sequence` and `firstCompleted` 217 | /// This is a safe operation, because a `Future` with error type `Never` is guaranteed never to fail 218 | func promoteError() -> Future { 219 | return mapError(ImmediateExecutionContext) { $0 as! E } // future will never fail, so this map block will never get called 220 | } 221 | } 222 | 223 | public extension AsyncType where Value: ResultProtocol, Value.Error == BrightFuturesError { 224 | /// 'promotes' a `Future` with error type `BrightFuturesError` to a `Future` with an 225 | /// `BrightFuturesError` error type where `E` can be any type conforming to `ErrorType`. 226 | /// This allows the `Future` to be used more easily in combination with other futures 227 | /// for operations such as `sequence` and `firstCompleted` 228 | /// This is a safe operation, because a `BrightFuturesError` will never be `.External` 229 | func promoteError() -> Future> { 230 | return mapError(ImmediateExecutionContext) { err in 231 | switch err { 232 | case .noSuchElement: 233 | return BrightFuturesError.noSuchElement 234 | case .invalidationTokenInvalidated: 235 | return BrightFuturesError.invalidationTokenInvalidated 236 | case .illegalState: 237 | return BrightFuturesError.illegalState 238 | case .external(_): 239 | fatalError("Encountered BrightFuturesError.External with Never, which should be impossible") 240 | } 241 | } 242 | } 243 | } 244 | 245 | public extension AsyncType where Value: ResultProtocol, Value.Value == NoValue { 246 | /// 'promotes' a `Future` with value type `NoValue` to a `Future` with a value type of choice. 247 | /// This allows the `Future` to be used more easily in combination with other futures 248 | /// for operations such as `sequence` and `firstCompleted` 249 | /// This is a safe operation, because a `Future` with value type `NoValue` is guaranteed never to succeed 250 | func promoteValue() -> Future { 251 | return map(ImmediateExecutionContext) { $0 as! T } // future will never succeed, so this map block will never get called 252 | } 253 | } 254 | 255 | -------------------------------------------------------------------------------- /Example/Pods/BrightFutures/Sources/BrightFutures/AsyncType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Async.swift 3 | // BrightFutures 4 | // 5 | // Created by Thomas Visser on 09/07/15. 6 | // Copyright © 2015 Thomas Visser. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol AsyncType { 12 | associatedtype Value 13 | 14 | var result: Value? { get } 15 | 16 | init() 17 | init(result: Value) 18 | init(result: Value, delay: DispatchTimeInterval) 19 | init(other: A) where A.Value == Value 20 | init(resolver: (_ result: @escaping (Value) -> Void) -> Void) 21 | 22 | @discardableResult 23 | func onComplete(_ context: @escaping ExecutionContext, callback: @escaping (Value) -> Void) -> Self 24 | } 25 | 26 | public extension AsyncType { 27 | /// `true` if the future completed (either `isSuccess` or `isFailure` will be `true`) 28 | var isCompleted: Bool { 29 | return result != nil 30 | } 31 | 32 | /// Blocks the current thread until the future is completed and then returns the result 33 | func forced() -> Value { 34 | return forced(DispatchTime.distantFuture)! 35 | } 36 | 37 | /// Blocks the current thread until the future is completed, but no longer than the given timeout 38 | /// If the future did not complete before the timeout, `nil` is returned, otherwise the result of the future is returned 39 | func forced(_ timeout: DispatchTime) -> Value? { 40 | if let result = result { 41 | return result 42 | } 43 | 44 | let sema = DispatchSemaphore(value: 0) 45 | var res: Value? = nil 46 | onComplete(DispatchQueue.global().context) { 47 | res = $0 48 | sema.signal() 49 | } 50 | 51 | let _ = sema.wait(timeout: timeout) 52 | 53 | return res 54 | } 55 | 56 | /// Alias of delay(queue:interval:) 57 | /// Will pass the main queue if we are currently on the main thread, or the 58 | /// global queue otherwise 59 | func delay(_ interval: DispatchTimeInterval) -> Self { 60 | if Thread.isMainThread { 61 | return delay(DispatchQueue.main, interval: interval) 62 | } 63 | 64 | return delay(DispatchQueue.global(), interval: interval) 65 | } 66 | 67 | /// Returns an Async that will complete with the result that this Async completes with 68 | /// after waiting for the given interval 69 | /// The delay is implemented using dispatch_after. The given queue is passed to that function. 70 | /// If you want a delay of 0 to mean 'delay until next runloop', you will want to pass the main 71 | /// queue. 72 | func delay(_ queue: DispatchQueue, interval: DispatchTimeInterval) -> Self { 73 | return Self { complete in 74 | onComplete(ImmediateExecutionContext) { result in 75 | queue.asyncAfter(deadline: DispatchTime.now() + interval) { 76 | complete(result) 77 | } 78 | } 79 | } 80 | } 81 | 82 | /// Adds the given closure as a callback for when this future completes. 83 | /// The closure is executed on the given context. If no context is given, the behavior is defined by the default threading model (see README.md) 84 | /// Returns a future that completes with the result from this future but only after executing the given closure 85 | func andThen(context c: @escaping ExecutionContext = DefaultThreadingModel(), callback: @escaping (Self.Value) -> Void) -> Self { 86 | return Self { complete in 87 | onComplete(c) { result in 88 | callback(result) 89 | complete(result) 90 | } 91 | } 92 | } 93 | } 94 | 95 | public extension AsyncType where Value: AsyncType { 96 | func flatten() -> Self.Value { 97 | return Self.Value { complete in 98 | self.onComplete(ImmediateExecutionContext) { value in 99 | value.onComplete(ImmediateExecutionContext, callback: complete) 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Example/Pods/BrightFutures/Sources/BrightFutures/Dispatch+BrightFutures.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Dispatch+BrightFutures.swift 3 | // BrightFutures 4 | // 5 | // Created by Thomas Visser on 13/08/16. 6 | // Copyright © 2016 Thomas Visser. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension DispatchQueue { 12 | var context: ExecutionContext { 13 | return { task in 14 | self.async(execute: task) 15 | } 16 | } 17 | 18 | func asyncValue(_ execute: @escaping () -> T) -> Future { 19 | return Future { completion in 20 | async { 21 | completion(.success(execute())) 22 | } 23 | } 24 | } 25 | 26 | func asyncResult(_ execute: @escaping () -> Result) -> Future { 27 | return Future { completion in 28 | async { 29 | completion(execute()) 30 | } 31 | } 32 | } 33 | 34 | func asyncValueAfter(_ deadline: DispatchTime, execute: @escaping () -> T) -> Future { 35 | return Future { completion in 36 | asyncAfter(deadline: deadline) { 37 | completion(.success(execute())) 38 | } 39 | } 40 | } 41 | 42 | } 43 | 44 | public extension DispatchSemaphore { 45 | var context: ExecutionContext { 46 | return { task in 47 | let _ = self.wait(timeout: DispatchTime.distantFuture) 48 | task() 49 | self.signal() 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Example/Pods/BrightFutures/Sources/BrightFutures/Errors.swift: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2014 Thomas Visser 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import Foundation 24 | 25 | /// An enum representing every possible error for errors returned by BrightFutures 26 | /// A `BrightFuturesError` can also wrap an external error (e.g. coming from a user defined future) 27 | /// in its `External` case. `BrightFuturesError` has the type of the external error as its generic parameter. 28 | public enum BrightFuturesError: Error { 29 | 30 | /// Indicates that a matching element could not be found, e.g. while filtering or finding 31 | case noSuchElement 32 | 33 | /// Used in the implementation of InvalidationToken 34 | case invalidationTokenInvalidated 35 | 36 | /// Indicates that an invalid / unexpected state was reached. This error is used in places that should not be executed 37 | case illegalState 38 | 39 | /// Wraps a different ErrorType instance 40 | case external(E) 41 | 42 | /// Constructs a BrightFutures.External with the given external error 43 | public init(external: E) { 44 | self = .external(external) 45 | } 46 | } 47 | 48 | extension BrightFuturesError: Equatable where E: Equatable { 49 | /// Returns `true` if `left` and `right` are both of the same case ignoring .External associated value 50 | public static func ==(lhs: BrightFuturesError, rhs: BrightFuturesError) -> Bool { 51 | switch (lhs, rhs) { 52 | case (.noSuchElement, .noSuchElement): return true 53 | case (.invalidationTokenInvalidated, .invalidationTokenInvalidated): return true 54 | case (.external(let lhs), .external(let rhs)): return lhs == rhs 55 | default: return false 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Example/Pods/BrightFutures/Sources/BrightFutures/ExecutionContext.swift: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2014 Thomas Visser 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import Foundation 24 | 25 | /// The context in which something can be executed 26 | /// By default, an execution context can be assumed to be asynchronous unless stated otherwise 27 | public typealias ExecutionContext = (@escaping () -> Void) -> Void 28 | 29 | /// Immediately executes the given task. No threading, no semaphores. 30 | public let ImmediateExecutionContext: ExecutionContext = { task in 31 | task() 32 | } 33 | 34 | /// Runs immediately if on the main thread, otherwise asynchronously on the main thread 35 | public let ImmediateOnMainExecutionContext: ExecutionContext = { task in 36 | if Thread.isMainThread { 37 | task() 38 | } else { 39 | DispatchQueue.main.async(execute: task) 40 | } 41 | } 42 | 43 | /// From https://github.com/BoltsFramework/Bolts-Swift/blob/5fe4df7acb384a93ad93e8595d42e2b431fdc266/Sources/BoltsSwift/Executor.swift#L56 44 | public let MaxStackDepthExecutionContext: ExecutionContext = { task in 45 | struct Static { 46 | static let taskDepthKey = "com.bolts.TaskDepthKey" 47 | static let maxTaskDepth = 20 48 | } 49 | 50 | var localThreadDictionary = Thread.current.threadDictionary 51 | 52 | var previousDepth: Int 53 | if let depth = localThreadDictionary[Static.taskDepthKey] as? Int { 54 | previousDepth = depth 55 | } else { 56 | previousDepth = 0 57 | } 58 | 59 | if previousDepth > 20 { 60 | DispatchQueue.global().async(execute: task) 61 | } else { 62 | localThreadDictionary[Static.taskDepthKey] = previousDepth + 1 63 | task() 64 | localThreadDictionary[Static.taskDepthKey] = previousDepth 65 | } 66 | } 67 | 68 | public typealias ThreadingModel = () -> ExecutionContext 69 | 70 | public var DefaultThreadingModel: ThreadingModel = defaultContext 71 | 72 | /// Defines BrightFutures' default threading behavior: 73 | /// - if on the main thread, `DispatchQueue.main.context` is returned 74 | /// - if off the main thread, `DispatchQueue.global().context` is returned 75 | public func defaultContext() -> ExecutionContext { 76 | return (Thread.isMainThread ? DispatchQueue.main : DispatchQueue.global()).context 77 | } 78 | -------------------------------------------------------------------------------- /Example/Pods/BrightFutures/Sources/BrightFutures/Future.swift: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2014 Thomas Visser 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import Foundation 24 | 25 | /// A Future represents the outcome of an asynchronous operation 26 | /// The outcome will be represented as an instance of the `Result` enum and will be stored 27 | /// in the `result` property. As long as the operation is not yet completed, `result` will be nil. 28 | /// Interested parties can be informed of the completion by using one of the available callback 29 | /// registration methods (e.g. onComplete, onSuccess & onFailure) or by immediately composing/chaining 30 | /// subsequent actions (e.g. map, flatMap, recover, andThen, etc.). 31 | /// 32 | /// For more info, see the project README.md 33 | public final class Future: Async> { 34 | 35 | public typealias CompletionCallback = (_ result: Result) -> Void 36 | public typealias SuccessCallback = (T) -> Void 37 | public typealias FailureCallback = (E) -> Void 38 | 39 | public required init() { 40 | super.init() 41 | } 42 | 43 | public required init(result: Future.Value) { 44 | super.init(result: result) 45 | } 46 | 47 | public init(value: T, delay: DispatchTimeInterval) { 48 | super.init(result: .success(value), delay: delay) 49 | } 50 | 51 | public required init(other: A) where A.Value == Value { 52 | super.init(other: other) 53 | } 54 | 55 | public required init(result: Value, delay: DispatchTimeInterval) { 56 | super.init(result: result, delay: delay) 57 | } 58 | 59 | public convenience init(value: T) { 60 | self.init(result: .success(value)) 61 | } 62 | 63 | public convenience init(error: E) { 64 | self.init(result: .failure(error)) 65 | } 66 | 67 | public required init(resolver: (_ result: @escaping (Value) -> Void) -> Void) { 68 | super.init(resolver: resolver) 69 | } 70 | 71 | } 72 | 73 | public func materialize(_ scope: ((T?, E?) -> Void) -> Void) -> Future { 74 | return Future { complete in 75 | scope { val, err in 76 | if let val = val { 77 | complete(.success(val)) 78 | } else if let err = err { 79 | complete(.failure(err)) 80 | } 81 | } 82 | } 83 | } 84 | 85 | public func materialize(_ scope: ((T) -> Void) -> Void) -> Future { 86 | return Future { complete in 87 | scope { val in 88 | complete(.success(val)) 89 | } 90 | } 91 | } 92 | 93 | public func materialize(_ scope: ((E?) -> Void) -> Void) -> Future { 94 | return Future { complete in 95 | scope { err in 96 | if let err = err { 97 | complete(.failure(err)) 98 | } else { 99 | complete(.success(())) 100 | } 101 | } 102 | } 103 | } 104 | 105 | /// Short-hand for `lhs.recover(rhs())` 106 | /// `rhs` is executed according to the default threading model (see README.md) 107 | public func ?? (_ lhs: Future, rhs: @autoclosure @escaping () -> T) -> Future { 108 | return lhs.recover(context: DefaultThreadingModel(), task: { _ in 109 | return rhs() 110 | }) 111 | } 112 | 113 | /// Short-hand for `lhs.recoverWith(rhs())` 114 | /// `rhs` is executed according to the default threading model (see README.md) 115 | public func ?? (_ lhs: Future, rhs: @autoclosure @escaping () -> Future) -> Future { 116 | return lhs.recoverWith(context: DefaultThreadingModel(), task: { _ in 117 | return rhs() 118 | }) 119 | } 120 | 121 | /// Can be used as the value type of a `Future` or `Result` to indicate it can never be a success. 122 | /// This is guaranteed by the type system, because `NoValue` has no possible values and thus cannot be created. 123 | public enum NoValue { } 124 | -------------------------------------------------------------------------------- /Example/Pods/BrightFutures/Sources/BrightFutures/InvalidationToken.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InvalidationToken.swift 3 | // BrightFutures 4 | // 5 | // Created by Thomas Visser on 15/01/15. 6 | // Copyright (c) 2015 Thomas Visser. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /// The type that all invalidation tokens conform to 12 | public protocol InvalidationTokenType { 13 | 14 | /// Indicates if the token is invalid 15 | var isInvalid : Bool { get } 16 | 17 | /// The future will fail with .InvalidationTokenInvalidated when the token invalidates 18 | var future: Future> { get } 19 | 20 | /// This context executes as long as the token is valid. If the token is invalid, the given blocks are discarded 21 | func validContext(_ parentContext: @escaping ExecutionContext) -> ExecutionContext 22 | 23 | } 24 | 25 | extension InvalidationTokenType { 26 | /// Alias of context(parentContext:task:) which uses the default threading model 27 | /// Due to a limitation of the Swift compiler, we cannot express this with a single method 28 | public var validContext: ExecutionContext { 29 | return validContext(DefaultThreadingModel()) 30 | } 31 | 32 | public func validContext(_ parentContext: @escaping ExecutionContext = DefaultThreadingModel()) -> ExecutionContext { 33 | return { task in 34 | parentContext { 35 | if !self.isInvalid { 36 | task() 37 | } 38 | } 39 | } 40 | } 41 | } 42 | 43 | /// The type that all invalidation tokens that can be manually invalidated conform to 44 | public protocol ManualInvalidationTokenType : InvalidationTokenType { 45 | /// Invalidates the token 46 | func invalidate() 47 | } 48 | 49 | /// A default invalidation token implementation 50 | public class InvalidationToken : ManualInvalidationTokenType { 51 | 52 | public let future = Future>() 53 | 54 | /// Creates a new valid token 55 | public init() { } 56 | 57 | /// Indicates if the token is invalid 58 | public var isInvalid: Bool { 59 | return future.isCompleted 60 | } 61 | 62 | /// Invalidates the token 63 | public func invalidate() { 64 | future.failure(.invalidationTokenInvalidated) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Example/Pods/BrightFutures/Sources/BrightFutures/MutableAsyncType+ResultType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MutableAsyncType+ResultType.swift 3 | // BrightFutures 4 | // 5 | // Created by Thomas Visser on 22/07/15. 6 | // Copyright © 2015 Thomas Visser. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | internal extension MutableAsyncType where Value: ResultProtocol { 12 | /// Completes the future with the given success value 13 | /// If the future is already completed, this function does nothing 14 | /// and an assert will be raised (if enabled) 15 | func success(_ value: Value.Value) { 16 | complete(Value(value: value)) 17 | } 18 | 19 | /// Tries to complete the future with the given success value 20 | /// If the future is already completed, nothing happens and `false` is returned 21 | /// otherwise the future is completed and `true` is returned 22 | func trySuccess(_ value: Value.Value) -> Bool { 23 | return tryComplete(Value(value: value)) 24 | } 25 | 26 | /// Completes the future with the given error 27 | /// If the future is already completed, this function does nothing 28 | /// and an assert will be raised (if enabled) 29 | func failure(_ error: Value.Error) { 30 | complete(Value(error: error)) 31 | } 32 | 33 | /// Tries to complete the future with the given error 34 | /// If the future is already completed, nothing happens and `false` is returned 35 | /// otherwise the future is completed and `true` is returned 36 | func tryFailure(_ error: Value.Error) -> Bool { 37 | return tryComplete(Value(error: error)) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Example/Pods/BrightFutures/Sources/BrightFutures/MutableAsyncType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MutableAsyncType.swift 3 | // BrightFutures 4 | // 5 | // Created by Thomas Visser on 14/07/15. 6 | // Copyright © 2015 Thomas Visser. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | internal protocol MutableAsyncType: AsyncType { 12 | /// Complete the Async with the given value 13 | /// If the Async is already completed, nothing happens and `false` is returned 14 | /// otherwise the future is completed and `true` is returned 15 | func tryComplete(_ result: Value) -> Bool 16 | } 17 | 18 | extension MutableAsyncType { 19 | 20 | /// Completes the Async with the given result 21 | /// If the Async is already completed, this function throws an error 22 | func complete(_ result: Value) { 23 | if !tryComplete(result) { 24 | print(result) 25 | let error = "Attempted to completed an Async that is already completed. This could become a fatalError." 26 | assert(false, error) 27 | print(error) 28 | } 29 | } 30 | 31 | func completeWith(_ other: A) where A.Value == Value { 32 | other.onComplete(ImmediateExecutionContext, callback: self.complete) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Example/Pods/BrightFutures/Sources/BrightFutures/NSOperationQueue+BrightFutures.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSOperationQueue+BrightFutures.swift 3 | // BrightFutures 4 | // 5 | // Created by Thomas Visser on 18/09/15. 6 | // Copyright © 2015 Thomas Visser. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension OperationQueue { 12 | /// An execution context that operates on the receiver. 13 | /// Tasks added to the execution context are executed as operations on the queue. 14 | var context: ExecutionContext { 15 | return { [weak self] task in 16 | self?.addOperation(BlockOperation(block: task)) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Example/Pods/BrightFutures/Sources/BrightFutures/Promise.swift: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2014 Thomas Visser 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import Foundation 24 | 25 | /// The source of a future. Create a `Promise` when you are 26 | /// performing an asynchronous task and want to return a future. 27 | /// Return the future and keep the promise around to complete it 28 | /// when the asynchronous operation is completed. Completing a 29 | /// promise is thread safe and is typically performed from the 30 | /// (background) thread where the operation itself is also performed. 31 | public final class Promise { 32 | 33 | /// The future that will complete through this promise 34 | public let future: Future 35 | 36 | /// Creates a new promise with a pending future 37 | public init() { 38 | self.future = Future() 39 | } 40 | 41 | /// Completes the promise's future with the given future 42 | public func completeWith(_ other: Future) { 43 | future.completeWith(other) 44 | } 45 | 46 | /// Completes the promise's future with the given success value 47 | /// See `Future.success(value: T)` 48 | public func success(_ value: T) { 49 | future.success(value) 50 | } 51 | 52 | /// Attempts to complete the promise's future with the given success value 53 | /// See `future.trySuccess(value: T)` 54 | @discardableResult 55 | public func trySuccess(_ value: T) -> Bool { 56 | return future.trySuccess(value) 57 | } 58 | 59 | /// Completes the promise's future with the given error 60 | /// See `future.failure(error: E)` 61 | public func failure(_ error: E) { 62 | future.failure(error) 63 | } 64 | 65 | /// Attempts to complete the promise's future with the given error 66 | /// See `future.tryFailure(error: E)` 67 | @discardableResult 68 | public func tryFailure(_ error: E) -> Bool { 69 | return future.tryFailure(error) 70 | } 71 | 72 | /// Completes the promise's future with the given result 73 | /// See `future.complete(result: Result)` 74 | public func complete(_ result: Result) { 75 | future.complete(result) 76 | } 77 | 78 | /// Attempts to complete the promise's future with the given result 79 | /// See `future.tryComplete(result: Result)` 80 | @discardableResult 81 | public func tryComplete(_ result: Result) -> Bool { 82 | return future.tryComplete(result) 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /Example/Pods/BrightFutures/Sources/BrightFutures/Result+BrightFutures.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Result+BrightFutures.swift 3 | // BrightFutures 4 | // 5 | // Created by Thomas Visser on 30/08/15. 6 | // Copyright © 2015 Thomas Visser. All rights reserved. 7 | // 8 | 9 | public extension ResultProtocol { 10 | 11 | /// Case analysis for Result. 12 | /// 13 | /// Returns the value produced by applying `ifFailure` to `failure` Results, or `ifSuccess` to `success` Results. 14 | func analysis(ifSuccess: (Value) -> Result, ifFailure: (Error) -> Result) -> Result { 15 | switch self.result { 16 | case .success(let value): 17 | return ifSuccess(value) 18 | case .failure(let error): 19 | return ifFailure(error) 20 | } 21 | } 22 | 23 | } 24 | 25 | extension ResultProtocol { 26 | /// Enables the chaining of two failable operations where the second operation is asynchronous and 27 | /// represented by a future. 28 | /// Like map, the given closure (that performs the second operation) is only executed 29 | /// if the first operation result is a .success 30 | /// If a regular `map` was used, the result would be `Result>`. 31 | /// The implementation of this function uses `map`, but then flattens the result before returning it. 32 | public func flatMap(_ f: (Value) -> Future) -> Future { 33 | return analysis(ifSuccess: { 34 | return f($0) 35 | }, ifFailure: { 36 | return Future(error: $0) 37 | }) 38 | } 39 | } 40 | 41 | extension ResultProtocol where Value: ResultProtocol, Error == Value.Error { 42 | 43 | /// Returns a .failure with the error from the outer or inner result if either of the two failed 44 | /// or a .success with the success value from the inner Result 45 | public func flatten() -> Result { 46 | return analysis(ifSuccess: { innerRes in 47 | return innerRes.analysis(ifSuccess: { 48 | return .success($0) 49 | }, ifFailure: { 50 | return .failure($0) 51 | }) 52 | }, ifFailure: { 53 | return .failure($0) 54 | }) 55 | } 56 | } 57 | 58 | extension ResultProtocol where Value: AsyncType, Value.Value: ResultProtocol, Error == Value.Value.Error { 59 | /// Returns the inner future if the outer result succeeded or a failed future 60 | /// with the error from the outer result otherwise 61 | public func flatten() -> Future { 62 | return Future { complete in 63 | analysis(ifSuccess: { innerFuture -> () in 64 | innerFuture.onComplete(ImmediateExecutionContext) { res in 65 | complete(res.analysis(ifSuccess: { 66 | return .success($0) 67 | }, ifFailure: { 68 | return .failure($0) 69 | })) 70 | } 71 | }, ifFailure: { 72 | complete(.failure($0)) 73 | }) 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Example/Pods/BrightFutures/Sources/BrightFutures/ResultProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResultProtocol.swift 3 | // BrightFutures-iOS 4 | // 5 | // Created by Kim de Vos on 26/03/2019. 6 | // Copyright © 2019 Thomas Visser. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /// A protocol that can be used to constrain associated types as `Result`. 12 | public protocol ResultProtocol { 13 | associatedtype Value 14 | associatedtype Error: Swift.Error 15 | 16 | init(value: Value) 17 | init(error: Error) 18 | 19 | var result: Result { get } 20 | } 21 | 22 | extension Result: ResultProtocol { 23 | /// Constructs a success wrapping a `value`. 24 | public init(value: Success) { 25 | self = .success(value) 26 | } 27 | 28 | /// Constructs a failure wrapping an `error`. 29 | public init(error: Failure) { 30 | self = .failure(error) 31 | } 32 | 33 | public var result: Result { 34 | return self 35 | } 36 | 37 | public var value: Success? { 38 | switch self { 39 | case .success(let value): return value 40 | case .failure: return nil 41 | } 42 | } 43 | 44 | public var error: Failure? { 45 | switch self { 46 | case .success: return nil 47 | case .failure(let error): return error 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Example/Pods/BrightFutures/Sources/BrightFutures/SequenceType+BrightFutures.swift: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2014 Thomas Visser 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import Foundation 24 | 25 | extension Sequence { 26 | /// Turns a sequence of T's into an array of `Future`'s by calling the given closure for each element in the sequence. 27 | /// If no context is provided, the given closure is executed on `Queue.global` 28 | public func traverse(_ context: @escaping ExecutionContext = DispatchQueue.global().context, f: (Iterator.Element) -> A) -> Future<[U], E> where A.Value: ResultProtocol, A.Value.Value == U, A.Value.Error == E { 29 | return map(f).fold(context, zero: [U]()) { (list: [U], elem: U) -> [U] in 30 | return list + [elem] 31 | } 32 | } 33 | } 34 | 35 | extension Sequence where Iterator.Element: AsyncType { 36 | /// Returns a future that returns with the first future from the given sequence that completes 37 | /// (regardless of whether that future succeeds or fails) 38 | public func firstCompleted() -> Iterator.Element { 39 | let res = Async() 40 | for fut in self { 41 | fut.onComplete(DispatchQueue.global().context) { 42 | res.tryComplete($0) 43 | } 44 | } 45 | return Iterator.Element(other: res) 46 | } 47 | } 48 | 49 | extension Sequence where Iterator.Element: AsyncType, Iterator.Element.Value: ResultProtocol { 50 | 51 | //// The free functions in this file operate on sequences of Futures 52 | 53 | /// Performs the fold operation over a sequence of futures. The folding is performed 54 | /// on `Queue.global`. 55 | /// (The Swift compiler does not allow a context parameter with a default value 56 | /// so we define some functions twice) 57 | public func fold(_ zero: R, f: @escaping (R, Iterator.Element.Value.Value) -> R) -> Future { 58 | return fold(DispatchQueue.global().context, zero: zero, f: f) 59 | } 60 | 61 | /// Performs the fold operation over a sequence of futures. The folding is performed 62 | /// in the given context. 63 | public func fold(_ context: @escaping ExecutionContext, zero: R, f: @escaping (R, Iterator.Element.Value.Value) -> R) -> Future { 64 | return reduce(Future(value: zero)) { zero, elem in 65 | return zero.flatMap(MaxStackDepthExecutionContext) { zeroVal in 66 | elem.map(context) { elemVal in 67 | return f(zeroVal, elemVal) 68 | } 69 | } 70 | } 71 | } 72 | 73 | /// Turns a sequence of `Future`'s into a future with an array of T's (Future<[T]>) 74 | /// If one of the futures in the given sequence fails, the returned future will fail 75 | /// with the error of the first future that comes first in the list. 76 | public func sequence() -> Future<[Iterator.Element.Value.Value], Iterator.Element.Value.Error> { 77 | return traverse(ImmediateExecutionContext) { 78 | return $0 79 | } 80 | } 81 | 82 | /// See `find>(seq: S, context c: ExecutionContext, p: T -> Bool) -> Future` 83 | public func find(_ p: @escaping (Iterator.Element.Value.Value) -> Bool) -> Future> { 84 | return find(DispatchQueue.global().context, p: p) 85 | } 86 | 87 | /// Returns a future that succeeds with the value from the first future in the given 88 | /// sequence that passes the test `p`. 89 | /// If any of the futures in the given sequence fail, the returned future fails with the 90 | /// error of the first failed future in the sequence. 91 | /// If no futures in the sequence pass the test, a future with an error with NoSuchElement is returned. 92 | public func find(_ context: @escaping ExecutionContext, p: @escaping (Iterator.Element.Value.Value) -> Bool) -> Future> { 93 | return sequence().mapError(ImmediateExecutionContext) { error in 94 | return BrightFuturesError(external: error) 95 | }.flatMap(context) { val -> Result> in 96 | for elem in val { 97 | if (p(elem)) { 98 | return .success(elem) 99 | } 100 | } 101 | return .failure(.noSuchElement) 102 | } 103 | } 104 | } 105 | 106 | extension Sequence where Iterator.Element: ResultProtocol { 107 | /// Turns a sequence of `Result`'s into a Result with an array of T's (`Result<[T]>`) 108 | /// If one of the results in the given sequence is a .failure, the returned result is a .failure with the 109 | /// error from the first failed result from the sequence. 110 | public func sequence() -> Result<[Iterator.Element.Value], Iterator.Element.Error> { 111 | return reduce(.success([])) { (res, elem) -> Result<[Iterator.Element.Value], Iterator.Element.Error> in 112 | switch res { 113 | case .success(let resultSequence): 114 | return elem.analysis(ifSuccess: { 115 | let newSeq = resultSequence + [$0] 116 | return .success(newSeq) 117 | }, ifFailure: { 118 | return .failure($0) 119 | }) 120 | case .failure(_): 121 | return res 122 | } 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /Example/Pods/Local Podspecs/NADocumentPicker.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "NADocumentPicker", 3 | "version": "3.2.0", 4 | "summary": "Encapsulates UIKit document picker UI", 5 | "description": "Encapsulates UIKit document picker UI.\nAllows the user to select iCloud documents (and Google Drive, One Drive, etc), with a simple Future based API", 6 | "homepage": "http://nickager.com/blog/2016/03/07/DocumentPicker", 7 | "license": "MIT", 8 | "authors": { 9 | "Nick Ager": "nick.ager@gmail.com" 10 | }, 11 | "source": { 12 | "git": "https://github.com/NickAger/NADocumentPicker.git", 13 | "tag": "3.2.0" 14 | }, 15 | "platforms": { 16 | "ios": "12.0" 17 | }, 18 | "swift_versions": [ 19 | "5.0" 20 | ], 21 | "requires_arc": true, 22 | "source_files": "Pod/Classes/**/*", 23 | "frameworks": "UIKit", 24 | "dependencies": { 25 | "BrightFutures": [ 26 | 27 | ] 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Example/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - BrightFutures (8.0.0) 3 | - NADocumentPicker (3.2.0): 4 | - BrightFutures 5 | 6 | DEPENDENCIES: 7 | - BrightFutures 8 | - NADocumentPicker (from `../`) 9 | 10 | SPEC REPOS: 11 | https://github.com/cocoapods/specs.git: 12 | - BrightFutures 13 | 14 | EXTERNAL SOURCES: 15 | NADocumentPicker: 16 | :path: "../" 17 | 18 | SPEC CHECKSUMS: 19 | BrightFutures: f8427b46feabaf73c5e71ace7d86d65dfbb47696 20 | NADocumentPicker: a64ddaf309b54e6addc014ad49d1acdb3ea5f86e 21 | 22 | PODFILE CHECKSUM: b5e57d6297223ed12f8280f4f9db125458d525da 23 | 24 | COCOAPODS: 1.7.0.beta.2 25 | -------------------------------------------------------------------------------- /Example/Pods/Pods.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/BrightFutures/BrightFutures-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 8.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/BrightFutures/BrightFutures-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_BrightFutures : NSObject 3 | @end 4 | @implementation PodsDummy_BrightFutures 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/BrightFutures/BrightFutures-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/BrightFutures/BrightFutures-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double BrightFuturesVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char BrightFuturesVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/BrightFutures/BrightFutures.modulemap: -------------------------------------------------------------------------------- 1 | framework module BrightFutures { 2 | umbrella header "BrightFutures-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/BrightFutures/BrightFutures.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/BrightFutures 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 4 | PODS_BUILD_DIR = ${BUILD_DIR} 5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_ROOT = ${SRCROOT} 7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/BrightFutures 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/BrightFutures/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 7.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/NADocumentPicker/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 3.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/NADocumentPicker/NADocumentPicker-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 3.2.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/NADocumentPicker/NADocumentPicker-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_NADocumentPicker : NSObject 3 | @end 4 | @implementation PodsDummy_NADocumentPicker 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/NADocumentPicker/NADocumentPicker-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/NADocumentPicker/NADocumentPicker-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double NADocumentPickerVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char NADocumentPickerVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/NADocumentPicker/NADocumentPicker.modulemap: -------------------------------------------------------------------------------- 1 | framework module NADocumentPicker { 2 | umbrella header "NADocumentPicker-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/NADocumentPicker/NADocumentPicker.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/NADocumentPicker 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BrightFutures" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | OTHER_LDFLAGS = $(inherited) -framework "UIKit" 5 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_ROOT = ${SRCROOT} 9 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. 10 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | SKIP_INSTALL = YES 12 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Example/Pods-NADocumentPicker_Example-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Example/Pods-NADocumentPicker_Example-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## BrightFutures 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2014 Thomas Visser 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | ## NADocumentPicker 29 | 30 | Copyright (c) 2016 Nick Ager 31 | 32 | Permission is hereby granted, free of charge, to any person obtaining a copy 33 | of this software and associated documentation files (the "Software"), to deal 34 | in the Software without restriction, including without limitation the rights 35 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 36 | copies of the Software, and to permit persons to whom the Software is 37 | furnished to do so, subject to the following conditions: 38 | 39 | The above copyright notice and this permission notice shall be included in 40 | all copies or substantial portions of the Software. 41 | 42 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 43 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 44 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 45 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 46 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 47 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 48 | THE SOFTWARE. 49 | 50 | Generated by CocoaPods - https://cocoapods.org 51 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Example/Pods-NADocumentPicker_Example-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | The MIT License (MIT) 18 | 19 | Copyright (c) 2014 Thomas Visser 20 | 21 | Permission is hereby granted, free of charge, to any person obtaining a copy 22 | of this software and associated documentation files (the "Software"), to deal 23 | in the Software without restriction, including without limitation the rights 24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | copies of the Software, and to permit persons to whom the Software is 26 | furnished to do so, subject to the following conditions: 27 | 28 | The above copyright notice and this permission notice shall be included in all 29 | copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | SOFTWARE. 38 | License 39 | MIT 40 | Title 41 | BrightFutures 42 | Type 43 | PSGroupSpecifier 44 | 45 | 46 | FooterText 47 | Copyright (c) 2016 Nick Ager <nick.ager@gmail.com> 48 | 49 | Permission is hereby granted, free of charge, to any person obtaining a copy 50 | of this software and associated documentation files (the "Software"), to deal 51 | in the Software without restriction, including without limitation the rights 52 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 53 | copies of the Software, and to permit persons to whom the Software is 54 | furnished to do so, subject to the following conditions: 55 | 56 | The above copyright notice and this permission notice shall be included in 57 | all copies or substantial portions of the Software. 58 | 59 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 60 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 61 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 62 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 63 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 64 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 65 | THE SOFTWARE. 66 | 67 | License 68 | MIT 69 | Title 70 | NADocumentPicker 71 | Type 72 | PSGroupSpecifier 73 | 74 | 75 | FooterText 76 | Generated by CocoaPods - https://cocoapods.org 77 | Title 78 | 79 | Type 80 | PSGroupSpecifier 81 | 82 | 83 | StringsTable 84 | Acknowledgements 85 | Title 86 | Acknowledgements 87 | 88 | 89 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Example/Pods-NADocumentPicker_Example-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_NADocumentPicker_Example : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_NADocumentPicker_Example 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Example/Pods-NADocumentPicker_Example-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | function on_error { 7 | echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" 8 | } 9 | trap 'on_error $LINENO' ERR 10 | 11 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 12 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 13 | # frameworks to, so exit 0 (signalling the script phase was successful). 14 | exit 0 15 | fi 16 | 17 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 18 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 19 | 20 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 21 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 22 | 23 | # Used as a return value for each invocation of `strip_invalid_archs` function. 24 | STRIP_BINARY_RETVAL=0 25 | 26 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 27 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 28 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 29 | 30 | # Copies and strips a vendored framework 31 | install_framework() 32 | { 33 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 34 | local source="${BUILT_PRODUCTS_DIR}/$1" 35 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 36 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 37 | elif [ -r "$1" ]; then 38 | local source="$1" 39 | fi 40 | 41 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 42 | 43 | if [ -L "${source}" ]; then 44 | echo "Symlinked..." 45 | source="$(readlink "${source}")" 46 | fi 47 | 48 | # Use filter instead of exclude so missing patterns don't throw errors. 49 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 50 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 51 | 52 | local basename 53 | basename="$(basename -s .framework "$1")" 54 | binary="${destination}/${basename}.framework/${basename}" 55 | 56 | if ! [ -r "$binary" ]; then 57 | binary="${destination}/${basename}" 58 | elif [ -L "${binary}" ]; then 59 | echo "Destination binary is symlinked..." 60 | dirname="$(dirname "${binary}")" 61 | binary="${dirname}/$(readlink "${binary}")" 62 | fi 63 | 64 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 65 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 66 | strip_invalid_archs "$binary" 67 | fi 68 | 69 | # Resign the code if required by the build settings to avoid unstable apps 70 | code_sign_if_enabled "${destination}/$(basename "$1")" 71 | 72 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 73 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 74 | local swift_runtime_libs 75 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) 76 | for lib in $swift_runtime_libs; do 77 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 78 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 79 | code_sign_if_enabled "${destination}/${lib}" 80 | done 81 | fi 82 | } 83 | 84 | # Copies and strips a vendored dSYM 85 | install_dsym() { 86 | local source="$1" 87 | if [ -r "$source" ]; then 88 | # Copy the dSYM into a the targets temp dir. 89 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 90 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 91 | 92 | local basename 93 | basename="$(basename -s .framework.dSYM "$source")" 94 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 95 | 96 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 97 | if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then 98 | strip_invalid_archs "$binary" 99 | fi 100 | 101 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 102 | # Move the stripped file into its final destination. 103 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 104 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 105 | else 106 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 107 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 108 | fi 109 | fi 110 | } 111 | 112 | # Copies the bcsymbolmap files of a vendored framework 113 | install_bcsymbolmap() { 114 | local bcsymbolmap_path="$1" 115 | local destination="${BUILT_PRODUCTS_DIR}" 116 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" 117 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" 118 | } 119 | 120 | # Signs a framework with the provided identity 121 | code_sign_if_enabled() { 122 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 123 | # Use the current code_sign_identity 124 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 125 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 126 | 127 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 128 | code_sign_cmd="$code_sign_cmd &" 129 | fi 130 | echo "$code_sign_cmd" 131 | eval "$code_sign_cmd" 132 | fi 133 | } 134 | 135 | # Strip invalid architectures 136 | strip_invalid_archs() { 137 | binary="$1" 138 | # Get architectures for current target binary 139 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 140 | # Intersect them with the architectures we are building for 141 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 142 | # If there are no archs supported by this binary then warn the user 143 | if [[ -z "$intersected_archs" ]]; then 144 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 145 | STRIP_BINARY_RETVAL=0 146 | return 147 | fi 148 | stripped="" 149 | for arch in $binary_archs; do 150 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 151 | # Strip non-valid architectures in-place 152 | lipo -remove "$arch" -output "$binary" "$binary" 153 | stripped="$stripped $arch" 154 | fi 155 | done 156 | if [[ "$stripped" ]]; then 157 | echo "Stripped $binary of architectures:$stripped" 158 | fi 159 | STRIP_BINARY_RETVAL=1 160 | } 161 | 162 | 163 | if [[ "$CONFIGURATION" == "Debug" ]]; then 164 | install_framework "${BUILT_PRODUCTS_DIR}/BrightFutures/BrightFutures.framework" 165 | install_framework "${BUILT_PRODUCTS_DIR}/NADocumentPicker/NADocumentPicker.framework" 166 | fi 167 | if [[ "$CONFIGURATION" == "Release" ]]; then 168 | install_framework "${BUILT_PRODUCTS_DIR}/BrightFutures/BrightFutures.framework" 169 | install_framework "${BUILT_PRODUCTS_DIR}/NADocumentPicker/NADocumentPicker.framework" 170 | fi 171 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 172 | wait 173 | fi 174 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Example/Pods-NADocumentPicker_Example-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then 7 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # resources to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 13 | 14 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 15 | > "$RESOURCES_TO_COPY" 16 | 17 | XCASSET_FILES=() 18 | 19 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 20 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 21 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 22 | 23 | case "${TARGETED_DEVICE_FAMILY:-}" in 24 | 1,2) 25 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 26 | ;; 27 | 1) 28 | TARGET_DEVICE_ARGS="--target-device iphone" 29 | ;; 30 | 2) 31 | TARGET_DEVICE_ARGS="--target-device ipad" 32 | ;; 33 | 3) 34 | TARGET_DEVICE_ARGS="--target-device tv" 35 | ;; 36 | 4) 37 | TARGET_DEVICE_ARGS="--target-device watch" 38 | ;; 39 | *) 40 | TARGET_DEVICE_ARGS="--target-device mac" 41 | ;; 42 | esac 43 | 44 | install_resource() 45 | { 46 | if [[ "$1" = /* ]] ; then 47 | RESOURCE_PATH="$1" 48 | else 49 | RESOURCE_PATH="${PODS_ROOT}/$1" 50 | fi 51 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 52 | cat << EOM 53 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 54 | EOM 55 | exit 1 56 | fi 57 | case $RESOURCE_PATH in 58 | *.storyboard) 59 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 60 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 61 | ;; 62 | *.xib) 63 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 64 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 65 | ;; 66 | *.framework) 67 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 68 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 69 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 70 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 71 | ;; 72 | *.xcdatamodel) 73 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 74 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 75 | ;; 76 | *.xcdatamodeld) 77 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 78 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 79 | ;; 80 | *.xcmappingmodel) 81 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 82 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 83 | ;; 84 | *.xcassets) 85 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 86 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 87 | ;; 88 | *) 89 | echo "$RESOURCE_PATH" || true 90 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 91 | ;; 92 | esac 93 | } 94 | 95 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 97 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 98 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 99 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 100 | fi 101 | rm -f "$RESOURCES_TO_COPY" 102 | 103 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] 104 | then 105 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 106 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 107 | while read line; do 108 | if [[ $line != "${PODS_ROOT}*" ]]; then 109 | XCASSET_FILES+=("$line") 110 | fi 111 | done <<<"$OTHER_XCASSETS" 112 | 113 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then 114 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 115 | else 116 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" 117 | fi 118 | fi 119 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Example/Pods-NADocumentPicker_Example-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_NADocumentPicker_ExampleVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_NADocumentPicker_ExampleVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Example/Pods-NADocumentPicker_Example.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BrightFutures" "${PODS_CONFIGURATION_BUILD_DIR}/NADocumentPicker" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BrightFutures/BrightFutures.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/NADocumentPicker/NADocumentPicker.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "BrightFutures" -framework "NADocumentPicker" -framework "UIKit" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Example/Pods-NADocumentPicker_Example.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_NADocumentPicker_Example { 2 | umbrella header "Pods-NADocumentPicker_Example-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Example/Pods-NADocumentPicker_Example.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BrightFutures" "${PODS_CONFIGURATION_BUILD_DIR}/NADocumentPicker" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BrightFutures/BrightFutures.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/NADocumentPicker/NADocumentPicker.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "BrightFutures" -framework "NADocumentPicker" -framework "UIKit" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Tests/Pods-NADocumentPicker_Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Tests/Pods-NADocumentPicker_Tests-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | Generated by CocoaPods - https://cocoapods.org 4 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Tests/Pods-NADocumentPicker_Tests-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Generated by CocoaPods - https://cocoapods.org 18 | Title 19 | 20 | Type 21 | PSGroupSpecifier 22 | 23 | 24 | StringsTable 25 | Acknowledgements 26 | Title 27 | Acknowledgements 28 | 29 | 30 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Tests/Pods-NADocumentPicker_Tests-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_NADocumentPicker_Tests : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_NADocumentPicker_Tests 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Tests/Pods-NADocumentPicker_Tests-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 7 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # frameworks to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 13 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 14 | 15 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 16 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 17 | 18 | # Used as a return value for each invocation of `strip_invalid_archs` function. 19 | STRIP_BINARY_RETVAL=0 20 | 21 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 22 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 23 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 24 | 25 | # Copies and strips a vendored framework 26 | install_framework() 27 | { 28 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 29 | local source="${BUILT_PRODUCTS_DIR}/$1" 30 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 31 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 32 | elif [ -r "$1" ]; then 33 | local source="$1" 34 | fi 35 | 36 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 37 | 38 | if [ -L "${source}" ]; then 39 | echo "Symlinked..." 40 | source="$(readlink "${source}")" 41 | fi 42 | 43 | # Use filter instead of exclude so missing patterns don't throw errors. 44 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 45 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 46 | 47 | local basename 48 | basename="$(basename -s .framework "$1")" 49 | binary="${destination}/${basename}.framework/${basename}" 50 | if ! [ -r "$binary" ]; then 51 | binary="${destination}/${basename}" 52 | fi 53 | 54 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 55 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 56 | strip_invalid_archs "$binary" 57 | fi 58 | 59 | # Resign the code if required by the build settings to avoid unstable apps 60 | code_sign_if_enabled "${destination}/$(basename "$1")" 61 | 62 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 63 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 64 | local swift_runtime_libs 65 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 66 | for lib in $swift_runtime_libs; do 67 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 68 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 69 | code_sign_if_enabled "${destination}/${lib}" 70 | done 71 | fi 72 | } 73 | 74 | # Copies and strips a vendored dSYM 75 | install_dsym() { 76 | local source="$1" 77 | if [ -r "$source" ]; then 78 | # Copy the dSYM into a the targets temp dir. 79 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 80 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 81 | 82 | local basename 83 | basename="$(basename -s .framework.dSYM "$source")" 84 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 85 | 86 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 87 | if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then 88 | strip_invalid_archs "$binary" 89 | fi 90 | 91 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 92 | # Move the stripped file into its final destination. 93 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 94 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 95 | else 96 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 97 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 98 | fi 99 | fi 100 | } 101 | 102 | # Signs a framework with the provided identity 103 | code_sign_if_enabled() { 104 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 105 | # Use the current code_sign_identitiy 106 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 107 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 108 | 109 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 110 | code_sign_cmd="$code_sign_cmd &" 111 | fi 112 | echo "$code_sign_cmd" 113 | eval "$code_sign_cmd" 114 | fi 115 | } 116 | 117 | # Strip invalid architectures 118 | strip_invalid_archs() { 119 | binary="$1" 120 | # Get architectures for current target binary 121 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 122 | # Intersect them with the architectures we are building for 123 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 124 | # If there are no archs supported by this binary then warn the user 125 | if [[ -z "$intersected_archs" ]]; then 126 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 127 | STRIP_BINARY_RETVAL=0 128 | return 129 | fi 130 | stripped="" 131 | for arch in $binary_archs; do 132 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 133 | # Strip non-valid architectures in-place 134 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 135 | stripped="$stripped $arch" 136 | fi 137 | done 138 | if [[ "$stripped" ]]; then 139 | echo "Stripped $binary of architectures:$stripped" 140 | fi 141 | STRIP_BINARY_RETVAL=1 142 | } 143 | 144 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 145 | wait 146 | fi 147 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Tests/Pods-NADocumentPicker_Tests-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then 7 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # resources to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 13 | 14 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 15 | > "$RESOURCES_TO_COPY" 16 | 17 | XCASSET_FILES=() 18 | 19 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 20 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 21 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 22 | 23 | case "${TARGETED_DEVICE_FAMILY:-}" in 24 | 1,2) 25 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 26 | ;; 27 | 1) 28 | TARGET_DEVICE_ARGS="--target-device iphone" 29 | ;; 30 | 2) 31 | TARGET_DEVICE_ARGS="--target-device ipad" 32 | ;; 33 | 3) 34 | TARGET_DEVICE_ARGS="--target-device tv" 35 | ;; 36 | 4) 37 | TARGET_DEVICE_ARGS="--target-device watch" 38 | ;; 39 | *) 40 | TARGET_DEVICE_ARGS="--target-device mac" 41 | ;; 42 | esac 43 | 44 | install_resource() 45 | { 46 | if [[ "$1" = /* ]] ; then 47 | RESOURCE_PATH="$1" 48 | else 49 | RESOURCE_PATH="${PODS_ROOT}/$1" 50 | fi 51 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 52 | cat << EOM 53 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 54 | EOM 55 | exit 1 56 | fi 57 | case $RESOURCE_PATH in 58 | *.storyboard) 59 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 60 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 61 | ;; 62 | *.xib) 63 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 64 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 65 | ;; 66 | *.framework) 67 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 68 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 69 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 70 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 71 | ;; 72 | *.xcdatamodel) 73 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 74 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 75 | ;; 76 | *.xcdatamodeld) 77 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 78 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 79 | ;; 80 | *.xcmappingmodel) 81 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 82 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 83 | ;; 84 | *.xcassets) 85 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 86 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 87 | ;; 88 | *) 89 | echo "$RESOURCE_PATH" || true 90 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 91 | ;; 92 | esac 93 | } 94 | 95 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 97 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 98 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 99 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 100 | fi 101 | rm -f "$RESOURCES_TO_COPY" 102 | 103 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] 104 | then 105 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 106 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 107 | while read line; do 108 | if [[ $line != "${PODS_ROOT}*" ]]; then 109 | XCASSET_FILES+=("$line") 110 | fi 111 | done <<<"$OTHER_XCASSETS" 112 | 113 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then 114 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 115 | else 116 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" 117 | fi 118 | fi 119 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Tests/Pods-NADocumentPicker_Tests-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_NADocumentPicker_TestsVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_NADocumentPicker_TestsVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Tests/Pods-NADocumentPicker_Tests.debug.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BrightFutures" "${PODS_CONFIGURATION_BUILD_DIR}/NADocumentPicker" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BrightFutures/BrightFutures.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/NADocumentPicker/NADocumentPicker.framework/Headers" 4 | OTHER_LDFLAGS = $(inherited) -framework "BrightFutures" -framework "NADocumentPicker" -framework "UIKit" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 8 | PODS_ROOT = ${SRCROOT}/Pods 9 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Tests/Pods-NADocumentPicker_Tests.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_NADocumentPicker_Tests { 2 | umbrella header "Pods-NADocumentPicker_Tests-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-NADocumentPicker_Tests/Pods-NADocumentPicker_Tests.release.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BrightFutures" "${PODS_CONFIGURATION_BUILD_DIR}/NADocumentPicker" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BrightFutures/BrightFutures.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/NADocumentPicker/NADocumentPicker.framework/Headers" 4 | OTHER_LDFLAGS = $(inherited) -framework "BrightFutures" -framework "NADocumentPicker" -framework "UIKit" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 8 | PODS_ROOT = ${SRCROOT}/Pods 9 | -------------------------------------------------------------------------------- /Example/Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/Tests/Tests.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import XCTest 3 | @testable import NADocumentPicker_Example 4 | @testable import NADocumentPicker 5 | import BrightFutures 6 | 7 | class Tests: XCTestCase { 8 | 9 | func testMemoryLeaks() { 10 | let expectationTest = expectation(description: "Future will complete") 11 | let vc = UIViewController() 12 | let dp = NADocumentPicker(parentViewController: vc) 13 | 14 | dp.promise.future.onComplete { [weak dp] _ in 15 | XCTAssert(dp == nil, "Expect the instance of NADocumentPicker to have freed itself") 16 | expectationTest.fulfill() 17 | } 18 | 19 | DispatchQueue.global().async { [weak dp] in 20 | if let dp = dp { 21 | // simulate a failure on a background thread 22 | dp.promise.failure(NADocumentPickerErrors.noDocumentPicked) 23 | } 24 | } 25 | 26 | waitForExpectations(timeout: 10) { error in 27 | if let error = error { 28 | print("Error: \(error.localizedDescription)") 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Nick Ager 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /NADocumentPicker.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "NADocumentPicker" 3 | s.version = "3.3.0" 4 | s.summary = "Encapsulates UIKit document picker UI" 5 | s.description = <<-DESC 6 | Encapsulates UIKit document picker UI. 7 | Allows the user to select iCloud documents (and Google Drive, One Drive, etc), with a simple Future based API 8 | DESC 9 | 10 | s.homepage = "http://nickager.com/blog/2016/03/07/DocumentPicker" 11 | s.license = 'MIT' 12 | s.author = { "Nick Ager" => "nick.ager@gmail.com" } 13 | s.source = { :git => "https://github.com/NickAger/NADocumentPicker.git", :tag => s.version.to_s } 14 | # s.social_media_url = 'https://twitter.com/NickAger' 15 | 16 | s.ios.deployment_target = '12.0' 17 | s.swift_versions = ['5.0'] 18 | s.platform = :ios, '12.0' 19 | s.requires_arc = true 20 | 21 | s.source_files = 'Pod/Classes/**/*' 22 | 23 | s.frameworks = 'UIKit' 24 | s.dependency 'BrightFutures' 25 | end 26 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | import PackageDescription 2 | 3 | let package = Package( 4 | name: "BrightFutures", 5 | dependencies: [ 6 | .Package(url: "https://github.com/Thomvis/BrightFutures.git", majorVersion: 8) 7 | ] 8 | ) 9 | -------------------------------------------------------------------------------- /Pod/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NickAger/NADocumentPicker/382d746a347fdde42a85db6101dcfa4fdb52b9e0/Pod/Assets/.gitkeep -------------------------------------------------------------------------------- /Pod/Classes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NickAger/NADocumentPicker/382d746a347fdde42a85db6101dcfa4fdb52b9e0/Pod/Classes/.gitkeep -------------------------------------------------------------------------------- /Pod/Classes/NADocumentPicker.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NADocumentPicker.swift 3 | // Encapsulates UIKit document picker UI 4 | // iDiffView 5 | // 6 | // "Why doesn't Dropbox support iOS's open dialog?" - see discussion here: https://www.dropboxforum.com/hc/en-us/community/posts/204836509-Why-doesn-t-Dropbox-support-iOS-s-open-dialog- 7 | // 8 | // Created by Nick Ager on 25/01/2016. 9 | // Copyright © 2016 RocketBox Ltd. All rights reserved. 10 | // 11 | 12 | import UIKit 13 | import MobileCoreServices 14 | import BrightFutures 15 | 16 | /** 17 | Error type for `NADocumentPicker` 18 | 19 | - NoDocumentPicked: is the error returned by the `Future` 20 | from `show` when no document is choosen by the user. 21 | */ 22 | public enum NADocumentPickerErrors: Error { 23 | case noDocumentPicked 24 | } 25 | 26 | /** 27 | Encapsulates UIKit document picker UI, providing a simple API. 28 | `show` is the only API entry. 29 | */ 30 | open class NADocumentPicker : NSObject { 31 | fileprivate let parentViewController: UIViewController 32 | fileprivate var keepInMemory: NADocumentPicker? 33 | /*private*/ let promise = Promise() 34 | 35 | /** 36 | Shows the document picker, returning a `Future` containing the document picked 37 | or `NoDocumentPicked`. 38 | 39 | See also: 40 | - [nickager.com](http://nickager.com/blog/2016/03/07/DocumentPicker) 41 | - [github](https://github.com/NickAger/NADocumentPicker) 42 | 43 | - Parameter view: The view from which the popover document menu appears 44 | - Parameter parentViewController: The associated parent view controller 45 | - Parameter documentTypes: An array of document types to be opened, by default PlainText 46 | 47 | - Returns: A `Future` containing the document picked or `NoDocumentPicked` 48 | */ 49 | open class func show(from view: UIView, parentViewController: UIViewController, documentTypes: [String] = [kUTTypePlainText as String]) -> Future { 50 | let instance = NADocumentPicker(parentViewController: parentViewController) 51 | return instance.showDocumentPicker(from: view, parentViewController: parentViewController, documentTypes: documentTypes) 52 | } 53 | 54 | /*private*/ init(parentViewController: UIViewController) { 55 | self.parentViewController = parentViewController 56 | super.init() 57 | 58 | keepInMemoryUntilComplete() 59 | } 60 | 61 | private func showDocumentPicker(from view: UIView, parentViewController: UIViewController, documentTypes: [String]) -> Future { 62 | let documentPicker = UIDocumentPickerViewController(documentTypes:documentTypes, in: UIDocumentPickerMode.open) 63 | documentPicker.delegate = self 64 | 65 | parentViewController.present(documentPicker, animated: true) 66 | return promise.future 67 | } 68 | 69 | private func keepOurselvesInMemory() { 70 | keepInMemory = self 71 | } 72 | 73 | private func freeOurselvesFromMemory() { 74 | keepInMemory = nil 75 | } 76 | 77 | private func keepInMemoryUntilComplete() { 78 | keepOurselvesInMemory() 79 | self.promise.future.onComplete { [unowned self] _ in 80 | self.freeOurselvesFromMemory() 81 | } 82 | } 83 | } 84 | 85 | // MARK: UIDocumentPickerDelegate 86 | extension NADocumentPicker : UIDocumentPickerDelegate { 87 | public func documentPicker(_: UIDocumentPickerViewController, didPickDocumentAt url: URL) { 88 | promise.success(url) 89 | } 90 | 91 | public func documentPickerWasCancelled(_: UIDocumentPickerViewController) { 92 | promise.failure(NADocumentPickerErrors.noDocumentPicked) 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NADocumentPicker 2 | 3 | [![CI Status](http://img.shields.io/travis/NickAger/NADocumentPicker.svg?style=flat)](https://travis-ci.org/NickAger/NADocumentPicker) 4 | [![Version](https://img.shields.io/cocoapods/v/NADocumentPicker.svg?style=flat)](http://cocoapods.org/pods/NADocumentPicker) 5 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 6 | [![License](https://img.shields.io/cocoapods/l/NADocumentPicker.svg?style=flat)](http://cocoapods.org/pods/NADocumentPicker) 7 | [![Platform](https://img.shields.io/cocoapods/p/NADocumentPicker.svg?style=flat)](http://cocoapods.org/pods/NADocumentPicker) 8 | 9 | `NADocumentPicker` encapsulates UIKit document picker UI allowing the user to select iCloud documents (and Google Drive, One Drive, etc), with a simple [`Future` ](https://github.com/Thomvis/BrightFutures) based API: 10 | 11 | ![](http://nickager.com/images/blog/DocumentPicker/filepicker-combined.jpg) 12 | 13 | ## Usage 14 | 15 | `NADocumentPicker.show(..)` returns a [`Future` ](https://github.com/Thomvis/BrightFutures#examples). Hooking into `onSuccess` provides the URL of the file choosen by the user: 16 | 17 | ```swift 18 | @IBAction func pickerButtonPressed(sender: UIButton) { 19 | let urlPickedfuture = NADocumentPicker.show(from: sender, parentViewController: self) 20 | 21 | urlPickedfuture.onSuccess { url in 22 | print("URL: \(url)") 23 | } 24 | } 25 | ``` 26 | 27 | You can try-out `NADocumentPicker` demo project by using the cocoapod `try` option as: 28 | 29 | ``` 30 | $ pod try NADocumentPicker 31 | ``` 32 | 33 | ## Installation 34 | 35 | NADocumentPicker is available through [CocoaPods](http://cocoapods.org). To install 36 | it, simply add the following line to your Podfile: 37 | 38 | ```ruby 39 | pod "NADocumentPicker" 40 | ``` 41 | 42 | ## Configuration 43 | 44 | You need to ensure you give your application the following entitlements: 45 | 46 | * iCloud entitlement 47 | * iCloud containers entitlement 48 | 49 | See below: 50 | 51 | ![](Example/NADocumentPicker/iCloudFix@2x.png) 52 | 53 | If you haven't added these entitlements you will have a runtime exception as: 54 | 55 | > Application initializing document picker is missing the iCloud entitlement. Is com.apple.developer.icloud-container-identifiers set? 56 | 57 | ## Author 58 | 59 | Nick Ager, nick.ager@gmail.com 60 | 61 | ## License 62 | 63 | NADocumentPicker is available under the MIT license. See the LICENSE file for more info. 64 | 65 | --- 66 | 67 | For more detail see [http://nickager.com/blog/2016/03/07/DocumentPicker](http://nickager.com/blog/2016/03/07/DocumentPicker) 68 | -------------------------------------------------------------------------------- /_Pods.xcodeproj: -------------------------------------------------------------------------------- 1 | Example/Pods/Pods.xcodeproj --------------------------------------------------------------------------------