├── .gitignore ├── .travis.yml ├── APNSUtil.podspec ├── APNSUtil.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ └── APNSUtil.xcscheme ├── APNSUtil ├── APNSUtil.h ├── Assets │ └── .gitkeep ├── Classes │ ├── .gitkeep │ ├── APNSInstance.swift │ ├── APNSManager.swift │ └── NSObject+Codable.swift └── Info.plist ├── APNSUtilAppExtension.podspec ├── Example ├── APNSUtil.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── APNSUtil-Example.xcscheme ├── APNSUtil.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── APNSUtil │ ├── APNSPayload.swift │ ├── AppDelegate.swift │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ └── ViewController.swift ├── Podfile ├── Podfile.lock └── Tests │ ├── Info.plist │ └── Tests.swift ├── LICENSE ├── README.md └── _Pods.xcodeproj /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | .build/ 41 | 42 | # CocoaPods 43 | # 44 | # We recommend against adding the Pods directory to your .gitignore. However 45 | # you should judge for yourself, the pros and cons are mentioned at: 46 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 47 | # 48 | Pods/ 49 | Example/Pods/ 50 | 51 | # Carthage 52 | # 53 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 54 | # Carthage/Checkouts 55 | 56 | # Carthage/Build 57 | 58 | # fastlane 59 | # 60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 61 | # screenshots whenever they are needed. 62 | # For more information about the recommended setup visit: 63 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 64 | 65 | fastlane/report.xml 66 | fastlane/Preview.html 67 | fastlane/screenshots 68 | fastlane/test_output 69 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: swift 2 | osx_image: xcode10.3 3 | script: set -o pipefail && xcodebuild -project APNSUtil.xcodeproj -scheme APNSUtil -sdk iphonesimulator | xcpretty 4 | -------------------------------------------------------------------------------- /APNSUtil.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint APNSUtil.podspec' to ensure this is a 3 | # valid spec before submitting. 4 | # 5 | # Any lines starting with a # are optional, but their use is encouraged 6 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | s.name = 'APNSUtil' 11 | s.version = '1.6.0' 12 | s.summary = 'APNSUtil is makes code simple using apple push notification service.' 13 | s.description = 'APNSUtil is makes code simple using apple push notification service.' 14 | s.homepage = 'https://github.com/pisces/APNSUtil' 15 | s.license = { :type => 'MIT', :file => 'LICENSE' } 16 | s.author = { 'pisces' => 'hh963103@gmail.com' } 17 | s.source = { :git => 'https://github.com/pisces/APNSUtil.git', :tag => s.version.to_s } 18 | s.ios.deployment_target = '9.0' 19 | s.source_files = 'APNSUtil/Classes/**/*' 20 | end 21 | -------------------------------------------------------------------------------- /APNSUtil.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2301E972205A51F300E0E358 /* APNSUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 2301E970205A51F300E0E358 /* APNSUtil.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 2301E97B205A524B00E0E358 /* APNSInstance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2301E978205A524B00E0E358 /* APNSInstance.swift */; }; 12 | 2301E97C205A524B00E0E358 /* APNSManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2301E979205A524B00E0E358 /* APNSManager.swift */; }; 13 | 2301E97D205A524B00E0E358 /* NSObject+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2301E97A205A524B00E0E358 /* NSObject+Codable.swift */; }; 14 | /* End PBXBuildFile section */ 15 | 16 | /* Begin PBXFileReference section */ 17 | 2301E96D205A51F300E0E358 /* APNSUtil.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = APNSUtil.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 18 | 2301E970205A51F300E0E358 /* APNSUtil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = APNSUtil.h; sourceTree = ""; }; 19 | 2301E971205A51F300E0E358 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 20 | 2301E978205A524B00E0E358 /* APNSInstance.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = APNSInstance.swift; path = Classes/APNSInstance.swift; sourceTree = ""; }; 21 | 2301E979205A524B00E0E358 /* APNSManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = APNSManager.swift; path = Classes/APNSManager.swift; sourceTree = ""; }; 22 | 2301E97A205A524B00E0E358 /* NSObject+Codable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "NSObject+Codable.swift"; path = "Classes/NSObject+Codable.swift"; sourceTree = ""; }; 23 | /* End PBXFileReference section */ 24 | 25 | /* Begin PBXFrameworksBuildPhase section */ 26 | 2301E969205A51F300E0E358 /* Frameworks */ = { 27 | isa = PBXFrameworksBuildPhase; 28 | buildActionMask = 2147483647; 29 | files = ( 30 | ); 31 | runOnlyForDeploymentPostprocessing = 0; 32 | }; 33 | /* End PBXFrameworksBuildPhase section */ 34 | 35 | /* Begin PBXGroup section */ 36 | 2301E963205A51F300E0E358 = { 37 | isa = PBXGroup; 38 | children = ( 39 | 2301E96F205A51F300E0E358 /* APNSUtil */, 40 | 2301E96E205A51F300E0E358 /* Products */, 41 | ); 42 | sourceTree = ""; 43 | }; 44 | 2301E96E205A51F300E0E358 /* Products */ = { 45 | isa = PBXGroup; 46 | children = ( 47 | 2301E96D205A51F300E0E358 /* APNSUtil.framework */, 48 | ); 49 | name = Products; 50 | sourceTree = ""; 51 | }; 52 | 2301E96F205A51F300E0E358 /* APNSUtil */ = { 53 | isa = PBXGroup; 54 | children = ( 55 | 2301E978205A524B00E0E358 /* APNSInstance.swift */, 56 | 2301E979205A524B00E0E358 /* APNSManager.swift */, 57 | 2301E97A205A524B00E0E358 /* NSObject+Codable.swift */, 58 | 2301E970205A51F300E0E358 /* APNSUtil.h */, 59 | 2301E971205A51F300E0E358 /* Info.plist */, 60 | ); 61 | path = APNSUtil; 62 | sourceTree = ""; 63 | }; 64 | /* End PBXGroup section */ 65 | 66 | /* Begin PBXHeadersBuildPhase section */ 67 | 2301E96A205A51F300E0E358 /* Headers */ = { 68 | isa = PBXHeadersBuildPhase; 69 | buildActionMask = 2147483647; 70 | files = ( 71 | 2301E972205A51F300E0E358 /* APNSUtil.h in Headers */, 72 | ); 73 | runOnlyForDeploymentPostprocessing = 0; 74 | }; 75 | /* End PBXHeadersBuildPhase section */ 76 | 77 | /* Begin PBXNativeTarget section */ 78 | 2301E96C205A51F300E0E358 /* APNSUtil */ = { 79 | isa = PBXNativeTarget; 80 | buildConfigurationList = 2301E975205A51F300E0E358 /* Build configuration list for PBXNativeTarget "APNSUtil" */; 81 | buildPhases = ( 82 | 2301E968205A51F300E0E358 /* Sources */, 83 | 2301E969205A51F300E0E358 /* Frameworks */, 84 | 2301E96A205A51F300E0E358 /* Headers */, 85 | 2301E96B205A51F300E0E358 /* Resources */, 86 | ); 87 | buildRules = ( 88 | ); 89 | dependencies = ( 90 | ); 91 | name = APNSUtil; 92 | productName = APNSUtil; 93 | productReference = 2301E96D205A51F300E0E358 /* APNSUtil.framework */; 94 | productType = "com.apple.product-type.framework"; 95 | }; 96 | /* End PBXNativeTarget section */ 97 | 98 | /* Begin PBXProject section */ 99 | 2301E964205A51F300E0E358 /* Project object */ = { 100 | isa = PBXProject; 101 | attributes = { 102 | LastUpgradeCheck = 1120; 103 | ORGANIZATIONNAME = pisces; 104 | TargetAttributes = { 105 | 2301E96C205A51F300E0E358 = { 106 | CreatedOnToolsVersion = 9.2; 107 | LastSwiftMigration = 0920; 108 | ProvisioningStyle = Automatic; 109 | }; 110 | }; 111 | }; 112 | buildConfigurationList = 2301E967205A51F300E0E358 /* Build configuration list for PBXProject "APNSUtil" */; 113 | compatibilityVersion = "Xcode 8.0"; 114 | developmentRegion = en; 115 | hasScannedForEncodings = 0; 116 | knownRegions = ( 117 | en, 118 | Base, 119 | ); 120 | mainGroup = 2301E963205A51F300E0E358; 121 | productRefGroup = 2301E96E205A51F300E0E358 /* Products */; 122 | projectDirPath = ""; 123 | projectRoot = ""; 124 | targets = ( 125 | 2301E96C205A51F300E0E358 /* APNSUtil */, 126 | ); 127 | }; 128 | /* End PBXProject section */ 129 | 130 | /* Begin PBXResourcesBuildPhase section */ 131 | 2301E96B205A51F300E0E358 /* Resources */ = { 132 | isa = PBXResourcesBuildPhase; 133 | buildActionMask = 2147483647; 134 | files = ( 135 | ); 136 | runOnlyForDeploymentPostprocessing = 0; 137 | }; 138 | /* End PBXResourcesBuildPhase section */ 139 | 140 | /* Begin PBXSourcesBuildPhase section */ 141 | 2301E968205A51F300E0E358 /* Sources */ = { 142 | isa = PBXSourcesBuildPhase; 143 | buildActionMask = 2147483647; 144 | files = ( 145 | 2301E97B205A524B00E0E358 /* APNSInstance.swift in Sources */, 146 | 2301E97D205A524B00E0E358 /* NSObject+Codable.swift in Sources */, 147 | 2301E97C205A524B00E0E358 /* APNSManager.swift in Sources */, 148 | ); 149 | runOnlyForDeploymentPostprocessing = 0; 150 | }; 151 | /* End PBXSourcesBuildPhase section */ 152 | 153 | /* Begin XCBuildConfiguration section */ 154 | 2301E973205A51F300E0E358 /* Debug */ = { 155 | isa = XCBuildConfiguration; 156 | buildSettings = { 157 | ALWAYS_SEARCH_USER_PATHS = NO; 158 | CLANG_ANALYZER_NONNULL = YES; 159 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 160 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 161 | CLANG_CXX_LIBRARY = "libc++"; 162 | CLANG_ENABLE_MODULES = YES; 163 | CLANG_ENABLE_OBJC_ARC = YES; 164 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 165 | CLANG_WARN_BOOL_CONVERSION = YES; 166 | CLANG_WARN_COMMA = YES; 167 | CLANG_WARN_CONSTANT_CONVERSION = YES; 168 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 169 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 170 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 171 | CLANG_WARN_EMPTY_BODY = YES; 172 | CLANG_WARN_ENUM_CONVERSION = YES; 173 | CLANG_WARN_INFINITE_RECURSION = YES; 174 | CLANG_WARN_INT_CONVERSION = YES; 175 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 176 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 177 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 178 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 179 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 180 | CLANG_WARN_STRICT_PROTOTYPES = YES; 181 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 182 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 183 | CLANG_WARN_UNREACHABLE_CODE = YES; 184 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 185 | CODE_SIGN_IDENTITY = "iPhone Developer"; 186 | COPY_PHASE_STRIP = NO; 187 | CURRENT_PROJECT_VERSION = 1; 188 | DEBUG_INFORMATION_FORMAT = dwarf; 189 | ENABLE_STRICT_OBJC_MSGSEND = YES; 190 | ENABLE_TESTABILITY = YES; 191 | GCC_C_LANGUAGE_STANDARD = gnu11; 192 | GCC_DYNAMIC_NO_PIC = NO; 193 | GCC_NO_COMMON_BLOCKS = YES; 194 | GCC_OPTIMIZATION_LEVEL = 0; 195 | GCC_PREPROCESSOR_DEFINITIONS = ( 196 | "DEBUG=1", 197 | "$(inherited)", 198 | ); 199 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 200 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 201 | GCC_WARN_UNDECLARED_SELECTOR = YES; 202 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 203 | GCC_WARN_UNUSED_FUNCTION = YES; 204 | GCC_WARN_UNUSED_VARIABLE = YES; 205 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 206 | MTL_ENABLE_DEBUG_INFO = YES; 207 | ONLY_ACTIVE_ARCH = YES; 208 | SDKROOT = iphoneos; 209 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 210 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 211 | VERSIONING_SYSTEM = "apple-generic"; 212 | VERSION_INFO_PREFIX = ""; 213 | }; 214 | name = Debug; 215 | }; 216 | 2301E974205A51F300E0E358 /* Release */ = { 217 | isa = XCBuildConfiguration; 218 | buildSettings = { 219 | ALWAYS_SEARCH_USER_PATHS = NO; 220 | CLANG_ANALYZER_NONNULL = YES; 221 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 222 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 223 | CLANG_CXX_LIBRARY = "libc++"; 224 | CLANG_ENABLE_MODULES = YES; 225 | CLANG_ENABLE_OBJC_ARC = YES; 226 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 227 | CLANG_WARN_BOOL_CONVERSION = YES; 228 | CLANG_WARN_COMMA = YES; 229 | CLANG_WARN_CONSTANT_CONVERSION = YES; 230 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 231 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 232 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 233 | CLANG_WARN_EMPTY_BODY = YES; 234 | CLANG_WARN_ENUM_CONVERSION = YES; 235 | CLANG_WARN_INFINITE_RECURSION = YES; 236 | CLANG_WARN_INT_CONVERSION = YES; 237 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 238 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 239 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 240 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 241 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 242 | CLANG_WARN_STRICT_PROTOTYPES = YES; 243 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 244 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 245 | CLANG_WARN_UNREACHABLE_CODE = YES; 246 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 247 | CODE_SIGN_IDENTITY = "iPhone Developer"; 248 | COPY_PHASE_STRIP = NO; 249 | CURRENT_PROJECT_VERSION = 1; 250 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 251 | ENABLE_NS_ASSERTIONS = NO; 252 | ENABLE_STRICT_OBJC_MSGSEND = YES; 253 | GCC_C_LANGUAGE_STANDARD = gnu11; 254 | GCC_NO_COMMON_BLOCKS = YES; 255 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 256 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 257 | GCC_WARN_UNDECLARED_SELECTOR = YES; 258 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 259 | GCC_WARN_UNUSED_FUNCTION = YES; 260 | GCC_WARN_UNUSED_VARIABLE = YES; 261 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 262 | MTL_ENABLE_DEBUG_INFO = NO; 263 | SDKROOT = iphoneos; 264 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 265 | VALIDATE_PRODUCT = YES; 266 | VERSIONING_SYSTEM = "apple-generic"; 267 | VERSION_INFO_PREFIX = ""; 268 | }; 269 | name = Release; 270 | }; 271 | 2301E976205A51F300E0E358 /* Debug */ = { 272 | isa = XCBuildConfiguration; 273 | buildSettings = { 274 | CLANG_ENABLE_MODULES = YES; 275 | CODE_SIGN_IDENTITY = ""; 276 | CODE_SIGN_STYLE = Automatic; 277 | DEFINES_MODULE = YES; 278 | DYLIB_COMPATIBILITY_VERSION = 1; 279 | DYLIB_CURRENT_VERSION = 1; 280 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 281 | FRAMEWORK_SEARCH_PATHS = "${PROJECT_DIR}/Carthage/Build/iOS"; 282 | INFOPLIST_FILE = APNSUtil/Info.plist; 283 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 284 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 285 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 286 | ONLY_ACTIVE_ARCH = YES; 287 | OTHER_LDFLAGS = ""; 288 | PRODUCT_BUNDLE_IDENTIFIER = pisces.lib.APNSUtil; 289 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 290 | SKIP_INSTALL = YES; 291 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 292 | SWIFT_VERSION = 5.0; 293 | TARGETED_DEVICE_FAMILY = "1,2"; 294 | }; 295 | name = Debug; 296 | }; 297 | 2301E977205A51F300E0E358 /* Release */ = { 298 | isa = XCBuildConfiguration; 299 | buildSettings = { 300 | CLANG_ENABLE_MODULES = YES; 301 | CODE_SIGN_IDENTITY = ""; 302 | CODE_SIGN_STYLE = Automatic; 303 | DEFINES_MODULE = YES; 304 | DYLIB_COMPATIBILITY_VERSION = 1; 305 | DYLIB_CURRENT_VERSION = 1; 306 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 307 | FRAMEWORK_SEARCH_PATHS = "${PROJECT_DIR}/Carthage/Build/iOS"; 308 | INFOPLIST_FILE = APNSUtil/Info.plist; 309 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 310 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 311 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 312 | ONLY_ACTIVE_ARCH = YES; 313 | OTHER_LDFLAGS = ""; 314 | PRODUCT_BUNDLE_IDENTIFIER = pisces.lib.APNSUtil; 315 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 316 | SKIP_INSTALL = YES; 317 | SWIFT_VERSION = 5.0; 318 | TARGETED_DEVICE_FAMILY = "1,2"; 319 | }; 320 | name = Release; 321 | }; 322 | /* End XCBuildConfiguration section */ 323 | 324 | /* Begin XCConfigurationList section */ 325 | 2301E967205A51F300E0E358 /* Build configuration list for PBXProject "APNSUtil" */ = { 326 | isa = XCConfigurationList; 327 | buildConfigurations = ( 328 | 2301E973205A51F300E0E358 /* Debug */, 329 | 2301E974205A51F300E0E358 /* Release */, 330 | ); 331 | defaultConfigurationIsVisible = 0; 332 | defaultConfigurationName = Release; 333 | }; 334 | 2301E975205A51F300E0E358 /* Build configuration list for PBXNativeTarget "APNSUtil" */ = { 335 | isa = XCConfigurationList; 336 | buildConfigurations = ( 337 | 2301E976205A51F300E0E358 /* Debug */, 338 | 2301E977205A51F300E0E358 /* Release */, 339 | ); 340 | defaultConfigurationIsVisible = 0; 341 | defaultConfigurationName = Release; 342 | }; 343 | /* End XCConfigurationList section */ 344 | }; 345 | rootObject = 2301E964205A51F300E0E358 /* Project object */; 346 | } 347 | -------------------------------------------------------------------------------- /APNSUtil.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /APNSUtil.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /APNSUtil.xcodeproj/xcshareddata/xcschemes/APNSUtil.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 52 | 53 | 59 | 60 | 66 | 67 | 68 | 69 | 71 | 72 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /APNSUtil/APNSUtil.h: -------------------------------------------------------------------------------- 1 | // 2 | // APNSUtil.h 3 | // APNSUtil 4 | // 5 | // Created by KWANG HYOUN KIM on 15/03/2018. 6 | // Copyright © 2018 pisces. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for APNSUtil. 12 | FOUNDATION_EXPORT double APNSUtilVersionNumber; 13 | 14 | //! Project version string for APNSUtil. 15 | FOUNDATION_EXPORT const unsigned char APNSUtilVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /APNSUtil/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pisces/APNSUtil/336050a6993adcac6c905766fcca28ec15f8824e/APNSUtil/Assets/.gitkeep -------------------------------------------------------------------------------- /APNSUtil/Classes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pisces/APNSUtil/336050a6993adcac6c905766fcca28ec15f8824e/APNSUtil/Classes/.gitkeep -------------------------------------------------------------------------------- /APNSUtil/Classes/APNSInstance.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MIT License 3 | // 4 | // Copyright (c) 2019 Steve Kim 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | // 24 | // APNSInstance.swift 25 | // APNSUtil 26 | // 27 | // Created by pisces on 12/01/2018. 28 | // Copyright © 2019 Steve Kim. All rights reserved. 29 | // 30 | 31 | import Foundation 32 | 33 | @objcMembers public class APNSInstance: NSObject { 34 | 35 | // MARK: - Private Constants 36 | 37 | private struct Const { 38 | static let keyForAPNSInstance = "APNSInstance.shared" 39 | } 40 | 41 | public static let shared = decodeInstance() 42 | 43 | // MARK: - Public Properties 44 | 45 | public private(set) var tokenString: String? 46 | public private(set) var token: Data? 47 | 48 | // MARK: - Constructors 49 | 50 | public override init() { 51 | super.init() 52 | } 53 | public required init?(coder aDecoder: NSCoder) { 54 | super.init() 55 | 56 | decodeProperties(with: aDecoder) 57 | } 58 | 59 | // MARK: - Public Methods 60 | 61 | public func clear() { 62 | token = nil 63 | tokenString = nil 64 | 65 | UserDefaults.standard.removeObject(forKey: Const.keyForAPNSInstance) 66 | UserDefaults.standard.synchronize() 67 | } 68 | public func setAPNSToken(_ token: Data) { 69 | self.token = token 70 | tokenString = token.reduce("", { $0 + String(format: "%02X", $1) }) 71 | 72 | UserDefaults.standard.set(NSKeyedArchiver.archivedData(withRootObject: self), forKey: Const.keyForAPNSInstance) 73 | UserDefaults.standard.synchronize() 74 | } 75 | 76 | // MARK: - Private Methods 77 | 78 | private class func decodeInstance() -> APNSInstance { 79 | guard let data = UserDefaults.standard.data(forKey: Const.keyForAPNSInstance), 80 | let instance = NSKeyedUnarchiver.unarchiveObject(with: data) as? APNSInstance else { 81 | return APNSInstance() 82 | } 83 | return instance 84 | } 85 | } 86 | 87 | extension APNSInstance: NSCoding { 88 | public func encode(with aCoder: NSCoder) { 89 | encodeProperties(with: aCoder) 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /APNSUtil/Classes/APNSManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MIT License 3 | // 4 | // Copyright (c) 2019 Steve Kim 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | // 24 | // APNSManager.swift 25 | // APNSUtil 26 | // 27 | // Created by pisces on 12/01/2018. 28 | // Copyright © 2019 Steve Kim. All rights reserved. 29 | // 30 | 31 | import UIKit 32 | import UserNotifications 33 | 34 | public class APNSManager { 35 | 36 | // MARK: - Public Constants 37 | 38 | public typealias SubscribeClosure = (RemoteNotificationElement) -> Void 39 | 40 | public static let shared = APNSManager() 41 | private let kAuthorizationStatusDetermined: String = "kAuthorizationStatusDetermined" 42 | 43 | // MARK: - Public Properties 44 | 45 | private(set) var isAuthorizationStatusDetermined: Bool { 46 | get { 47 | return UserDefaults.standard.bool(forKey: kAuthorizationStatusDetermined) 48 | } 49 | set { 50 | UserDefaults.standard.set(newValue, forKey: kAuthorizationStatusDetermined) 51 | UserDefaults.standard.synchronize() 52 | } 53 | } 54 | 55 | // MARK: - Private Properties 56 | 57 | private var isInitialized = false 58 | private var types: UIUserNotificationType = [.sound, .alert, .badge] 59 | private var subscribeClosureMap = [Int: SubscribeClosure]() 60 | private var elements = [RemoteNotificationElement]() 61 | 62 | // MARK: - Public Methods 63 | 64 | @discardableResult 65 | public func begin() -> Self { 66 | isInitialized = true 67 | dequeue() 68 | return self 69 | } 70 | public func register() -> Self { 71 | #if !APP_EXTENSIONS 72 | if #available(iOS 10.0, *) { 73 | let types = self.types 74 | let options: () -> UNAuthorizationOptions = { 75 | var rawValue: UInt = 0 76 | if types.rawValue & UIUserNotificationType.alert.rawValue == UIUserNotificationType.alert.rawValue { 77 | rawValue |= UNAuthorizationOptions.alert.rawValue 78 | } 79 | if types.rawValue & UIUserNotificationType.sound.rawValue == UIUserNotificationType.sound.rawValue { 80 | rawValue |= UNAuthorizationOptions.sound.rawValue 81 | } 82 | if types.rawValue & UIUserNotificationType.badge.rawValue == UIUserNotificationType.badge.rawValue { 83 | rawValue |= UNAuthorizationOptions.badge.rawValue 84 | } 85 | return UNAuthorizationOptions(rawValue: rawValue) 86 | } 87 | 88 | let center = UNUserNotificationCenter.current() 89 | center.delegate = UIApplication.shared.delegate as? UNUserNotificationCenterDelegate 90 | center.requestAuthorization(options: options()) { (granted, error) in 91 | guard error == nil else {return} 92 | 93 | DispatchQueue.main.async { 94 | UIApplication.shared.registerForRemoteNotifications() 95 | } 96 | } 97 | } else { 98 | UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: types, categories: nil)) 99 | } 100 | isAuthorizationStatusDetermined = true 101 | #endif 102 | return self 103 | } 104 | public func registerDeviceToken(_ deviceToken: Data) { 105 | APNSInstance.shared.setAPNSToken(deviceToken) 106 | } 107 | public func setTypes(_ types: UIUserNotificationType) -> Self { 108 | self.types = types 109 | return self 110 | } 111 | public func subscribe(_ target: T, _ closure: @escaping SubscribeClosure) -> Self { 112 | guard subscribeClosureMap[target.hashValue] == nil else {return self} 113 | subscribeClosureMap[target.hashValue] = closure 114 | return self 115 | } 116 | public func unregister() { 117 | subscribeClosureMap.removeAll() 118 | #if !APP_EXTENSIONS 119 | UIApplication.shared.unregisterForRemoteNotifications() 120 | #endif 121 | APNSInstance.shared.clear() 122 | elements.removeAll() 123 | isAuthorizationStatusDetermined = true 124 | } 125 | public func unsubscribe(_ target: T) { 126 | subscribeClosureMap.removeValue(forKey: target.hashValue) 127 | } 128 | 129 | // MARK: - Private Methods 130 | 131 | private func dequeue() { 132 | guard isInitialized, elements.count > 0 else {return} 133 | let element = elements.removeFirst() 134 | subscribeClosureMap.forEach { $0.value(element) } 135 | dequeue() 136 | } 137 | private func didReceive(userInfo: [AnyHashable : Any], isInactive: Bool) { 138 | enqueue(.init(isInactive: isInactive, userInfo: userInfo)).dequeue() 139 | } 140 | @discardableResult 141 | private func enqueue(_ element: RemoteNotificationElement) -> Self { 142 | elements.append(element) 143 | return self 144 | } 145 | } 146 | 147 | #if !APP_EXTENSIONS 148 | extension APNSManager { 149 | 150 | // MARK: - Public Methods (Launching) 151 | 152 | public func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) { 153 | guard #available(iOS 10.0, *) else { 154 | let remote = launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification] as? [AnyHashable: Any] 155 | let local = launchOptions?[UIApplication.LaunchOptionsKey.localNotification] as? [AnyHashable: Any] 156 | guard let userInfo = remote ?? local else {return} 157 | didReceive(userInfo: userInfo, isInactive: true) 158 | return 159 | } 160 | } 161 | 162 | // MARK: - Public Methods (Register device token) 163 | 164 | public func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { 165 | registerDeviceToken(deviceToken) 166 | } 167 | 168 | // MARK: - Public Methods (Push Notification for iOS 9) 169 | 170 | public func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) { 171 | guard #available(iOS 10.0, *) else { 172 | application.registerForRemoteNotifications() 173 | return 174 | } 175 | } 176 | public func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) { 177 | guard #available(iOS 10.0, *) else { 178 | didReceive(userInfo: userInfo, isInactive: application.applicationState == .inactive) 179 | return 180 | } 181 | } 182 | 183 | // MARK: - Public Methods (Local Notification) 184 | 185 | public func application(_ application: UIApplication, didReceive notification: UILocalNotification) { 186 | didReceive(userInfo: notification.userInfo ?? [:], isInactive: application.applicationState == .inactive) 187 | } 188 | 189 | // MARK: - Public Methods (Push Notification for iOS 9) 190 | 191 | @available(iOS 10.0, *) 192 | public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification) { 193 | didReceive(userInfo: notification.request.content.userInfo, isInactive: false) 194 | } 195 | @available(iOS 10.0, *) 196 | public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) { 197 | didReceive(userInfo: response.notification.request.content.userInfo, isInactive: true) 198 | } 199 | } 200 | #endif 201 | 202 | public struct RemoteNotificationElement { 203 | public let isInactive: Bool 204 | public let userInfo: [AnyHashable : Any] 205 | 206 | public init(isInactive: Bool, userInfo: [AnyHashable : Any]) { 207 | self.isInactive = isInactive 208 | self.userInfo = userInfo 209 | } 210 | 211 | public func payload() -> T? { 212 | do { 213 | let data = try JSONSerialization.data(withJSONObject: userInfo, options: .prettyPrinted) 214 | return try JSONDecoder().decode(T.self, from: data) 215 | } catch { 216 | return nil 217 | } 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /APNSUtil/Classes/NSObject+Codable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MIT License 3 | // 4 | // Copyright (c) 2019 Steve Kim 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | // 24 | // NSObject+Codable.swift 25 | // APNSUtil 26 | // 27 | // Created by pisces on 12/01/2018. 28 | // Copyright © 2019 Steve Kim. All rights reserved. 29 | // 30 | 31 | import Foundation 32 | 33 | extension NSObject { 34 | 35 | // MARK: - Public Properties 36 | 37 | public var mirrorChildList: [Mirror.Child] { 38 | return Mirror(reflecting: self).children.filter { $0.label != nil } 39 | } 40 | 41 | // MARK: - Public Methods 42 | 43 | public func decodeProperties(with corder: NSCoder, ignoreKeys: [String]? = nil) { 44 | let mirror = Mirror(reflecting: self) 45 | var current = mirror.superclassMirror 46 | 47 | while current != nil { 48 | decodeChildren(filteredChildren(current), corder: corder, ignoreKeys: ignoreKeys) 49 | current = current?.superclassMirror 50 | } 51 | 52 | decodeChildren(filteredChildren(mirror), corder: corder, ignoreKeys: ignoreKeys) 53 | } 54 | public func dictionary(ignoreKeys: [String]? = nil) -> [String: Any] { 55 | let mirror = Mirror(reflecting: self) 56 | var current = mirror.superclassMirror 57 | var dict = [String: Any]() 58 | 59 | while current != nil { 60 | setValue(with: filteredChildren(current), dict: &dict, ignoreKeys: ignoreKeys) 61 | current = current?.superclassMirror 62 | } 63 | 64 | setValue(with: filteredChildren(mirror), dict: &dict, ignoreKeys: ignoreKeys) 65 | 66 | return dict 67 | } 68 | public func encodeProperties(with corder: NSCoder, ignoreKeys: [String]? = nil) { 69 | let mirror = Mirror(reflecting: self) 70 | var current = mirror.superclassMirror 71 | 72 | while current != nil { 73 | encodeChildren(filteredChildren(current), corder: corder, ignoreKeys: ignoreKeys) 74 | current = current?.superclassMirror 75 | } 76 | 77 | encodeChildren(filteredChildren(mirror), corder: corder, ignoreKeys: ignoreKeys) 78 | } 79 | 80 | // MARK: - Private Methods 81 | 82 | private func decodeChildren(_ children: [Mirror.Child]?, corder: NSCoder, ignoreKeys: [String]? = nil) { 83 | children?.forEach { 84 | if let ignoreKeys = ignoreKeys, ignoreKeys.contains($0.label!) { 85 | return 86 | } 87 | if let value = corder.decodeObject(forKey: $0.label!), !(value is NSNull) { 88 | setValue(value, forKey: $0.label!) 89 | } 90 | } 91 | } 92 | private func encodeChildren(_ children: [Mirror.Child]?, corder: NSCoder, ignoreKeys: [String]? = nil) { 93 | children?.forEach { 94 | if let ignoreKeys = ignoreKeys, ignoreKeys.contains($0.label!) { 95 | return 96 | } 97 | if !($0.value is NSNull) { 98 | corder.encode($0.value, forKey: $0.label!) 99 | } 100 | } 101 | } 102 | private func filteredChildren(_ mirror: Mirror?) -> [Mirror.Child] { 103 | return mirror?.children.filter { $0.label != nil } ?? [] 104 | } 105 | private func setValue(with children: [Mirror.Child]?, dict: inout [String: Any], ignoreKeys: [String]? = nil) { 106 | children?.forEach { 107 | if let ignoreKeys = ignoreKeys, ignoreKeys.contains($0.label!) { 108 | return 109 | } 110 | dict[$0.label!] = value(forKey: $0.label!) 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /APNSUtil/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 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 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /APNSUtilAppExtension.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint APNSUtil.podspec' to ensure this is a 3 | # valid spec before submitting. 4 | # 5 | # Any lines starting with a # are optional, but their use is encouraged 6 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | s.name = 'APNSUtilAppExtension' 11 | s.version = '1.6.0' 12 | s.summary = 'APNSUtil is makes code simple using apple push notification service.' 13 | s.description = 'APNSUtil is makes code simple using apple push notification service.' 14 | s.homepage = 'https://github.com/pisces/APNSUtil' 15 | s.license = { :type => 'MIT', :file => 'LICENSE' } 16 | s.author = { 'pisces' => 'hh963103@gmail.com' } 17 | s.source = { :git => 'https://github.com/pisces/APNSUtil.git', :tag => s.version.to_s } 18 | s.ios.deployment_target = '9.0' 19 | s.source_files = 'APNSUtil/Classes/**/*' 20 | s.pod_target_xcconfig = { 'OTHER_SWIFT_FLAGS' => '-DAPP_EXTENSIONS' } 21 | end 22 | -------------------------------------------------------------------------------- /Example/APNSUtil.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 23DD8253205A12130002267E /* APNSPayload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23DD8252205A12130002267E /* APNSPayload.swift */; }; 11 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; }; 12 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* ViewController.swift */; }; 13 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; }; 14 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; 15 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; 16 | 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* Tests.swift */; }; 17 | 8D4EAEA7233869E2A81761A0 /* Pods_APNSUtil_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 410077C5AFCC70C96F50B471 /* Pods_APNSUtil_Tests.framework */; }; 18 | A9AA029B027D5EEB216B3610 /* Pods_APNSUtil_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DFAED169DBE8447D1E185E8 /* Pods_APNSUtil_Example.framework */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXContainerItemProxy section */ 22 | 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */ = { 23 | isa = PBXContainerItemProxy; 24 | containerPortal = 607FACC81AFB9204008FA782 /* Project object */; 25 | proxyType = 1; 26 | remoteGlobalIDString = 607FACCF1AFB9204008FA782; 27 | remoteInfo = APNSUtil; 28 | }; 29 | /* End PBXContainerItemProxy section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | 1163079A272593A5791C94AE /* APNSUtil.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = APNSUtil.podspec; path = ../APNSUtil.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 33 | 23DD8252205A12130002267E /* APNSPayload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APNSPayload.swift; sourceTree = ""; }; 34 | 396298E19FD6F33BA824CC9F /* Pods-APNSUtil_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-APNSUtil_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-APNSUtil_Example/Pods-APNSUtil_Example.release.xcconfig"; sourceTree = ""; }; 35 | 3DA2E07181A857E5BACD1642 /* Pods-APNSUtil_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-APNSUtil_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-APNSUtil_Tests/Pods-APNSUtil_Tests.release.xcconfig"; sourceTree = ""; }; 36 | 410077C5AFCC70C96F50B471 /* Pods_APNSUtil_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_APNSUtil_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 37 | 44A9161105E3A023502A94FF /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 38 | 4522AA1D0BA111F360A9A33E /* Pods-APNSUtil_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-APNSUtil_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-APNSUtil_Tests/Pods-APNSUtil_Tests.debug.xcconfig"; sourceTree = ""; }; 39 | 5DFAED169DBE8447D1E185E8 /* Pods_APNSUtil_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_APNSUtil_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 40 | 607FACD01AFB9204008FA782 /* APNSUtil_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = APNSUtil_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 42 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 43 | 607FACD71AFB9204008FA782 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 44 | 607FACDA1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 45 | 607FACDC1AFB9204008FA782 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 46 | 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 47 | 607FACE51AFB9204008FA782 /* APNSUtil_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = APNSUtil_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 49 | 607FACEB1AFB9204008FA782 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; 50 | A04261443121492C88E6696B /* Pods-APNSUtil_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-APNSUtil_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-APNSUtil_Example/Pods-APNSUtil_Example.debug.xcconfig"; sourceTree = ""; }; 51 | EA10B048D5DEE472DB42B4BA /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 52 | /* End PBXFileReference section */ 53 | 54 | /* Begin PBXFrameworksBuildPhase section */ 55 | 607FACCD1AFB9204008FA782 /* Frameworks */ = { 56 | isa = PBXFrameworksBuildPhase; 57 | buildActionMask = 2147483647; 58 | files = ( 59 | A9AA029B027D5EEB216B3610 /* Pods_APNSUtil_Example.framework in Frameworks */, 60 | ); 61 | runOnlyForDeploymentPostprocessing = 0; 62 | }; 63 | 607FACE21AFB9204008FA782 /* Frameworks */ = { 64 | isa = PBXFrameworksBuildPhase; 65 | buildActionMask = 2147483647; 66 | files = ( 67 | 8D4EAEA7233869E2A81761A0 /* Pods_APNSUtil_Tests.framework in Frameworks */, 68 | ); 69 | runOnlyForDeploymentPostprocessing = 0; 70 | }; 71 | /* End PBXFrameworksBuildPhase section */ 72 | 73 | /* Begin PBXGroup section */ 74 | 3CFBF6DDAC18DDF730C5BEC5 /* Pods */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | A04261443121492C88E6696B /* Pods-APNSUtil_Example.debug.xcconfig */, 78 | 396298E19FD6F33BA824CC9F /* Pods-APNSUtil_Example.release.xcconfig */, 79 | 4522AA1D0BA111F360A9A33E /* Pods-APNSUtil_Tests.debug.xcconfig */, 80 | 3DA2E07181A857E5BACD1642 /* Pods-APNSUtil_Tests.release.xcconfig */, 81 | ); 82 | name = Pods; 83 | sourceTree = ""; 84 | }; 85 | 607FACC71AFB9204008FA782 = { 86 | isa = PBXGroup; 87 | children = ( 88 | 607FACF51AFB993E008FA782 /* Podspec Metadata */, 89 | 607FACD21AFB9204008FA782 /* Example for APNSUtil */, 90 | 607FACE81AFB9204008FA782 /* Tests */, 91 | 607FACD11AFB9204008FA782 /* Products */, 92 | 3CFBF6DDAC18DDF730C5BEC5 /* Pods */, 93 | ABD4536A8D863EDFF78773C4 /* Frameworks */, 94 | ); 95 | sourceTree = ""; 96 | }; 97 | 607FACD11AFB9204008FA782 /* Products */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 607FACD01AFB9204008FA782 /* APNSUtil_Example.app */, 101 | 607FACE51AFB9204008FA782 /* APNSUtil_Tests.xctest */, 102 | ); 103 | name = Products; 104 | sourceTree = ""; 105 | }; 106 | 607FACD21AFB9204008FA782 /* Example for APNSUtil */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */, 110 | 607FACD71AFB9204008FA782 /* ViewController.swift */, 111 | 607FACD91AFB9204008FA782 /* Main.storyboard */, 112 | 607FACDC1AFB9204008FA782 /* Images.xcassets */, 113 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */, 114 | 607FACD31AFB9204008FA782 /* Supporting Files */, 115 | 23DD8252205A12130002267E /* APNSPayload.swift */, 116 | ); 117 | name = "Example for APNSUtil"; 118 | path = APNSUtil; 119 | sourceTree = ""; 120 | }; 121 | 607FACD31AFB9204008FA782 /* Supporting Files */ = { 122 | isa = PBXGroup; 123 | children = ( 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 | 1163079A272593A5791C94AE /* APNSUtil.podspec */, 150 | EA10B048D5DEE472DB42B4BA /* README.md */, 151 | 44A9161105E3A023502A94FF /* LICENSE */, 152 | ); 153 | name = "Podspec Metadata"; 154 | sourceTree = ""; 155 | }; 156 | ABD4536A8D863EDFF78773C4 /* Frameworks */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | 5DFAED169DBE8447D1E185E8 /* Pods_APNSUtil_Example.framework */, 160 | 410077C5AFCC70C96F50B471 /* Pods_APNSUtil_Tests.framework */, 161 | ); 162 | name = Frameworks; 163 | sourceTree = ""; 164 | }; 165 | /* End PBXGroup section */ 166 | 167 | /* Begin PBXNativeTarget section */ 168 | 607FACCF1AFB9204008FA782 /* APNSUtil_Example */ = { 169 | isa = PBXNativeTarget; 170 | buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "APNSUtil_Example" */; 171 | buildPhases = ( 172 | 2CC42F9299EAC49E41A71E53 /* [CP] Check Pods Manifest.lock */, 173 | 607FACCC1AFB9204008FA782 /* Sources */, 174 | 607FACCD1AFB9204008FA782 /* Frameworks */, 175 | 607FACCE1AFB9204008FA782 /* Resources */, 176 | A632D08F6B50CC23298A7478 /* [CP] Embed Pods Frameworks */, 177 | ); 178 | buildRules = ( 179 | ); 180 | dependencies = ( 181 | ); 182 | name = APNSUtil_Example; 183 | productName = APNSUtil; 184 | productReference = 607FACD01AFB9204008FA782 /* APNSUtil_Example.app */; 185 | productType = "com.apple.product-type.application"; 186 | }; 187 | 607FACE41AFB9204008FA782 /* APNSUtil_Tests */ = { 188 | isa = PBXNativeTarget; 189 | buildConfigurationList = 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "APNSUtil_Tests" */; 190 | buildPhases = ( 191 | BDAD0D8957304EFC768F6D68 /* [CP] Check Pods Manifest.lock */, 192 | 607FACE11AFB9204008FA782 /* Sources */, 193 | 607FACE21AFB9204008FA782 /* Frameworks */, 194 | 607FACE31AFB9204008FA782 /* Resources */, 195 | ); 196 | buildRules = ( 197 | ); 198 | dependencies = ( 199 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */, 200 | ); 201 | name = APNSUtil_Tests; 202 | productName = Tests; 203 | productReference = 607FACE51AFB9204008FA782 /* APNSUtil_Tests.xctest */; 204 | productType = "com.apple.product-type.bundle.unit-test"; 205 | }; 206 | /* End PBXNativeTarget section */ 207 | 208 | /* Begin PBXProject section */ 209 | 607FACC81AFB9204008FA782 /* Project object */ = { 210 | isa = PBXProject; 211 | attributes = { 212 | LastSwiftUpdateCheck = 0830; 213 | LastUpgradeCheck = 1010; 214 | ORGANIZATIONNAME = CocoaPods; 215 | TargetAttributes = { 216 | 607FACCF1AFB9204008FA782 = { 217 | CreatedOnToolsVersion = 6.3.1; 218 | LastSwiftMigration = 0900; 219 | }; 220 | 607FACE41AFB9204008FA782 = { 221 | CreatedOnToolsVersion = 6.3.1; 222 | LastSwiftMigration = 1120; 223 | TestTargetID = 607FACCF1AFB9204008FA782; 224 | }; 225 | }; 226 | }; 227 | buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "APNSUtil" */; 228 | compatibilityVersion = "Xcode 3.2"; 229 | developmentRegion = en; 230 | hasScannedForEncodings = 0; 231 | knownRegions = ( 232 | en, 233 | Base, 234 | ); 235 | mainGroup = 607FACC71AFB9204008FA782; 236 | productRefGroup = 607FACD11AFB9204008FA782 /* Products */; 237 | projectDirPath = ""; 238 | projectRoot = ""; 239 | targets = ( 240 | 607FACCF1AFB9204008FA782 /* APNSUtil_Example */, 241 | 607FACE41AFB9204008FA782 /* APNSUtil_Tests */, 242 | ); 243 | }; 244 | /* End PBXProject section */ 245 | 246 | /* Begin PBXResourcesBuildPhase section */ 247 | 607FACCE1AFB9204008FA782 /* Resources */ = { 248 | isa = PBXResourcesBuildPhase; 249 | buildActionMask = 2147483647; 250 | files = ( 251 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */, 252 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */, 253 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */, 254 | ); 255 | runOnlyForDeploymentPostprocessing = 0; 256 | }; 257 | 607FACE31AFB9204008FA782 /* Resources */ = { 258 | isa = PBXResourcesBuildPhase; 259 | buildActionMask = 2147483647; 260 | files = ( 261 | ); 262 | runOnlyForDeploymentPostprocessing = 0; 263 | }; 264 | /* End PBXResourcesBuildPhase section */ 265 | 266 | /* Begin PBXShellScriptBuildPhase section */ 267 | 2CC42F9299EAC49E41A71E53 /* [CP] Check Pods Manifest.lock */ = { 268 | isa = PBXShellScriptBuildPhase; 269 | buildActionMask = 2147483647; 270 | files = ( 271 | ); 272 | inputPaths = ( 273 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 274 | "${PODS_ROOT}/Manifest.lock", 275 | ); 276 | name = "[CP] Check Pods Manifest.lock"; 277 | outputPaths = ( 278 | "$(DERIVED_FILE_DIR)/Pods-APNSUtil_Example-checkManifestLockResult.txt", 279 | ); 280 | runOnlyForDeploymentPostprocessing = 0; 281 | shellPath = /bin/sh; 282 | 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"; 283 | showEnvVarsInLog = 0; 284 | }; 285 | A632D08F6B50CC23298A7478 /* [CP] Embed Pods Frameworks */ = { 286 | isa = PBXShellScriptBuildPhase; 287 | buildActionMask = 2147483647; 288 | files = ( 289 | ); 290 | inputPaths = ( 291 | "${PODS_ROOT}/Target Support Files/Pods-APNSUtil_Example/Pods-APNSUtil_Example-frameworks.sh", 292 | "${BUILT_PRODUCTS_DIR}/APNSUtil/APNSUtil.framework", 293 | ); 294 | name = "[CP] Embed Pods Frameworks"; 295 | outputPaths = ( 296 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/APNSUtil.framework", 297 | ); 298 | runOnlyForDeploymentPostprocessing = 0; 299 | shellPath = /bin/sh; 300 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-APNSUtil_Example/Pods-APNSUtil_Example-frameworks.sh\"\n"; 301 | showEnvVarsInLog = 0; 302 | }; 303 | BDAD0D8957304EFC768F6D68 /* [CP] Check Pods Manifest.lock */ = { 304 | isa = PBXShellScriptBuildPhase; 305 | buildActionMask = 2147483647; 306 | files = ( 307 | ); 308 | inputPaths = ( 309 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 310 | "${PODS_ROOT}/Manifest.lock", 311 | ); 312 | name = "[CP] Check Pods Manifest.lock"; 313 | outputPaths = ( 314 | "$(DERIVED_FILE_DIR)/Pods-APNSUtil_Tests-checkManifestLockResult.txt", 315 | ); 316 | runOnlyForDeploymentPostprocessing = 0; 317 | shellPath = /bin/sh; 318 | 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"; 319 | showEnvVarsInLog = 0; 320 | }; 321 | /* End PBXShellScriptBuildPhase section */ 322 | 323 | /* Begin PBXSourcesBuildPhase section */ 324 | 607FACCC1AFB9204008FA782 /* Sources */ = { 325 | isa = PBXSourcesBuildPhase; 326 | buildActionMask = 2147483647; 327 | files = ( 328 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */, 329 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, 330 | 23DD8253205A12130002267E /* APNSPayload.swift in Sources */, 331 | ); 332 | runOnlyForDeploymentPostprocessing = 0; 333 | }; 334 | 607FACE11AFB9204008FA782 /* Sources */ = { 335 | isa = PBXSourcesBuildPhase; 336 | buildActionMask = 2147483647; 337 | files = ( 338 | 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */, 339 | ); 340 | runOnlyForDeploymentPostprocessing = 0; 341 | }; 342 | /* End PBXSourcesBuildPhase section */ 343 | 344 | /* Begin PBXTargetDependency section */ 345 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */ = { 346 | isa = PBXTargetDependency; 347 | target = 607FACCF1AFB9204008FA782 /* APNSUtil_Example */; 348 | targetProxy = 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */; 349 | }; 350 | /* End PBXTargetDependency section */ 351 | 352 | /* Begin PBXVariantGroup section */ 353 | 607FACD91AFB9204008FA782 /* Main.storyboard */ = { 354 | isa = PBXVariantGroup; 355 | children = ( 356 | 607FACDA1AFB9204008FA782 /* Base */, 357 | ); 358 | name = Main.storyboard; 359 | sourceTree = ""; 360 | }; 361 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */ = { 362 | isa = PBXVariantGroup; 363 | children = ( 364 | 607FACDF1AFB9204008FA782 /* Base */, 365 | ); 366 | name = LaunchScreen.xib; 367 | sourceTree = ""; 368 | }; 369 | /* End PBXVariantGroup section */ 370 | 371 | /* Begin XCBuildConfiguration section */ 372 | 607FACED1AFB9204008FA782 /* Debug */ = { 373 | isa = XCBuildConfiguration; 374 | buildSettings = { 375 | ALWAYS_SEARCH_USER_PATHS = NO; 376 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 377 | CLANG_CXX_LIBRARY = "libc++"; 378 | CLANG_ENABLE_MODULES = YES; 379 | CLANG_ENABLE_OBJC_ARC = YES; 380 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 381 | CLANG_WARN_BOOL_CONVERSION = YES; 382 | CLANG_WARN_COMMA = YES; 383 | CLANG_WARN_CONSTANT_CONVERSION = YES; 384 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 385 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 386 | CLANG_WARN_EMPTY_BODY = YES; 387 | CLANG_WARN_ENUM_CONVERSION = YES; 388 | CLANG_WARN_INFINITE_RECURSION = YES; 389 | CLANG_WARN_INT_CONVERSION = YES; 390 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 391 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 392 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 393 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 394 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 395 | CLANG_WARN_STRICT_PROTOTYPES = YES; 396 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 397 | CLANG_WARN_UNREACHABLE_CODE = YES; 398 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 399 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 400 | COPY_PHASE_STRIP = NO; 401 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 402 | ENABLE_STRICT_OBJC_MSGSEND = YES; 403 | ENABLE_TESTABILITY = YES; 404 | GCC_C_LANGUAGE_STANDARD = gnu99; 405 | GCC_DYNAMIC_NO_PIC = NO; 406 | GCC_NO_COMMON_BLOCKS = YES; 407 | GCC_OPTIMIZATION_LEVEL = 0; 408 | GCC_PREPROCESSOR_DEFINITIONS = ( 409 | "DEBUG=1", 410 | "$(inherited)", 411 | ); 412 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 413 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 414 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 415 | GCC_WARN_UNDECLARED_SELECTOR = YES; 416 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 417 | GCC_WARN_UNUSED_FUNCTION = YES; 418 | GCC_WARN_UNUSED_VARIABLE = YES; 419 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 420 | MTL_ENABLE_DEBUG_INFO = YES; 421 | ONLY_ACTIVE_ARCH = YES; 422 | SDKROOT = iphoneos; 423 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 424 | SWIFT_VERSION = 5.0; 425 | }; 426 | name = Debug; 427 | }; 428 | 607FACEE1AFB9204008FA782 /* Release */ = { 429 | isa = XCBuildConfiguration; 430 | buildSettings = { 431 | ALWAYS_SEARCH_USER_PATHS = NO; 432 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 433 | CLANG_CXX_LIBRARY = "libc++"; 434 | CLANG_ENABLE_MODULES = YES; 435 | CLANG_ENABLE_OBJC_ARC = YES; 436 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 437 | CLANG_WARN_BOOL_CONVERSION = YES; 438 | CLANG_WARN_COMMA = YES; 439 | CLANG_WARN_CONSTANT_CONVERSION = YES; 440 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 441 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 442 | CLANG_WARN_EMPTY_BODY = YES; 443 | CLANG_WARN_ENUM_CONVERSION = YES; 444 | CLANG_WARN_INFINITE_RECURSION = YES; 445 | CLANG_WARN_INT_CONVERSION = YES; 446 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 447 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 448 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 449 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 450 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 451 | CLANG_WARN_STRICT_PROTOTYPES = YES; 452 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 453 | CLANG_WARN_UNREACHABLE_CODE = YES; 454 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 455 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 456 | COPY_PHASE_STRIP = NO; 457 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 458 | ENABLE_NS_ASSERTIONS = NO; 459 | ENABLE_STRICT_OBJC_MSGSEND = YES; 460 | GCC_C_LANGUAGE_STANDARD = gnu99; 461 | GCC_NO_COMMON_BLOCKS = YES; 462 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 463 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 464 | GCC_WARN_UNDECLARED_SELECTOR = YES; 465 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 466 | GCC_WARN_UNUSED_FUNCTION = YES; 467 | GCC_WARN_UNUSED_VARIABLE = YES; 468 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 469 | MTL_ENABLE_DEBUG_INFO = NO; 470 | SDKROOT = iphoneos; 471 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 472 | SWIFT_VERSION = 5.0; 473 | VALIDATE_PRODUCT = YES; 474 | }; 475 | name = Release; 476 | }; 477 | 607FACF01AFB9204008FA782 /* Debug */ = { 478 | isa = XCBuildConfiguration; 479 | baseConfigurationReference = A04261443121492C88E6696B /* Pods-APNSUtil_Example.debug.xcconfig */; 480 | buildSettings = { 481 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 482 | INFOPLIST_FILE = APNSUtil/Info.plist; 483 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 484 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 485 | MODULE_NAME = ExampleApp; 486 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; 487 | PRODUCT_NAME = "$(TARGET_NAME)"; 488 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 489 | SWIFT_VERSION = 5.0; 490 | TARGETED_DEVICE_FAMILY = "1,2"; 491 | }; 492 | name = Debug; 493 | }; 494 | 607FACF11AFB9204008FA782 /* Release */ = { 495 | isa = XCBuildConfiguration; 496 | baseConfigurationReference = 396298E19FD6F33BA824CC9F /* Pods-APNSUtil_Example.release.xcconfig */; 497 | buildSettings = { 498 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 499 | INFOPLIST_FILE = APNSUtil/Info.plist; 500 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 501 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 502 | MODULE_NAME = ExampleApp; 503 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; 504 | PRODUCT_NAME = "$(TARGET_NAME)"; 505 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 506 | SWIFT_VERSION = 5.0; 507 | TARGETED_DEVICE_FAMILY = "1,2"; 508 | }; 509 | name = Release; 510 | }; 511 | 607FACF31AFB9204008FA782 /* Debug */ = { 512 | isa = XCBuildConfiguration; 513 | baseConfigurationReference = 4522AA1D0BA111F360A9A33E /* Pods-APNSUtil_Tests.debug.xcconfig */; 514 | buildSettings = { 515 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 516 | GCC_PREPROCESSOR_DEFINITIONS = ( 517 | "DEBUG=1", 518 | "$(inherited)", 519 | ); 520 | INFOPLIST_FILE = Tests/Info.plist; 521 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 522 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; 523 | PRODUCT_NAME = "$(TARGET_NAME)"; 524 | SWIFT_VERSION = 5.0; 525 | }; 526 | name = Debug; 527 | }; 528 | 607FACF41AFB9204008FA782 /* Release */ = { 529 | isa = XCBuildConfiguration; 530 | baseConfigurationReference = 3DA2E07181A857E5BACD1642 /* Pods-APNSUtil_Tests.release.xcconfig */; 531 | buildSettings = { 532 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 533 | INFOPLIST_FILE = Tests/Info.plist; 534 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 535 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; 536 | PRODUCT_NAME = "$(TARGET_NAME)"; 537 | SWIFT_VERSION = 5.0; 538 | }; 539 | name = Release; 540 | }; 541 | /* End XCBuildConfiguration section */ 542 | 543 | /* Begin XCConfigurationList section */ 544 | 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "APNSUtil" */ = { 545 | isa = XCConfigurationList; 546 | buildConfigurations = ( 547 | 607FACED1AFB9204008FA782 /* Debug */, 548 | 607FACEE1AFB9204008FA782 /* Release */, 549 | ); 550 | defaultConfigurationIsVisible = 0; 551 | defaultConfigurationName = Release; 552 | }; 553 | 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "APNSUtil_Example" */ = { 554 | isa = XCConfigurationList; 555 | buildConfigurations = ( 556 | 607FACF01AFB9204008FA782 /* Debug */, 557 | 607FACF11AFB9204008FA782 /* Release */, 558 | ); 559 | defaultConfigurationIsVisible = 0; 560 | defaultConfigurationName = Release; 561 | }; 562 | 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "APNSUtil_Tests" */ = { 563 | isa = XCConfigurationList; 564 | buildConfigurations = ( 565 | 607FACF31AFB9204008FA782 /* Debug */, 566 | 607FACF41AFB9204008FA782 /* Release */, 567 | ); 568 | defaultConfigurationIsVisible = 0; 569 | defaultConfigurationName = Release; 570 | }; 571 | /* End XCConfigurationList section */ 572 | }; 573 | rootObject = 607FACC81AFB9204008FA782 /* Project object */; 574 | } 575 | -------------------------------------------------------------------------------- /Example/APNSUtil.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/APNSUtil.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/APNSUtil.xcodeproj/xcshareddata/xcschemes/APNSUtil-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/APNSUtil.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/APNSUtil.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/APNSUtil/APNSPayload.swift: -------------------------------------------------------------------------------- 1 | // 2 | // APNSPayload.swift 3 | // APNSUtil 4 | // 5 | // Created by pisces on 03/15/2018. 6 | // Copyright (c) 2018 pisces. All rights reserved. 7 | // 8 | 9 | import APNSUtil 10 | 11 | struct APNSPayload: Decodable { 12 | let aps: APS? 13 | 14 | struct APS: Decodable { 15 | let sound: String? 16 | let alert: Alert? 17 | } 18 | 19 | struct Alert: Decodable { 20 | let body: String? 21 | let title: String? 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Example/APNSUtil/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // APNSUtil 4 | // 5 | // Created by pisces on 03/15/2018. 6 | // Copyright (c) 2018 pisces. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import UserNotifications 11 | import APNSUtil 12 | 13 | @UIApplicationMain 14 | class AppDelegate: UIResponder, UIApplicationDelegate { 15 | 16 | var window: UIWindow? 17 | 18 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 19 | APNSManager.shared.application(application, didFinishLaunchingWithOptions: launchOptions) 20 | return true 21 | } 22 | 23 | // MARK: - Push Notification 24 | 25 | func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { 26 | APNSManager.shared.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken) 27 | // <>(APNSInstance.shared.tokenString) 28 | } 29 | func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { 30 | } 31 | 32 | // MARK: - Push Notification for iOS 9 33 | 34 | func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) { 35 | APNSManager.shared.application(application, didRegister: notificationSettings) 36 | } 37 | func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) { 38 | APNSManager.shared.application(application, didReceiveRemoteNotification: userInfo) 39 | } 40 | 41 | // MARK: - Public Methods (UIApplicationDelegate - Local Notification) 42 | 43 | func application(_ application: UIApplication, didReceive notification: UILocalNotification) { 44 | APNSManager.shared.application(application, didReceive: notification) 45 | } 46 | } 47 | 48 | extension AppDelegate: UNUserNotificationCenterDelegate { 49 | @available(iOS 10.0, *) 50 | func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { 51 | APNSManager.shared.userNotificationCenter(center, willPresent: notification) 52 | } 53 | @available(iOS 10.0, *) 54 | func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { 55 | APNSManager.shared.userNotificationCenter(center, didReceive: response) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Example/APNSUtil/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Example/APNSUtil/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 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Example/APNSUtil/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "size" : "1024x1024", 46 | "scale" : "1x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Example/APNSUtil/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 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Example/APNSUtil/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // APNSUtil 4 | // 5 | // Created by pisces on 03/15/2018. 6 | // Copyright (c) 2018 pisces. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import APNSUtil 11 | 12 | class ViewController: UIViewController { 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | APNSManager.shared 17 | .setTypes([.sound, .alert, .badge]) // setting user notification types 18 | .register() // registering to use apns 19 | .subscribe(self) { // subscribe receiving apns payload 20 | // your custom payload with generic 21 | guard let payload: APNSPayload = $0.payload() else { 22 | return 23 | } 24 | 25 | print("subscribe", $0.isInactive, $0.userInfo, payload) 26 | 27 | if $0.isInactive { 28 | // TODO: write code to present viewController on inactive 29 | } else { 30 | // TODO: write code to show toast message on active 31 | } 32 | }.begin() // begin receiving apns payload 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | 3 | target 'APNSUtil_Example' do 4 | pod 'APNSUtil', :path => '../' 5 | 6 | target 'APNSUtil_Tests' do 7 | inherit! :search_paths 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - APNSUtil (1.5.0) 3 | 4 | DEPENDENCIES: 5 | - APNSUtil (from `../`) 6 | 7 | EXTERNAL SOURCES: 8 | APNSUtil: 9 | :path: "../" 10 | 11 | SPEC CHECKSUMS: 12 | APNSUtil: ef85e8835b13c492127e25cd9c57c0fb59651169 13 | 14 | PODFILE CHECKSUM: 682a114a47371b5a83ba6292e00758c19f6a5987 15 | 16 | COCOAPODS: 1.7.5 17 | -------------------------------------------------------------------------------- /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 XCTest 2 | import APNSUtil 3 | 4 | class Tests: XCTestCase { 5 | 6 | override func setUp() { 7 | super.setUp() 8 | // Put setup code here. This method is called before the invocation of each test method in the class. 9 | } 10 | 11 | override func tearDown() { 12 | // Put teardown code here. This method is called after the invocation of each test method in the class. 13 | super.tearDown() 14 | } 15 | 16 | func testExample() { 17 | // This is an example of a functional test case. 18 | XCTAssert(true, "Pass") 19 | } 20 | 21 | func testPerformanceExample() { 22 | // This is an example of a performance test case. 23 | self.measure() { 24 | // Put the code you want to measure the time of here. 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Steve Kim 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # APNSUtil 2 | 3 | ![Swift](https://img.shields.io/badge/Swift-5-orange.svg) 4 | [![CI Status](http://img.shields.io/travis/pisces/APNSUtil.svg?style=flat)](https://travis-ci.org/pisces/APNSUtil) 5 | [![Version](https://img.shields.io/cocoapods/v/APNSUtil.svg?style=flat)](http://cocoapods.org/pods/APNSUtil) 6 | [![License](https://img.shields.io/cocoapods/l/APNSUtil.svg?style=flat)](http://cocoapods.org/pods/APNSUtil) 7 | [![Platform](https://img.shields.io/cocoapods/p/APNSUtil.svg?style=flat)](http://cocoapods.org/pods/APNSUtil) 8 | [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 9 | 10 | - APNSUtil makes code simple settings and landing for apple push notification service. 11 | 12 | ## Features 13 | - Using apple push notification service simply 14 | - No need write codes for any iOS versions 15 | - Support chained functional programing 16 | 17 | ## Import 18 | 19 | ```swift 20 | import APNSUtil 21 | ``` 22 | 23 | ## Using 24 | 25 | ### Implementation for main view controller 26 | ```swift 27 | import UIKit 28 | import APNSUtil 29 | 30 | class ViewController: UIViewController { 31 | override func viewDidLoad() { 32 | super.viewDidLoad() 33 | 34 | APNSManager.shared 35 | .setTypes([.sound, .alert, .badge]) // setting user notification types 36 | .register() // register to use apns 37 | .subscribe(self) { // subscribe to receive apns payload 38 | // your payload model with generic 39 | guard let payload: APNSPayload = $0.payload() else { 40 | return 41 | } 42 | 43 | print("subscribe", $0.isInactive, $0.userInfo, payload) 44 | 45 | if $0.isInactive { 46 | // TODO: write code to present viewController on inactive 47 | } else { 48 | // TODO: write code to show toast message on active 49 | } 50 | }.begin() // begin to receive apns payload 51 | } 52 | } 53 | ``` 54 | 55 | ### Implementation for app delegate 56 | 57 | ```swift 58 | import UIKit 59 | import UserNotifications 60 | import APNSUtil 61 | 62 | @UIApplicationMain 63 | class AppDelegate: UIResponder, UIApplicationDelegate { 64 | 65 | var window: UIWindow? 66 | 67 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 68 | APNSManager.shared.application(application, didFinishLaunchingWithOptions: launchOptions) 69 | return true 70 | } 71 | 72 | // MARK: - Push Notification 73 | 74 | func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { 75 | APNSManager.shared.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken) 76 | // <>(APNSInstance.shared.tokenString) 77 | } 78 | func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { 79 | } 80 | 81 | // MARK: - Push Notification for iOS 9 82 | 83 | func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) { 84 | APNSManager.shared.application(application, didRegister: notificationSettings) 85 | } 86 | func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) { 87 | APNSManager.shared.application(application, didReceiveRemoteNotification: userInfo) 88 | } 89 | 90 | // MARK: - Public Methods (UIApplicationDelegate - Local Notification) 91 | 92 | func application(_ application: UIApplication, didReceive notification: UILocalNotification) { 93 | APNSManager.shared.application(application, didReceive: notification) 94 | } 95 | } 96 | 97 | extension AppDelegate: UNUserNotificationCenterDelegate { 98 | @available(iOS 10.0, *) 99 | func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { 100 | APNSManager.shared.userNotificationCenter(center, willPresent: notification) 101 | } 102 | @available(iOS 10.0, *) 103 | func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { 104 | APNSManager.shared.userNotificationCenter(center, didReceive: response) 105 | } 106 | } 107 | ``` 108 | 109 | ### Implement your payload model 110 | ```swift 111 | struct APNSPayload: Decodable { 112 | let aps: APS? 113 | 114 | // Add properties here you need 115 | 116 | struct APS: Decodable { 117 | let sound: String? 118 | let alert: Alert? 119 | } 120 | 121 | struct Alert: Decodable { 122 | let body: String? 123 | let title: String? 124 | } 125 | } 126 | ``` 127 | 128 | ### Using with your payload model as generic 129 | 130 | ```swift 131 | APNSManager.shared 132 | .setTypes([.sound, .alert, .badge]) 133 | .register() 134 | .subscribe(self) { 135 | guard let payload: APNSPayload = $0.payload() else { 136 | return 137 | } 138 | 139 | // write here to process payload model 140 | }.begin() 141 | ``` 142 | 143 | ### Using with raw userInfo 144 | 145 | ```swift 146 | APNSManager.shared 147 | .setTypes([.sound, .alert, .badge]) 148 | .register() 149 | .subscribe(self) { 150 | let userInfo = $0.userInfo 151 | 152 | // write here to process userInfo 153 | }.begin() 154 | ``` 155 | 156 | ## Installation 157 | 158 | ### CocoaPods 159 | 160 | [CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command: 161 | 162 | ```bash 163 | $ gem install cocoapods 164 | ``` 165 | 166 | > CocoaPods 1.0.0+ is required to build APNSUtil 1.1.5+. 167 | 168 | To integrate APNSUtil into your Xcode project using CocoaPods, specify it in your `Podfile`: 169 | 170 | ```ruby 171 | source 'https://github.com/CocoaPods/Specs.git' 172 | platform :ios, '9.0' 173 | 174 | # Default 175 | target '' do 176 | pod 'APNSUtil', '~> 1.6.0' 177 | end 178 | 179 | # for AppExtension 180 | target '' do 181 | pod 'APNSUtil/AppExtension', '~> 1.6.0' 182 | end 183 | ``` 184 | 185 | Then, run the following command: 186 | 187 | ```bash 188 | $ pod install 189 | ``` 190 | 191 | ### Carthage 192 | 193 | [Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. 194 | 195 | You can install Carthage with [Homebrew](http://brew.sh/) using the following command: 196 | 197 | ```bash 198 | $ brew update 199 | $ brew install carthage 200 | ``` 201 | 202 | To integrate Alamofire into your Xcode project using Carthage, specify it in your `Cartfile`: 203 | 204 | ```ogdl 205 | github "pisces/APNSUtil" ~> 1.6.0 206 | ``` 207 | 208 | Run `carthage update` to build the framework and drag the built `APNSUtil.framework` into your Xcode project. 209 | 210 | ## Requirements 211 | 212 | iOS Deployment Target 9.0 higher 213 | 214 | ## Author 215 | 216 | Steve Kim, hh963103@gmail.com 217 | 218 | ## License 219 | 220 | APNSUtil is available under the MIT license. See the LICENSE file for more info. 221 | -------------------------------------------------------------------------------- /_Pods.xcodeproj: -------------------------------------------------------------------------------- 1 | Example/Pods/Pods.xcodeproj --------------------------------------------------------------------------------