├── ZeroPush-iOS Tests ├── en.lproj │ └── InfoPlist.strings ├── ZeroPush-iOS Tests-Prefix.pch ├── ZeroPush-iOS Tests-Info.plist └── ZeroPushSpec.m ├── zeropush-docs-header.png ├── .gitignore ├── Podfile ├── .travis.yml ├── ZeroPush-iOS ├── ZeroPush-iOS-Prefix.pch ├── ZeroPush.h └── ZeroPush.m ├── Podfile.lock ├── CHANGES.md ├── ZeroPush.podspec ├── LICENSE ├── ZeroPush-iOS.xcodeproj ├── xcshareddata │ └── xcschemes │ │ ├── ZeroPush-iOS.xcscheme │ │ └── ZeroPush-iOS Tests.xcscheme └── project.pbxproj └── README.md /ZeroPush-iOS Tests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /zeropush-docs-header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZeroPush/ZeroPush-iOS/HEAD/zeropush-docs-header.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ZeroPush-iOS.xcworkspace/ 2 | ZeroPush-iOS.xcodeproj/project.xcworkspace/ 3 | ZeroPush-iOS.xcodeproj/xcuserdata/ 4 | Pods/ 5 | Build/ 6 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | platform :ios, '7.0' 3 | 4 | podspec 5 | 6 | target 'ZeroPush-iOS Tests' do 7 | pod 'Kiwi' 8 | pod 'Nocilla' 9 | end 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | script: xcodebuild -workspace ZeroPush-iOS.xcworkspace -scheme 'ZeroPush-iOS Tests' -destination 'platform=iOS Simulator,name=iPhone 6,OS=latest' clean build test 3 | -------------------------------------------------------------------------------- /ZeroPush-iOS/ZeroPush-iOS-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'ZeroPush-iOS-SDK' target in the 'ZeroPush-iOS-SDK' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Kiwi (2.3.1) 3 | - Nocilla (0.9.0) 4 | 5 | DEPENDENCIES: 6 | - Kiwi 7 | - Nocilla 8 | 9 | SPEC CHECKSUMS: 10 | Kiwi: f038a6c61f7a9e4d7766bff5717aa3b3fdb75f55 11 | Nocilla: d7d96e8a11e363f0d7c976d48b320c43d61fb471 12 | 13 | COCOAPODS: 0.36.3 14 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | ## 2015-04-10 ZeroPush-iOS 2.1.0 2 | 3 | Add `unregisterDeviceToken` - a way to unregister a device token - @jessearmand 4 | 5 | ## 2015-03-17 ZeroPush-iOS 2.0.5 6 | 7 | Move auth_token out of `request.HTTPBody` and into the Authorization header. This fixes problems in the `getChannels` method. 8 | -------------------------------------------------------------------------------- /ZeroPush-iOS Tests/ZeroPush-iOS Tests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #import 10 | #endif 11 | -------------------------------------------------------------------------------- /ZeroPush.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "ZeroPush" 3 | s.version = "2.1.2" 4 | s.summary = "ZeroPush is a lightweight wrapper for the ZeroPush API." 5 | s.homepage = "https://zeropush.com" 6 | s.license = 'MIT' 7 | s.authors = { "Adam Duke" => "adam.v.duke@gmail.com", "Stefan Natchev" => "stefan.natchev@gmail.com" } 8 | s.source = { :git => "https://github.com/ZeroPush/ZeroPush-iOS.git", :tag => "2.1.2" } 9 | s.platform = :ios, '6.0' 10 | s.source_files = 'ZeroPush-iOS/*.{h,m}' 11 | s.frameworks = 'Foundation', 'UIKit' 12 | s.requires_arc = true 13 | end 14 | 15 | -------------------------------------------------------------------------------- /ZeroPush-iOS Tests/ZeroPush-iOS Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | zeropush.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Symmetric Infinity LLC 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | -------------------------------------------------------------------------------- /ZeroPush-iOS.xcodeproj/xcshareddata/xcschemes/ZeroPush-iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /ZeroPush-iOS/ZeroPush.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZeroPush.h 3 | // ZeroPush-iOS 4 | // 5 | // Created by Stefan Natchev on 2/5/13. 6 | // Copyright (c) 2015 SymmetricInfinity. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @protocol ZeroPushDelegate 13 | @optional 14 | 15 | - (void)tokenRegistrationDidFailWithError:(NSError *)error; 16 | - (void)tokenUnregistrationDidFailWithError:(NSError *)error; 17 | - (void)subscribeDidFailWithError:(NSError *)error; 18 | - (void)unsubscribeDidFailWithError:(NSError *)error; 19 | - (void)setBadgeDidFailWithError:(NSError *)error; 20 | 21 | @end 22 | 23 | @interface ZeroPush : NSObject 24 | 25 | @property (nonatomic, copy) NSString *apiKey; 26 | @property (nonatomic, strong)NSString *deviceToken; 27 | 28 | @property (nonatomic, weak) id delegate; 29 | 30 | /** 31 | * Get the shared ZeroPush instance 32 | */ 33 | + (ZeroPush *)shared; 34 | 35 | /** 36 | * Set the shared ZeroPush instance's apiKey 37 | */ 38 | + (void)engageWithAPIKey:(NSString *)apiKey; 39 | 40 | /** 41 | * Set the shared ZeroPush instance's apiKey and specify a ZeroPushDelegate 42 | */ 43 | + (void)engageWithAPIKey:(NSString *)apiKey delegate:(id)delegate; 44 | 45 | /** 46 | * Parse a device token given the raw data returned by Apple from registering for notifications 47 | */ 48 | + (NSString *)deviceTokenFromData:(NSData *)tokenData; 49 | 50 | /** 51 | * A convenience wrapper for [[UIApplication sharedApplication] registerForRemoteNotificationTypes:types]; 52 | * deprecated in iOS7 53 | */ 54 | - (void)registerForRemoteNotificationTypes:(UIRemoteNotificationType)types NS_DEPRECATED_IOS(3_0, 8_0, "Please use registerForRemoteNotifications instead"); 55 | 56 | /** 57 | * Preferred method for registering for notifications. Backwards compatible with iOS7 58 | */ 59 | - (void)registerForRemoteNotifications; 60 | 61 | /** 62 | * Register the device's token with ZeroPush 63 | */ 64 | - (void)registerDeviceToken:(NSData *)deviceToken; 65 | 66 | /** 67 | * Register the device's token with ZeroPush and subscribe the device's token to a broadcast channel 68 | */ 69 | - (void)registerDeviceToken:(NSData *)deviceToken channel:(NSString *)channel; 70 | 71 | /** 72 | * Unregister the previously registered device token from ZeroPush 73 | */ 74 | - (void)unregisterDeviceToken; 75 | 76 | /** 77 | * Subscribe the device's token to a broadcast channel 78 | */ 79 | - (void)subscribeToChannel:(NSString *)channel; 80 | 81 | /** 82 | * Unsubscribe the device's token from a broadcast channel 83 | */ 84 | - (void)unsubscribeFromChannel:(NSString *)channel; 85 | 86 | - (void)unsubscribeFromAllChannels; 87 | 88 | 89 | - (void)getDevice:(void (^)(NSDictionary *device, NSError *error)) callback; 90 | 91 | /** 92 | * return a list of all the channels to which the device is subscribed 93 | */ 94 | - (void)getChannels:(void (^)(NSArray *channels, NSError *error)) callback; 95 | /** 96 | * set a list of the channels to which a device is subscribed 97 | */ 98 | - (void)setChannels:(NSArray*)channels; 99 | 100 | /** 101 | * Set the device's badge number to the given value 102 | */ 103 | - (void)setBadge:(NSInteger)badge; 104 | 105 | /** 106 | * Set the device's badge number to zero 107 | */ 108 | - (void)resetBadge; 109 | 110 | @end 111 | -------------------------------------------------------------------------------- /ZeroPush-iOS.xcodeproj/xcshareddata/xcschemes/ZeroPush-iOS Tests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![ZeroPush](https://raw.github.com/ZeroPush/ZeroPush-iOS/master/zeropush-docs-header.png)](https://zeropush.com) 2 | [![ZeroPush Cocoapod](https://img.shields.io/cocoapods/v/ZeroPush.svg)](http://cocoapods.org/?q=zeropush) 3 | [![ZeroPush Travis](https://img.shields.io/travis/ZeroPush/ZeroPush-iOS.svg)](https://travis-ci.org/ZeroPush/ZeroPush-iOS) 4 | 5 | Purpose: 6 | --- 7 | 8 | ZeroPush-iOS is a lightweight Obj-C wrapper around the [ZeroPush](http://zeropush.com) API. 9 | It provides some convenience methods to help you get up an running with ZeroPush as quickly as possible. 10 | 11 | Building/Linking/Adding to your project: 12 | --- 13 | 14 | We recommend using the [ZeroPush Cocoapod](http://cocoapods.org/?q=zeropush). 15 | 16 | In your `Podfile` add the following line: 17 | 18 | ```ruby 19 | pod 'ZeroPush', '~> 2.0' 20 | ``` 21 | 22 | and install the Pods 23 | ```bash 24 | $> pod install 25 | ``` 26 | 27 | Configuration: 28 | --- 29 | 30 | After the client library has been installed, add the following to your `AppDelegate`. 31 | 32 | ```objc 33 | //In AppDelegate.h - Add the ZeroPushDelegate 34 | 35 | #import "ZeroPush.h" 36 | @interface AppDelegate : UIResponder 37 | 38 | 39 | // In AppDelegate.m 40 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 41 | { 42 | 43 | #if DEBUG 44 | [ZeroPush engageWithAPIKey:@"iosdev_apptoken" delegate:self]; 45 | #else 46 | [ZeroPush engageWithAPIKey:@"iosprod_apptoken" delegate:self]; 47 | #endif 48 | 49 | //now ask the user if they want to recieve push notifications. You can place this in another part of your app. 50 | [[ZeroPush shared] registerForRemoteNotifications]; 51 | 52 | return true; 53 | } 54 | 55 | - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)tokenData 56 | { 57 | // Call the convenience method registerDeviceToken, this helps us track device tokens for you 58 | [[ZeroPush shared] registerDeviceToken:tokenData]; 59 | 60 | // This would be a good time to save the token and associate it with a user that you want to notify later. 61 | NSString *tokenString = [ZeroPush deviceTokenFromData:tokenData]; 62 | NSLog(@"%@", tokenString); 63 | 64 | // For instance you can associate it with a user's email address 65 | // [[ZeroPush shared] subscribeToChannel:@"user@example.com"]; 66 | // You can then use the /broadcast endpoint to notify all devices subscribed to that email address. No need to save tokens! 67 | // Don't forget to unsubscribe from the channel when the user logs out of your app! 68 | } 69 | 70 | - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error 71 | { 72 | NSLog(@"%@", [error description]); 73 | //Common reason for errors: 74 | // 1.) Simulator does not support receiving push notifications 75 | // 2.) User rejected push alert 76 | // 3.) "no valid 'aps-environment' entitlement string found for application" 77 | // This means your provisioning profile does not have Push Notifications configured. https://zeropush.com/documentation/generating_certificates 78 | } 79 | 80 | ``` 81 | 82 | Upgrading from iOS7 83 | --- 84 | 85 | If you were using the helper method `[[ZeroPush shared] registerForRemoteNotificationTypes:]` in iOS7, you will need to change it when deploying to iOS8 86 | 87 | Before: 88 | ``` 89 | [[ZeroPush shared] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]; 90 | ``` 91 | 92 | After: 93 | ``` 94 | [[ZeroPush shared] registerForRemoteNotifications]; 95 | ``` 96 | 97 | Documentation: 98 | --- 99 | 100 | For more detailed documentation, refer to the [ZeroPush Docs](https://zeropush.com/documentation). 101 | 102 | License: 103 | --- 104 | 105 | Copyright (c) 2015 Symmetric Infinity LLC 106 | 107 | MIT License 108 | 109 | Permission is hereby granted, free of charge, to any person obtaining 110 | a copy of this software and associated documentation files (the 111 | "Software"), to deal in the Software without restriction, including 112 | without limitation the rights to use, copy, modify, merge, publish, 113 | distribute, sublicense, and/or sell copies of the Software, and to 114 | permit persons to whom the Software is furnished to do so, subject to 115 | the following conditions: 116 | 117 | The above copyright notice and this permission notice shall be 118 | included in all copies or substantial portions of the Software. 119 | 120 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 121 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 122 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 123 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 124 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 125 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 126 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 127 | 128 | -------------------------------------------------------------------------------- /ZeroPush-iOS/ZeroPush.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZeroPush.m 3 | // ZeroPush-iOS 4 | // 5 | // Created by Stefan Natchev on 2/5/13. 6 | // Copyright (c) 2015 SymmetricInfinity. All rights reserved. 7 | // 8 | 9 | #import "ZeroPush.h" 10 | 11 | static NSString *const ZeroPushAPIURLHost = @"https://api.zeropush.com"; 12 | static NSString *const ZeroPushClientVersion = @"ZeroPush-iOS/2.1.2"; 13 | 14 | @interface ZeroPush () 15 | 16 | @property (nonatomic, strong)NSHTTPURLResponse *lastResponse; 17 | @property (nonatomic, strong)NSOperationQueue *operationQueue; 18 | 19 | - (void)HTTPRequest:(NSString *) verb url:(NSString *)url params:(NSDictionary *)params completionHandler:(void (^)(NSHTTPURLResponse* response, NSData* data, NSError* connectionError)) handler; 20 | - (void)HTTPRequest:(NSString *) verb url:(NSString *)url completionHandler:(void (^)(NSHTTPURLResponse* response, NSData* data, NSError* connectionError)) handler; 21 | - (void)HTTPRequest:(NSString *) verb url:(NSString *)url params:(NSDictionary *)params errorSelector:(SEL)errorSelector; 22 | @end 23 | 24 | @implementation ZeroPush 25 | 26 | @synthesize apiKey = _apiKey; 27 | @synthesize delegate = _delegate; 28 | @synthesize deviceToken = _deviceToken; 29 | @synthesize lastResponse = _lastResponse; 30 | @synthesize operationQueue = _operationQueue; 31 | 32 | + (ZeroPush *)shared 33 | { 34 | static dispatch_once_t once; 35 | static id sharedInstance; 36 | dispatch_once(&once, ^{ 37 | sharedInstance = [[self alloc] init]; 38 | }); 39 | return sharedInstance; 40 | } 41 | 42 | + (void)engageWithAPIKey:(NSString *)apiKey 43 | { 44 | [self engageWithAPIKey:apiKey delegate:nil]; 45 | } 46 | 47 | + (void)engageWithAPIKey:(NSString *)apiKey delegate:(id)delegate 48 | { 49 | ZeroPush *sharedInstance = [ZeroPush shared]; 50 | sharedInstance.apiKey = apiKey; 51 | sharedInstance.delegate = delegate; 52 | } 53 | 54 | + (NSString *)deviceTokenFromData:(NSData *)tokenData 55 | { 56 | if (tokenData == nil) { 57 | return nil; 58 | } 59 | 60 | // our token should not be very big. This is a reasonable upper limit. 61 | if (tokenData.length >= 1024) { 62 | return nil; 63 | } 64 | 65 | NSMutableString *deviceToken = [NSMutableString stringWithCapacity:([tokenData length] * 2)]; 66 | const unsigned char *bytes = (const unsigned char *)[tokenData bytes]; 67 | 68 | for (NSUInteger i = 0; i < [tokenData length]; i++) { 69 | [deviceToken appendFormat:@"%02x", bytes[i]]; 70 | } 71 | 72 | return [NSString stringWithString:deviceToken]; 73 | } 74 | 75 | -(id)init { 76 | self = [super init]; 77 | if (self) { 78 | _operationQueue = [[NSOperationQueue alloc] init]; 79 | } 80 | 81 | return self; 82 | } 83 | 84 | - (void)registerForRemoteNotificationTypes:(UIRemoteNotificationType)types; 85 | { 86 | [[UIApplication sharedApplication] registerForRemoteNotificationTypes:types]; 87 | } 88 | 89 | - (void)registerForRemoteNotifications 90 | { 91 | #ifdef __IPHONE_8_0 92 | if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) { 93 | UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound) categories:nil]; 94 | [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings]; 95 | [[UIApplication sharedApplication] registerForRemoteNotifications]; 96 | } else { 97 | [[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]; 98 | } 99 | #else 100 | [[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]; 101 | #endif 102 | } 103 | 104 | - (NSDictionary *)userInfoForData:(id)data andResponse:(NSHTTPURLResponse *)response 105 | { 106 | NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; 107 | if (data) { 108 | id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 109 | json = json == nil ? [NSNull null] : json; 110 | [userInfo setObject:json forKey:@"response_data"]; 111 | } 112 | if (response) { 113 | [userInfo setObject:response forKey:@"response"]; 114 | } 115 | // make sure not to return a mutable dictionary 116 | return [NSDictionary dictionaryWithDictionary:userInfo]; 117 | } 118 | 119 | - (void)registerDeviceToken:(NSData *)deviceToken 120 | { 121 | [self registerDeviceToken:deviceToken channel:nil]; 122 | } 123 | 124 | - (void)registerDeviceToken:(NSData *)deviceToken channel:(NSString *)channel 125 | { 126 | self.deviceToken = [ZeroPush deviceTokenFromData:deviceToken]; 127 | 128 | NSMutableDictionary *params = [NSMutableDictionary dictionary]; 129 | [params setObject:self.deviceToken forKey:@"device_token"]; 130 | 131 | if (channel) { 132 | [params setObject:channel forKey:@"channel"]; 133 | } 134 | 135 | NSString *url = [NSString stringWithFormat:@"%@/register", ZeroPushAPIURLHost]; 136 | 137 | [self HTTPRequest:@"POST" 138 | url:url 139 | params:params 140 | errorSelector:@selector(tokenRegistrationDidFailWithError:)]; 141 | } 142 | 143 | 144 | - (void)unregisterDeviceToken 145 | { 146 | if ([self.deviceToken length] == 0) { 147 | return; 148 | } 149 | 150 | NSMutableDictionary *params = [NSMutableDictionary dictionary]; 151 | [params setObject:self.deviceToken forKey:@"device_token"]; 152 | 153 | 154 | NSString *url = [NSString stringWithFormat:@"%@/unregister", ZeroPushAPIURLHost]; 155 | 156 | [self HTTPRequest:@"DELETE" 157 | url:url 158 | params:params 159 | errorSelector:@selector(tokenUnregistrationDidFailWithError:)]; 160 | 161 | self.deviceToken = @""; 162 | } 163 | 164 | - (NSString *)deviceToken 165 | { 166 | if (_deviceToken == nil) { 167 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 168 | _deviceToken = [defaults stringForKey:@"com.zeropush.api.deviceToken"]; 169 | } 170 | 171 | if (_deviceToken == nil) { 172 | return @""; 173 | } 174 | 175 | return _deviceToken; 176 | } 177 | 178 | - (void)setDeviceToken:(NSString *)deviceToken 179 | { 180 | if (deviceToken != nil) { 181 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 182 | [defaults setObject:deviceToken forKey:@"com.zeropush.api.deviceToken"]; 183 | [defaults synchronize]; 184 | } 185 | _deviceToken = deviceToken; 186 | } 187 | 188 | -(NSString *)apiKey 189 | { 190 | if (_apiKey == nil) { 191 | return @""; 192 | } 193 | return _apiKey; 194 | } 195 | 196 | 197 | - (void)setBadge:(NSInteger)badge 198 | { 199 | // reset the device's badge 200 | [[UIApplication sharedApplication] setApplicationIconBadgeNumber:badge]; 201 | 202 | // tell the api the badge has been reset 203 | NSMutableDictionary *params = [NSMutableDictionary dictionary]; 204 | [params setObject:self.deviceToken forKey:@"device_token"]; 205 | [params setObject:[NSString stringWithFormat:@"%ld", (long)badge] forKey:@"badge"]; 206 | 207 | NSString *url = [NSString stringWithFormat:@"%@/set_badge", ZeroPushAPIURLHost]; 208 | 209 | [self HTTPRequest:@"POST" 210 | url:url 211 | params:params 212 | errorSelector:@selector(setBadgeDidFailWithError:)]; 213 | } 214 | 215 | - (void)resetBadge 216 | { 217 | [self setBadge:0]; 218 | } 219 | 220 | - (void)subscribeToChannel:(NSString *)channel; 221 | { 222 | NSMutableDictionary *params = [NSMutableDictionary dictionary]; 223 | [params setObject:self.deviceToken forKey:@"device_token"]; 224 | [params setObject:channel forKey:@"channel"]; 225 | 226 | NSString *url = [NSString stringWithFormat:@"%@/subscribe", ZeroPushAPIURLHost]; 227 | 228 | [self HTTPRequest:@"POST" 229 | url:url 230 | params:params 231 | errorSelector:@selector(subscribeDidFailWithError:)]; 232 | } 233 | 234 | - (void)unsubscribeFromChannel:(NSString *)channel; 235 | { 236 | NSMutableDictionary *params = [NSMutableDictionary dictionary]; 237 | [params setObject:self.deviceToken forKey:@"device_token"]; 238 | [params setObject:channel forKey:@"channel"]; 239 | 240 | NSString *url = [NSString stringWithFormat:@"%@/subscribe", ZeroPushAPIURLHost]; 241 | 242 | [self HTTPRequest:@"DELETE" 243 | url:url 244 | params:params 245 | errorSelector:@selector(unsubscribeDidFailWithError:)]; 246 | } 247 | 248 | -(void)unsubscribeFromAllChannels 249 | { 250 | if ([self.deviceToken length] == 0) { 251 | NSLog(@"ZeroPush-iOS: Cannot call %s before having a deviceToken", __PRETTY_FUNCTION__); 252 | return; 253 | } 254 | NSString *url = [NSString stringWithFormat:@"%@/devices/%@", ZeroPushAPIURLHost, self.deviceToken]; 255 | 256 | [self HTTPRequest:@"PUT" 257 | url:url 258 | params:@{@"channel_list": @""} 259 | errorSelector:@selector(unsubscribeDidFailWithError:)]; 260 | } 261 | 262 | 263 | - (void)getDevice:(void (^)(NSDictionary *device, NSError *error))callback 264 | { 265 | if ([self.deviceToken length] == 0) { 266 | NSLog(@"ZeroPush-iOS: Cannot call %s before having a deviceToken", __PRETTY_FUNCTION__); 267 | return; 268 | } 269 | NSString *url = [NSString stringWithFormat:@"%@/devices/%@", ZeroPushAPIURLHost, self.deviceToken]; 270 | 271 | [self HTTPRequest:@"GET" 272 | url:url 273 | completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *connectionError) { 274 | if(connectionError) { 275 | return callback(nil, connectionError); 276 | } 277 | 278 | NSError *error; 279 | NSDictionary *device = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; 280 | return callback(device, error); 281 | }]; 282 | } 283 | 284 | - (void)getChannels:(void (^)(NSArray *channels, NSError *error)) callback 285 | { 286 | [self getDevice:^(NSDictionary *device, NSError *error) { 287 | NSArray *channels = nil; 288 | if (device) { 289 | channels = [device objectForKey:@"channels"]; 290 | } 291 | return callback(channels, error); 292 | }]; 293 | } 294 | 295 | -(void)setChannels:(NSArray *)channels 296 | { 297 | if ([self.deviceToken length] == 0) { 298 | NSLog(@"ZeroPush-iOS: Cannot call %s before having a deviceToken", __PRETTY_FUNCTION__); 299 | return; 300 | } 301 | NSString *url = [NSString stringWithFormat:@"%@/devices/%@", ZeroPushAPIURLHost, self.deviceToken]; 302 | 303 | [self HTTPRequest:@"PUT" 304 | url:url 305 | params:@{@"channel_list": [channels componentsJoinedByString:@","]} 306 | errorSelector:@selector(subscribeDidFailWithError:)]; 307 | } 308 | 309 | 310 | #pragma mark - HTTP Requests 311 | 312 | -(void)HTTPRequest:(NSString *) verb url:(NSString *)url params:(NSDictionary *)params completionHandler:(void (^)(NSHTTPURLResponse* response, NSData* data, NSError* connectionError)) handler 313 | { 314 | self.lastResponse = nil; //clear out the response 315 | 316 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]]; 317 | request.HTTPMethod = verb; 318 | 319 | if(self.apiKey != nil && [self.apiKey length] > 0) 320 | { 321 | NSString *tokenValue = [NSString stringWithFormat:@"Token token=\"%@\"", self.apiKey]; 322 | [request setValue:tokenValue forHTTPHeaderField:@"Authorization"]; 323 | } 324 | 325 | if (params != nil) 326 | { 327 | NSError *jsonError; 328 | NSData *json = [NSJSONSerialization dataWithJSONObject:params options:0 error:&jsonError]; 329 | 330 | if(jsonError) { 331 | return handler(nil, nil, jsonError); 332 | } 333 | 334 | request.HTTPBody = json; 335 | [request setValue:ZeroPushClientVersion forHTTPHeaderField:@"X-API-Client-Agent"]; 336 | [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 337 | } 338 | 339 | [NSURLConnection sendAsynchronousRequest:request 340 | queue:self.operationQueue 341 | completionHandler:^(NSURLResponse *urlResponse, NSData *data, NSError *error) { 342 | NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) urlResponse; 343 | handler(httpResponse, data, error); 344 | self.lastResponse = httpResponse; 345 | }]; 346 | } 347 | 348 | -(void)HTTPRequest:(NSString *)verb url:(NSString *)url completionHandler:(void (^)(NSHTTPURLResponse *, NSData *, NSError *))handler 349 | { 350 | [self HTTPRequest:verb url:url params:nil completionHandler:handler]; 351 | } 352 | 353 | #pragma clang diagnostic push 354 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 355 | -(void)HTTPRequest:(NSString *)verb url:(NSString *)url params:(NSDictionary *)params errorSelector:(SEL)errorSelector 356 | { 357 | [self HTTPRequest:verb url:url params:params completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSError *error) { 358 | 359 | if (![self.delegate respondsToSelector:errorSelector]) { 360 | if (error) { 361 | NSLog(@"ZeroPush-iOS: %@", [error description]); 362 | } 363 | return; 364 | } 365 | if (error) { 366 | [self.delegate performSelector:errorSelector withObject:error]; 367 | return; 368 | } 369 | NSInteger statusCode = [response statusCode]; 370 | 371 | //if 300, we need to manually follow redirects 372 | 373 | if (statusCode >= 400) { 374 | NSDictionary *userInfo = [self userInfoForData:data andResponse:response]; 375 | NSError *apiError = [NSError errorWithDomain:@"com.zeropush.api" code:statusCode userInfo:userInfo]; 376 | [self.delegate performSelector:errorSelector withObject:apiError]; 377 | } 378 | }]; 379 | } 380 | #pragma clang diagnostic pop 381 | @end 382 | -------------------------------------------------------------------------------- /ZeroPush-iOS Tests/ZeroPushSpec.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZeroPushSpec.m 3 | // ZeroPush-iOS 4 | // 5 | // Created by Stefan Natchev on 9/12/14. 6 | // Copyright (c) 2015 ZeroPush. All rights reserved. 7 | // 8 | 9 | #import "Kiwi.h" 10 | #import "Nocilla.h" 11 | #import "ZeroPush.h" 12 | 13 | @interface TestApplication : NSObject 14 | - (void)tokenRegistrationDidFailWithError:(NSError *)error; 15 | - (void)tokenUnregistrationDidFailWithError:(NSError *)error; 16 | - (void)subscribeDidFailWithError:(NSError *)error; 17 | - (void)unsubscribeDidFailWithError:(NSError *)error; 18 | - (void)setBadgeDidFailWithError:(NSError *)error; 19 | @end 20 | 21 | @implementation TestApplication 22 | -(void)tokenRegistrationDidFailWithError:(NSError *)error 23 | { 24 | NSLog(@"Token registration failed"); 25 | } 26 | -(void)tokenUnregistrationDidFailWithError:(NSError *)error 27 | { 28 | NSLog(@"Token unregistration failed"); 29 | } 30 | -(void)subscribeDidFailWithError:(NSError *)error 31 | { 32 | NSLog(@"subscribe failed"); 33 | } 34 | -(void)unsubscribeDidFailWithError:(NSError *)error 35 | { 36 | NSLog(@"unsubscribe failed"); 37 | } 38 | -(void)setBadgeDidFailWithError:(NSError *)error 39 | { 40 | NSLog(@"set badge failed"); 41 | } 42 | @end 43 | 44 | /* NSData category */ 45 | // NSData+HexString.m 46 | // libsecurity_transform 47 | // 48 | // Copyright (c) 2011 Apple, Inc. All rights reserved. 49 | // 50 | @implementation NSData (HexString) 51 | 52 | +(id)dataWithHexString:(NSString *)hex 53 | { 54 | char buf[3]; 55 | buf[2] = '\0'; 56 | NSAssert(0 == [hex length] % 2, @"Hex strings should have an even number of digits (%@)", hex); 57 | unsigned char *bytes = malloc([hex length]/2); 58 | unsigned char *bp = bytes; 59 | for (CFIndex i = 0; i < [hex length]; i += 2) { 60 | buf[0] = [hex characterAtIndex:i]; 61 | buf[1] = [hex characterAtIndex:i+1]; 62 | char *b2 = NULL; 63 | *bp++ = strtol(buf, &b2, 16); 64 | NSAssert(b2 == buf + 2, @"String should be all hex digits: %@ (bad digit around %ld)", hex, i); 65 | } 66 | 67 | return [NSData dataWithBytesNoCopy:bytes length:[hex length]/2 freeWhenDone:YES]; 68 | } 69 | 70 | @end 71 | 72 | /* ZeroPush TestMethods */ 73 | 74 | @interface ZeroPush (TestMethods) 75 | 76 | @property (nonatomic, strong)NSHTTPURLResponse *lastResponse; 77 | 78 | @end 79 | 80 | SPEC_BEGIN(ZeroPushSpec) 81 | 82 | describe(@"ZeroPush", ^{ 83 | __block id application = [[TestApplication alloc] init]; 84 | __block ZeroPush * zeroPush = nil; 85 | 86 | let(deviceToken, ^{ 87 | return [NSData dataWithHexString:@"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"]; 88 | }); 89 | let(userDefaults, ^{ 90 | return [NSUserDefaults standardUserDefaults]; 91 | }); 92 | 93 | beforeAll(^{ 94 | [[LSNocilla sharedInstance] start]; 95 | }); 96 | 97 | beforeEach(^{ 98 | zeroPush = [[ZeroPush alloc] init]; 99 | zeroPush.delegate = application; 100 | zeroPush.apiKey = @"testing"; 101 | [userDefaults removeObjectForKey:@"com.zeropush.api.deviceToken"]; 102 | }); 103 | 104 | afterAll(^{ 105 | [[LSNocilla sharedInstance] stop]; 106 | }); 107 | afterEach(^{ 108 | [[LSNocilla sharedInstance] clearStubs]; 109 | }); 110 | 111 | context(@"engageWithAPIKey", ^{ 112 | it(@"returns a string representation of device token data", ^{ 113 | [[[ZeroPush deviceTokenFromData:deviceToken] should] equal: @"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"]; 114 | }); 115 | it(@"returns nil if the device token data is nil", ^{ 116 | [[[ZeroPush deviceTokenFromData:nil] should] beNil]; 117 | }); 118 | it(@"returns nil if the device token data is longer than 1024 bytes", ^{ 119 | NSMutableData *data = [NSMutableData dataWithData:deviceToken]; 120 | for(int i = 0; i < 35; i++){ 121 | [data appendData:deviceToken]; 122 | } 123 | [[[ZeroPush deviceTokenFromData:data] should] beNil]; 124 | }); 125 | }); 126 | 127 | context(@"engageWithAPIKey", ^{ 128 | it(@"should initialize the shared instance", ^{ 129 | [ZeroPush engageWithAPIKey:@"testing"]; 130 | [[[ZeroPush shared].apiKey should] equal:@"testing"]; 131 | }); 132 | it(@"should initialize the shared instance with a delegate", ^{ 133 | id newDelegate = [[TestApplication alloc] init]; 134 | [ZeroPush engageWithAPIKey:@"testing" delegate:newDelegate]; 135 | [[(NSObject*)[ZeroPush shared].delegate should] equal:newDelegate]; 136 | [[(NSObject*)[ZeroPush shared].delegate shouldNot] equal:application]; 137 | }); 138 | it(@"should not attempt to deference a deallocated delegate", ^{ 139 | id newDelegate = [[TestApplication alloc] init]; 140 | [ZeroPush engageWithAPIKey:@"testing" delegate:newDelegate]; 141 | newDelegate = nil; //dealloc 142 | [[(NSObject*)[ZeroPush shared].delegate should] beNil]; 143 | }); 144 | }); 145 | 146 | context(@"deviceToken", ^{ 147 | it(@"should never be nil", ^{ 148 | [[zeroPush.deviceToken should] equal:@""]; 149 | }); 150 | 151 | it(@"should save to NSUserDefaults", ^{ 152 | zeroPush.deviceToken = @"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; 153 | [[[userDefaults stringForKey:@"com.zeropush.api.deviceToken"] should] equal:@"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"]; 154 | }); 155 | 156 | it(@"should retrieve from NSUserDefaults", ^{ 157 | zeroPush.deviceToken = @"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; 158 | zeroPush.deviceToken = nil; 159 | [[zeroPush.deviceToken should] equal:@"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"]; 160 | }); 161 | }); 162 | 163 | context(@"API methods", ^{ 164 | beforeEach(^{ 165 | zeroPush.deviceToken = @"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; 166 | }); 167 | context(@"registerDeviceToken", ^{ 168 | it(@"should register with a device token", ^{ 169 | stubRequest(@"POST", @"https://api.zeropush.com/register"). 170 | withHeaders(@{ @"Content-Type": @"application/json", 171 | @"Authorization": @"Token token=\"testing\""}). 172 | withBody(@"{\"device_token\":\"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\"}"); 173 | 174 | [zeroPush registerDeviceToken:deviceToken]; 175 | [[[zeroPush deviceToken] should] equal:@"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"]; 176 | [[expectFutureValue(zeroPush.lastResponse) shouldEventually] beNonNil]; 177 | }); 178 | 179 | it(@"should register with a device token and subscribe it to a channel", ^{ 180 | stubRequest(@"POST", @"https://api.zeropush.com/register"). 181 | withHeaders(@{ @"Content-Type": @"application/json", 182 | @"Authorization": @"Token token=\"testing\""}). 183 | withBody(@"{\"channel\":\"testing-channel\",\"device_token\":\"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\"}"); 184 | 185 | [zeroPush registerDeviceToken:deviceToken channel:@"testing-channel"]; 186 | [[expectFutureValue(zeroPush.lastResponse) shouldEventually] beNonNil]; 187 | }); 188 | 189 | it(@"should call the error selector if an error happens", ^{ 190 | stubRequest(@"POST", @"https://api.zeropush.com/register"). 191 | withHeaders(@{ @"Content-Type": @"application/json", 192 | @"Authorization": @"Token token=\"testing\""}). 193 | withBody(@"{\"device_token\":\"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\"}"). 194 | andFailWithError([NSError errorWithDomain:@"com.zeropush.api" code:401 userInfo:nil]); 195 | 196 | [zeroPush registerDeviceToken:deviceToken]; 197 | [[expectFutureValue(application) shouldEventually] receive:@selector(tokenRegistrationDidFailWithError:)]; 198 | }); 199 | }); 200 | 201 | context(@"subscribeToChannel", ^{ 202 | it(@"should add a new channel to the channel subscriptions", ^{ 203 | stubRequest(@"POST", @"https://api.zeropush.com/subscribe"). 204 | withHeaders(@{ @"Content-Type": @"application/json", 205 | @"Authorization": @"Token token=\"testing\""}). 206 | withBody(@"{\"channel\":\"player-1\",\"device_token\":\"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\"}"); 207 | [zeroPush subscribeToChannel:@"player-1"]; 208 | [[expectFutureValue(zeroPush.lastResponse) shouldEventually] beNonNil]; 209 | }); 210 | 211 | it(@"should call the error selector if an error occured", ^{ 212 | stubRequest(@"POST", @"https://api.zeropush.com/subscribe"). 213 | withHeaders(@{ @"Content-Type": @"application/json", 214 | @"Authorization": @"Token token=\"testing\""}). 215 | withBody(@"{\"channel\":\"player-1\",\"device_token\":\"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\"}"). 216 | andFailWithError([NSError errorWithDomain:@"com.zeropush.api" code:401 userInfo:nil]); 217 | [zeroPush subscribeToChannel:@"player-1"]; 218 | [[expectFutureValue(application) shouldEventually] receive:@selector(subscribeDidFailWithError:)]; 219 | }); 220 | }); 221 | 222 | context(@"unsubscribeFromChannel", ^{ 223 | it(@"should remove a channel from the channel subscriptions", ^{ 224 | stubRequest(@"DELETE", @"https://api.zeropush.com/subscribe"). 225 | withHeaders(@{ @"Content-Type": @"application/json", 226 | @"Authorization": @"Token token=\"testing\""}). 227 | withBody(@"{\"channel\":\"player-1\",\"device_token\":\"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\"}"); 228 | 229 | [zeroPush unsubscribeFromChannel:@"player-1"]; 230 | [[expectFutureValue(zeroPush.lastResponse) shouldEventually] beNonNil]; 231 | }); 232 | 233 | it(@"should call the error selector if an error occured", ^{ 234 | stubRequest(@"DELETE", @"https://api.zeropush.com/subscribe"). 235 | withHeaders(@{ @"Content-Type": @"application/json", 236 | @"Authorization": @"Token token=\"testing\""}). 237 | withBody(@"{\"channel\":\"player-1\",\"device_token\":\"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\"}"). 238 | andFailWithError([NSError errorWithDomain:@"com.zeropush.api" code:401 userInfo:nil]); 239 | 240 | [zeroPush unsubscribeFromChannel:@"player-1"]; 241 | [[expectFutureValue(application) shouldEventually] receive:@selector(unsubscribeDidFailWithError:)]; 242 | }); 243 | }); 244 | 245 | context(@"unsubscribeFromAllChannels", ^{ 246 | it(@"should remove all channels", ^{ 247 | stubRequest(@"PUT", @"https://api.zeropush.com/devices/1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"). 248 | withHeaders(@{ @"Content-Type": @"application/json", 249 | @"Authorization": @"Token token=\"testing\""}). 250 | withBody(@"{\"channel_list\":\"\"}"); 251 | [zeroPush unsubscribeFromAllChannels]; 252 | [[expectFutureValue(zeroPush.lastResponse) shouldEventually] beNonNil]; 253 | }); 254 | 255 | it(@"should call the error selector if an error occured", ^{ 256 | stubRequest(@"PUT", @"https://api.zeropush.com/devices/1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"). 257 | withHeaders(@{ @"Content-Type": @"application/json", 258 | @"Authorization": @"Token token=\"testing\""}). 259 | withBody(@"{\"channel_list\":\"\"}"). 260 | andFailWithError([NSError errorWithDomain:@"com.zeropush.api" code:401 userInfo:nil]); 261 | 262 | [zeroPush unsubscribeFromAllChannels]; 263 | [[expectFutureValue(application) shouldEventually] receive:@selector(unsubscribeDidFailWithError:)]; 264 | }); 265 | }); 266 | 267 | context(@"getChannels", ^{ 268 | it(@"should invoke the callback with the channels", ^{ 269 | __block NSArray *fetchedChannels = nil; 270 | 271 | stubRequest(@"GET", @"https://api.zeropush.com/devices/1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"). 272 | withHeaders(@{@"Authorization": @"Token token=\"testing\""}). 273 | andReturn(200). 274 | withBody(@"{\"channels\":[\"player-1\"]}"); 275 | 276 | [zeroPush getChannels:^(NSArray *channels, NSError *error) { 277 | fetchedChannels = channels; 278 | }]; 279 | [[expectFutureValue(fetchedChannels) shouldEventually] equal:@[@"player-1"]]; 280 | }); 281 | 282 | it(@"should invoke the callback with an error", ^{ 283 | __block NSArray *fetchedChannels = nil; 284 | __block NSError *requestError = nil; 285 | 286 | stubRequest(@"GET", @"https://api.zeropush.com/devices/1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"). 287 | withHeaders(@{@"Authorization": @"Token token=\"testing\""}). 288 | andFailWithError([NSError errorWithDomain:@"com.zeropush.api" code:401 userInfo:nil]); 289 | 290 | [zeroPush getChannels:^(NSArray *channels, NSError *error) { 291 | fetchedChannels = channels; 292 | requestError = error; 293 | }]; 294 | [[expectFutureValue(fetchedChannels) shouldEventually] beNil]; 295 | [[expectFutureValue(requestError) shouldEventually] beNonNil]; 296 | }); 297 | }); 298 | 299 | context(@"setChannels", ^{ 300 | it(@"should make a request to set channels", ^{ 301 | stubRequest(@"PUT", @"https://api.zeropush.com/devices/1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"). 302 | withHeaders(@{ @"Content-Type": @"application/json", 303 | @"Authorization": @"Token token=\"testing\""}). 304 | withBody(@"{\"channel_list\":\"player-1,game-12\"}"); 305 | 306 | [zeroPush setChannels:@[@"player-1", @"game-12"]]; 307 | [[expectFutureValue(zeroPush.lastResponse) shouldEventually] beNonNil]; 308 | }); 309 | 310 | it(@"should call the error selector if an error occured", ^{ 311 | stubRequest(@"PUT", @"https://api.zeropush.com/devices/1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"). 312 | withHeaders(@{ @"Content-Type": @"application/json", 313 | @"Authorization": @"Token token=\"testing\""}). 314 | withBody(@"{\"channel_list\":\"player-1,game-12\"}"). 315 | andFailWithError([NSError errorWithDomain:@"com.zeropush.api" code:401 userInfo:nil]); 316 | [zeroPush setChannels:@[@"player-1", @"game-12"]]; 317 | [[expectFutureValue(application) shouldEventually] receive:@selector(subscribeDidFailWithError:)]; 318 | }); 319 | }); 320 | 321 | context(@"setBadge", ^{ 322 | it(@"should make a request to set badge", ^{ 323 | stubRequest(@"POST", @"https://api.zeropush.com/set_badge"). 324 | withHeaders(@{ @"Content-Type": @"application/json", 325 | @"Authorization": @"Token token=\"testing\""}). 326 | withBody(@"{\"badge\":\"1\",\"device_token\":\"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\"}"); 327 | 328 | [zeroPush setBadge:1]; 329 | [[expectFutureValue(zeroPush.lastResponse) shouldEventually] beNonNil]; 330 | }); 331 | 332 | it(@"should call the error selector if an error occured", ^{ 333 | stubRequest(@"POST", @"https://api.zeropush.com/set_badge"). 334 | withHeaders(@{ @"Content-Type": @"application/json", 335 | @"Authorization": @"Token token=\"testing\""}). 336 | withBody(@"{\"badge\":\"1\",\"device_token\":\"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\"}"). 337 | andFailWithError([NSError errorWithDomain:@"com.zeropush.api" code:401 userInfo:nil]); 338 | [zeroPush setBadge:1]; 339 | [[expectFutureValue(application) shouldEventually] receive:@selector(setBadgeDidFailWithError:)]; 340 | }); 341 | }); 342 | 343 | context(@"resetBadge", ^{ 344 | it(@"should make a request to set the badge to 0", ^{ 345 | stubRequest(@"POST", @"https://api.zeropush.com/set_badge"). 346 | withHeaders(@{ @"Content-Type": @"application/json", 347 | @"Authorization": @"Token token=\"testing\""}). 348 | withBody(@"{\"badge\":\"0\",\"device_token\":\"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\"}"); 349 | [zeroPush resetBadge]; 350 | [[expectFutureValue(zeroPush.lastResponse) shouldEventually] beNonNil]; 351 | }); 352 | }); 353 | 354 | context(@"unregisterDeviceToken", ^{ 355 | it(@"should unregister a device token", ^{ 356 | stubRequest(@"DELETE", @"https://api.zeropush.com/unregister"). 357 | withHeaders(@{ @"Content-Type": @"application/json", 358 | @"Authorization": @"Token token=\"testing\""}). 359 | withBody(@"{\"device_token\":\"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\"}"); 360 | 361 | [zeroPush unregisterDeviceToken]; 362 | [[[zeroPush deviceToken] should] beEmpty]; 363 | [[expectFutureValue(zeroPush.lastResponse) shouldEventually] beNonNil]; 364 | }); 365 | }); 366 | }); 367 | }); 368 | 369 | SPEC_END 370 | -------------------------------------------------------------------------------- /ZeroPush-iOS.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3BE9693F0DA14AB6BC3AC158 /* libPods-ZeroPush-iOS Tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F3643AE1BC094FDD95725C55 /* libPods-ZeroPush-iOS Tests.a */; }; 11 | 5628F0F516E6536300E504A2 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5628F0F416E6536300E504A2 /* UIKit.framework */; }; 12 | 56F0929616E64FC300C7BBDD /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 56F0929516E64FC300C7BBDD /* Foundation.framework */; }; 13 | 56F0929B16E64FC300C7BBDD /* ZeroPush.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 56F0929A16E64FC300C7BBDD /* ZeroPush.h */; }; 14 | 56F0929D16E64FC300C7BBDD /* ZeroPush.m in Sources */ = {isa = PBXBuildFile; fileRef = 56F0929C16E64FC300C7BBDD /* ZeroPush.m */; }; 15 | F835A85019C3636400B9B5D8 /* ZeroPushSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = F835A84F19C3636400B9B5D8 /* ZeroPushSpec.m */; }; 16 | F835A85119C3724300B9B5D8 /* ZeroPush.m in Sources */ = {isa = PBXBuildFile; fileRef = 56F0929C16E64FC300C7BBDD /* ZeroPush.m */; }; 17 | F846088A19C35A50006D19DF /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F846088919C35A50006D19DF /* XCTest.framework */; }; 18 | F846088B19C35A50006D19DF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 56F0929516E64FC300C7BBDD /* Foundation.framework */; }; 19 | F846088C19C35A50006D19DF /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5628F0F416E6536300E504A2 /* UIKit.framework */; }; 20 | F846089219C35A51006D19DF /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F846089019C35A50006D19DF /* InfoPlist.strings */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXContainerItemProxy section */ 24 | F846089619C35A51006D19DF /* PBXContainerItemProxy */ = { 25 | isa = PBXContainerItemProxy; 26 | containerPortal = 56F0928A16E64FC300C7BBDD /* Project object */; 27 | proxyType = 1; 28 | remoteGlobalIDString = 56F0929116E64FC300C7BBDD; 29 | remoteInfo = "ZeroPush-iOS"; 30 | }; 31 | /* End PBXContainerItemProxy section */ 32 | 33 | /* Begin PBXCopyFilesBuildPhase section */ 34 | 56F0929016E64FC300C7BBDD /* CopyFiles */ = { 35 | isa = PBXCopyFilesBuildPhase; 36 | buildActionMask = 2147483647; 37 | dstPath = "include/${PRODUCT_NAME}"; 38 | dstSubfolderSpec = 16; 39 | files = ( 40 | 56F0929B16E64FC300C7BBDD /* ZeroPush.h in CopyFiles */, 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | /* End PBXCopyFilesBuildPhase section */ 45 | 46 | /* Begin PBXFileReference section */ 47 | 0DC84CD4355CFB169F36B029 /* Pods-ZeroPush-iOS Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ZeroPush-iOS Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-ZeroPush-iOS Tests/Pods-ZeroPush-iOS Tests.release.xcconfig"; sourceTree = ""; }; 48 | 5628F0F416E6536300E504A2 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 49 | 56F0929216E64FC300C7BBDD /* libZeroPush-iOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libZeroPush-iOS.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 50 | 56F0929516E64FC300C7BBDD /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 51 | 56F0929916E64FC300C7BBDD /* ZeroPush-iOS-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ZeroPush-iOS-Prefix.pch"; sourceTree = ""; }; 52 | 56F0929A16E64FC300C7BBDD /* ZeroPush.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ZeroPush.h; sourceTree = ""; }; 53 | 56F0929C16E64FC300C7BBDD /* ZeroPush.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ZeroPush.m; sourceTree = ""; }; 54 | 83EC5399078E48BBAEF4040D /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 55 | D0C9BDD3B0D69B132C1E99D9 /* Pods-ZeroPush-iOS Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ZeroPush-iOS Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ZeroPush-iOS Tests/Pods-ZeroPush-iOS Tests.debug.xcconfig"; sourceTree = ""; }; 56 | F3643AE1BC094FDD95725C55 /* libPods-ZeroPush-iOS Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ZeroPush-iOS Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | F835A84F19C3636400B9B5D8 /* ZeroPushSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZeroPushSpec.m; sourceTree = ""; }; 58 | F846088819C35A50006D19DF /* ZeroPush-iOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "ZeroPush-iOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 59 | F846088919C35A50006D19DF /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 60 | F846088F19C35A50006D19DF /* ZeroPush-iOS Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ZeroPush-iOS Tests-Info.plist"; sourceTree = ""; }; 61 | F846089119C35A50006D19DF /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 62 | F846089519C35A51006D19DF /* ZeroPush-iOS Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ZeroPush-iOS Tests-Prefix.pch"; sourceTree = ""; }; 63 | /* End PBXFileReference section */ 64 | 65 | /* Begin PBXFrameworksBuildPhase section */ 66 | 56F0928F16E64FC300C7BBDD /* Frameworks */ = { 67 | isa = PBXFrameworksBuildPhase; 68 | buildActionMask = 2147483647; 69 | files = ( 70 | 5628F0F516E6536300E504A2 /* UIKit.framework in Frameworks */, 71 | 56F0929616E64FC300C7BBDD /* Foundation.framework in Frameworks */, 72 | ); 73 | runOnlyForDeploymentPostprocessing = 0; 74 | }; 75 | F846088519C35A50006D19DF /* Frameworks */ = { 76 | isa = PBXFrameworksBuildPhase; 77 | buildActionMask = 2147483647; 78 | files = ( 79 | F846088A19C35A50006D19DF /* XCTest.framework in Frameworks */, 80 | F846088C19C35A50006D19DF /* UIKit.framework in Frameworks */, 81 | F846088B19C35A50006D19DF /* Foundation.framework in Frameworks */, 82 | 3BE9693F0DA14AB6BC3AC158 /* libPods-ZeroPush-iOS Tests.a in Frameworks */, 83 | ); 84 | runOnlyForDeploymentPostprocessing = 0; 85 | }; 86 | /* End PBXFrameworksBuildPhase section */ 87 | 88 | /* Begin PBXGroup section */ 89 | 541CCCBCA8D1EC0CD33FE70A /* Pods */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | D0C9BDD3B0D69B132C1E99D9 /* Pods-ZeroPush-iOS Tests.debug.xcconfig */, 93 | 0DC84CD4355CFB169F36B029 /* Pods-ZeroPush-iOS Tests.release.xcconfig */, 94 | ); 95 | name = Pods; 96 | sourceTree = ""; 97 | }; 98 | 56F0928916E64FC300C7BBDD = { 99 | isa = PBXGroup; 100 | children = ( 101 | 56F0929716E64FC300C7BBDD /* ZeroPush-iOS */, 102 | F846088D19C35A50006D19DF /* ZeroPush-iOS Tests */, 103 | 56F0929416E64FC300C7BBDD /* Frameworks */, 104 | 56F0929316E64FC300C7BBDD /* Products */, 105 | 541CCCBCA8D1EC0CD33FE70A /* Pods */, 106 | ); 107 | sourceTree = ""; 108 | }; 109 | 56F0929316E64FC300C7BBDD /* Products */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 56F0929216E64FC300C7BBDD /* libZeroPush-iOS.a */, 113 | F846088819C35A50006D19DF /* ZeroPush-iOS Tests.xctest */, 114 | ); 115 | name = Products; 116 | sourceTree = ""; 117 | }; 118 | 56F0929416E64FC300C7BBDD /* Frameworks */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 56F0929516E64FC300C7BBDD /* Foundation.framework */, 122 | 5628F0F416E6536300E504A2 /* UIKit.framework */, 123 | 83EC5399078E48BBAEF4040D /* libPods.a */, 124 | F846088919C35A50006D19DF /* XCTest.framework */, 125 | F3643AE1BC094FDD95725C55 /* libPods-ZeroPush-iOS Tests.a */, 126 | ); 127 | name = Frameworks; 128 | sourceTree = ""; 129 | }; 130 | 56F0929716E64FC300C7BBDD /* ZeroPush-iOS */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | 56F0929A16E64FC300C7BBDD /* ZeroPush.h */, 134 | 56F0929C16E64FC300C7BBDD /* ZeroPush.m */, 135 | 56F0929816E64FC300C7BBDD /* Supporting Files */, 136 | ); 137 | path = "ZeroPush-iOS"; 138 | sourceTree = ""; 139 | }; 140 | 56F0929816E64FC300C7BBDD /* Supporting Files */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | 56F0929916E64FC300C7BBDD /* ZeroPush-iOS-Prefix.pch */, 144 | ); 145 | name = "Supporting Files"; 146 | sourceTree = ""; 147 | }; 148 | F846088D19C35A50006D19DF /* ZeroPush-iOS Tests */ = { 149 | isa = PBXGroup; 150 | children = ( 151 | F835A84F19C3636400B9B5D8 /* ZeroPushSpec.m */, 152 | F846088E19C35A50006D19DF /* Supporting Files */, 153 | ); 154 | path = "ZeroPush-iOS Tests"; 155 | sourceTree = ""; 156 | }; 157 | F846088E19C35A50006D19DF /* Supporting Files */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | F846088F19C35A50006D19DF /* ZeroPush-iOS Tests-Info.plist */, 161 | F846089019C35A50006D19DF /* InfoPlist.strings */, 162 | F846089519C35A51006D19DF /* ZeroPush-iOS Tests-Prefix.pch */, 163 | ); 164 | name = "Supporting Files"; 165 | sourceTree = ""; 166 | }; 167 | /* End PBXGroup section */ 168 | 169 | /* Begin PBXNativeTarget section */ 170 | 56F0929116E64FC300C7BBDD /* ZeroPush-iOS */ = { 171 | isa = PBXNativeTarget; 172 | buildConfigurationList = 56F092A016E64FC300C7BBDD /* Build configuration list for PBXNativeTarget "ZeroPush-iOS" */; 173 | buildPhases = ( 174 | 56F0928E16E64FC300C7BBDD /* Sources */, 175 | 56F0928F16E64FC300C7BBDD /* Frameworks */, 176 | 56F0929016E64FC300C7BBDD /* CopyFiles */, 177 | ); 178 | buildRules = ( 179 | ); 180 | dependencies = ( 181 | ); 182 | name = "ZeroPush-iOS"; 183 | productName = "ZeroPush-iOS"; 184 | productReference = 56F0929216E64FC300C7BBDD /* libZeroPush-iOS.a */; 185 | productType = "com.apple.product-type.library.static"; 186 | }; 187 | F846088719C35A50006D19DF /* ZeroPush-iOS Tests */ = { 188 | isa = PBXNativeTarget; 189 | buildConfigurationList = F846089A19C35A51006D19DF /* Build configuration list for PBXNativeTarget "ZeroPush-iOS Tests" */; 190 | buildPhases = ( 191 | 9C03861ECCE5485DBBC64916 /* Check Pods Manifest.lock */, 192 | F846088419C35A50006D19DF /* Sources */, 193 | F846088519C35A50006D19DF /* Frameworks */, 194 | F846088619C35A50006D19DF /* Resources */, 195 | 889C2535E886442BA91F6638 /* Copy Pods Resources */, 196 | ); 197 | buildRules = ( 198 | ); 199 | dependencies = ( 200 | F846089719C35A51006D19DF /* PBXTargetDependency */, 201 | ); 202 | name = "ZeroPush-iOS Tests"; 203 | productName = "ZeroPush-iOS Tests"; 204 | productReference = F846088819C35A50006D19DF /* ZeroPush-iOS Tests.xctest */; 205 | productType = "com.apple.product-type.bundle.unit-test"; 206 | }; 207 | /* End PBXNativeTarget section */ 208 | 209 | /* Begin PBXProject section */ 210 | 56F0928A16E64FC300C7BBDD /* Project object */ = { 211 | isa = PBXProject; 212 | attributes = { 213 | LastUpgradeCheck = 0460; 214 | ORGANIZATIONNAME = ZeroPush; 215 | TargetAttributes = { 216 | F846088719C35A50006D19DF = { 217 | TestTargetID = 56F0929116E64FC300C7BBDD; 218 | }; 219 | }; 220 | }; 221 | buildConfigurationList = 56F0928D16E64FC300C7BBDD /* Build configuration list for PBXProject "ZeroPush-iOS" */; 222 | compatibilityVersion = "Xcode 3.2"; 223 | developmentRegion = English; 224 | hasScannedForEncodings = 0; 225 | knownRegions = ( 226 | en, 227 | ); 228 | mainGroup = 56F0928916E64FC300C7BBDD; 229 | productRefGroup = 56F0929316E64FC300C7BBDD /* Products */; 230 | projectDirPath = ""; 231 | projectRoot = ""; 232 | targets = ( 233 | 56F0929116E64FC300C7BBDD /* ZeroPush-iOS */, 234 | F846088719C35A50006D19DF /* ZeroPush-iOS Tests */, 235 | ); 236 | }; 237 | /* End PBXProject section */ 238 | 239 | /* Begin PBXResourcesBuildPhase section */ 240 | F846088619C35A50006D19DF /* Resources */ = { 241 | isa = PBXResourcesBuildPhase; 242 | buildActionMask = 2147483647; 243 | files = ( 244 | F846089219C35A51006D19DF /* InfoPlist.strings in Resources */, 245 | ); 246 | runOnlyForDeploymentPostprocessing = 0; 247 | }; 248 | /* End PBXResourcesBuildPhase section */ 249 | 250 | /* Begin PBXShellScriptBuildPhase section */ 251 | 889C2535E886442BA91F6638 /* Copy Pods Resources */ = { 252 | isa = PBXShellScriptBuildPhase; 253 | buildActionMask = 2147483647; 254 | files = ( 255 | ); 256 | inputPaths = ( 257 | ); 258 | name = "Copy Pods Resources"; 259 | outputPaths = ( 260 | ); 261 | runOnlyForDeploymentPostprocessing = 0; 262 | shellPath = /bin/sh; 263 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ZeroPush-iOS Tests/Pods-ZeroPush-iOS Tests-resources.sh\"\n"; 264 | showEnvVarsInLog = 0; 265 | }; 266 | 9C03861ECCE5485DBBC64916 /* Check Pods Manifest.lock */ = { 267 | isa = PBXShellScriptBuildPhase; 268 | buildActionMask = 2147483647; 269 | files = ( 270 | ); 271 | inputPaths = ( 272 | ); 273 | name = "Check Pods Manifest.lock"; 274 | outputPaths = ( 275 | ); 276 | runOnlyForDeploymentPostprocessing = 0; 277 | shellPath = /bin/sh; 278 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 279 | showEnvVarsInLog = 0; 280 | }; 281 | /* End PBXShellScriptBuildPhase section */ 282 | 283 | /* Begin PBXSourcesBuildPhase section */ 284 | 56F0928E16E64FC300C7BBDD /* Sources */ = { 285 | isa = PBXSourcesBuildPhase; 286 | buildActionMask = 2147483647; 287 | files = ( 288 | 56F0929D16E64FC300C7BBDD /* ZeroPush.m in Sources */, 289 | ); 290 | runOnlyForDeploymentPostprocessing = 0; 291 | }; 292 | F846088419C35A50006D19DF /* Sources */ = { 293 | isa = PBXSourcesBuildPhase; 294 | buildActionMask = 2147483647; 295 | files = ( 296 | F835A85019C3636400B9B5D8 /* ZeroPushSpec.m in Sources */, 297 | F835A85119C3724300B9B5D8 /* ZeroPush.m in Sources */, 298 | ); 299 | runOnlyForDeploymentPostprocessing = 0; 300 | }; 301 | /* End PBXSourcesBuildPhase section */ 302 | 303 | /* Begin PBXTargetDependency section */ 304 | F846089719C35A51006D19DF /* PBXTargetDependency */ = { 305 | isa = PBXTargetDependency; 306 | target = 56F0929116E64FC300C7BBDD /* ZeroPush-iOS */; 307 | targetProxy = F846089619C35A51006D19DF /* PBXContainerItemProxy */; 308 | }; 309 | /* End PBXTargetDependency section */ 310 | 311 | /* Begin PBXVariantGroup section */ 312 | F846089019C35A50006D19DF /* InfoPlist.strings */ = { 313 | isa = PBXVariantGroup; 314 | children = ( 315 | F846089119C35A50006D19DF /* en */, 316 | ); 317 | name = InfoPlist.strings; 318 | sourceTree = ""; 319 | }; 320 | /* End PBXVariantGroup section */ 321 | 322 | /* Begin XCBuildConfiguration section */ 323 | 56F0929E16E64FC300C7BBDD /* Debug */ = { 324 | isa = XCBuildConfiguration; 325 | buildSettings = { 326 | ALWAYS_SEARCH_USER_PATHS = NO; 327 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 328 | CLANG_CXX_LIBRARY = "libc++"; 329 | CLANG_ENABLE_OBJC_ARC = YES; 330 | CLANG_WARN_CONSTANT_CONVERSION = YES; 331 | CLANG_WARN_EMPTY_BODY = YES; 332 | CLANG_WARN_ENUM_CONVERSION = YES; 333 | CLANG_WARN_INT_CONVERSION = YES; 334 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 335 | COPY_PHASE_STRIP = NO; 336 | GCC_C_LANGUAGE_STANDARD = gnu99; 337 | GCC_DYNAMIC_NO_PIC = NO; 338 | GCC_OPTIMIZATION_LEVEL = 0; 339 | GCC_PREPROCESSOR_DEFINITIONS = ( 340 | "DEBUG=1", 341 | "$(inherited)", 342 | ); 343 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 344 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 345 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 346 | GCC_WARN_UNUSED_VARIABLE = YES; 347 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 348 | ONLY_ACTIVE_ARCH = YES; 349 | SDKROOT = iphoneos; 350 | }; 351 | name = Debug; 352 | }; 353 | 56F0929F16E64FC300C7BBDD /* Release */ = { 354 | isa = XCBuildConfiguration; 355 | buildSettings = { 356 | ALWAYS_SEARCH_USER_PATHS = NO; 357 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 358 | CLANG_CXX_LIBRARY = "libc++"; 359 | CLANG_ENABLE_OBJC_ARC = YES; 360 | CLANG_WARN_CONSTANT_CONVERSION = YES; 361 | CLANG_WARN_EMPTY_BODY = YES; 362 | CLANG_WARN_ENUM_CONVERSION = YES; 363 | CLANG_WARN_INT_CONVERSION = YES; 364 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 365 | COPY_PHASE_STRIP = YES; 366 | GCC_C_LANGUAGE_STANDARD = gnu99; 367 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 368 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 369 | GCC_WARN_UNUSED_VARIABLE = YES; 370 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 371 | SDKROOT = iphoneos; 372 | VALIDATE_PRODUCT = YES; 373 | }; 374 | name = Release; 375 | }; 376 | 56F092A116E64FC300C7BBDD /* Debug */ = { 377 | isa = XCBuildConfiguration; 378 | buildSettings = { 379 | DSTROOT = /tmp/ZeroPush_iOS.dst; 380 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 381 | GCC_PREFIX_HEADER = "ZeroPush-iOS/ZeroPush-iOS-Prefix.pch"; 382 | OTHER_LDFLAGS = "$(inherited)"; 383 | PRODUCT_NAME = "$(TARGET_NAME)"; 384 | SKIP_INSTALL = YES; 385 | }; 386 | name = Debug; 387 | }; 388 | 56F092A216E64FC300C7BBDD /* Release */ = { 389 | isa = XCBuildConfiguration; 390 | buildSettings = { 391 | DSTROOT = /tmp/ZeroPush_iOS.dst; 392 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 393 | GCC_PREFIX_HEADER = "ZeroPush-iOS/ZeroPush-iOS-Prefix.pch"; 394 | OTHER_LDFLAGS = "$(inherited)"; 395 | PRODUCT_NAME = "$(TARGET_NAME)"; 396 | SKIP_INSTALL = YES; 397 | }; 398 | name = Release; 399 | }; 400 | F846089819C35A51006D19DF /* Debug */ = { 401 | isa = XCBuildConfiguration; 402 | baseConfigurationReference = D0C9BDD3B0D69B132C1E99D9 /* Pods-ZeroPush-iOS Tests.debug.xcconfig */; 403 | buildSettings = { 404 | BUNDLE_LOADER = ""; 405 | CLANG_ENABLE_MODULES = YES; 406 | CLANG_WARN_BOOL_CONVERSION = YES; 407 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 408 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 409 | FRAMEWORK_SEARCH_PATHS = ( 410 | "$(SDKROOT)/Developer/Library/Frameworks", 411 | "$(inherited)", 412 | "$(DEVELOPER_FRAMEWORKS_DIR)", 413 | ); 414 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 415 | GCC_PREFIX_HEADER = "ZeroPush-iOS Tests/ZeroPush-iOS Tests-Prefix.pch"; 416 | GCC_PREPROCESSOR_DEFINITIONS = ( 417 | "DEBUG=1", 418 | "$(inherited)", 419 | ); 420 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 421 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 422 | GCC_WARN_UNDECLARED_SELECTOR = YES; 423 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 424 | GCC_WARN_UNUSED_FUNCTION = YES; 425 | INFOPLIST_FILE = "ZeroPush-iOS Tests/ZeroPush-iOS Tests-Info.plist"; 426 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 427 | PRODUCT_NAME = "$(TARGET_NAME)"; 428 | TEST_HOST = ""; 429 | WRAPPER_EXTENSION = xctest; 430 | }; 431 | name = Debug; 432 | }; 433 | F846089919C35A51006D19DF /* Release */ = { 434 | isa = XCBuildConfiguration; 435 | baseConfigurationReference = 0DC84CD4355CFB169F36B029 /* Pods-ZeroPush-iOS Tests.release.xcconfig */; 436 | buildSettings = { 437 | BUNDLE_LOADER = ""; 438 | CLANG_ENABLE_MODULES = YES; 439 | CLANG_WARN_BOOL_CONVERSION = YES; 440 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 441 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 442 | ENABLE_NS_ASSERTIONS = NO; 443 | FRAMEWORK_SEARCH_PATHS = ( 444 | "$(SDKROOT)/Developer/Library/Frameworks", 445 | "$(inherited)", 446 | "$(DEVELOPER_FRAMEWORKS_DIR)", 447 | ); 448 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 449 | GCC_PREFIX_HEADER = "ZeroPush-iOS Tests/ZeroPush-iOS Tests-Prefix.pch"; 450 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 451 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 452 | GCC_WARN_UNDECLARED_SELECTOR = YES; 453 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 454 | GCC_WARN_UNUSED_FUNCTION = YES; 455 | INFOPLIST_FILE = "ZeroPush-iOS Tests/ZeroPush-iOS Tests-Info.plist"; 456 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 457 | PRODUCT_NAME = "$(TARGET_NAME)"; 458 | TEST_HOST = ""; 459 | WRAPPER_EXTENSION = xctest; 460 | }; 461 | name = Release; 462 | }; 463 | /* End XCBuildConfiguration section */ 464 | 465 | /* Begin XCConfigurationList section */ 466 | 56F0928D16E64FC300C7BBDD /* Build configuration list for PBXProject "ZeroPush-iOS" */ = { 467 | isa = XCConfigurationList; 468 | buildConfigurations = ( 469 | 56F0929E16E64FC300C7BBDD /* Debug */, 470 | 56F0929F16E64FC300C7BBDD /* Release */, 471 | ); 472 | defaultConfigurationIsVisible = 0; 473 | defaultConfigurationName = Release; 474 | }; 475 | 56F092A016E64FC300C7BBDD /* Build configuration list for PBXNativeTarget "ZeroPush-iOS" */ = { 476 | isa = XCConfigurationList; 477 | buildConfigurations = ( 478 | 56F092A116E64FC300C7BBDD /* Debug */, 479 | 56F092A216E64FC300C7BBDD /* Release */, 480 | ); 481 | defaultConfigurationIsVisible = 0; 482 | defaultConfigurationName = Release; 483 | }; 484 | F846089A19C35A51006D19DF /* Build configuration list for PBXNativeTarget "ZeroPush-iOS Tests" */ = { 485 | isa = XCConfigurationList; 486 | buildConfigurations = ( 487 | F846089819C35A51006D19DF /* Debug */, 488 | F846089919C35A51006D19DF /* Release */, 489 | ); 490 | defaultConfigurationIsVisible = 0; 491 | defaultConfigurationName = Release; 492 | }; 493 | /* End XCConfigurationList section */ 494 | }; 495 | rootObject = 56F0928A16E64FC300C7BBDD /* Project object */; 496 | } 497 | --------------------------------------------------------------------------------