diff --git a/ios/SAPTracker/src/xcode/Podfile b/ios/SAPTracker/src/xcode/Podfile deleted file mode 100644 index d1f5320c5d4..00000000000 --- a/ios/SAPTracker/src/xcode/Podfile +++ /dev/null @@ -1,13 +0,0 @@ -source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '7.1' -link_with ['SAPTracker', 'SAPTrackerTests'] -pod 'AFNetworking', '2.5.0' -pod 'AFNetworkActivityLogger', '2.0.3', :configurations => ['Debug'] -pod 'TSMarkdownParser' - -# Update acknowledgements in build settings -post_install do | installer | - require 'fileutils' - FileUtils.cp_r('Pods/Target Support Files/Pods/Pods-Acknowledgements.plist', 'SAPTracker/Settings.bundle/Acknowledgements.plist', :remove_destination => true) - FileUtils.cp_r('Pods/Target Support Files/Pods/Pods-Acknowledgements.markdown', 'SAPTracker/Acknowledgements.markdown', :remove_destination => true) -end \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Podfile.lock b/ios/SAPTracker/src/xcode/Podfile.lock deleted file mode 100644 index 63458c3dd76..00000000000 --- a/ios/SAPTracker/src/xcode/Podfile.lock +++ /dev/null @@ -1,38 +0,0 @@ -PODS: - - AFNetworkActivityLogger (2.0.3): - - AFNetworking/NSURLConnection (~> 2.0) - - AFNetworking/NSURLSession (~> 2.0) - - AFNetworking (2.5.0): - - AFNetworking/NSURLConnection (= 2.5.0) - - AFNetworking/NSURLSession (= 2.5.0) - - AFNetworking/Reachability (= 2.5.0) - - AFNetworking/Security (= 2.5.0) - - AFNetworking/Serialization (= 2.5.0) - - AFNetworking/UIKit (= 2.5.0) - - AFNetworking/NSURLConnection (2.5.0): - - AFNetworking/Reachability - - AFNetworking/Security - - AFNetworking/Serialization - - AFNetworking/NSURLSession (2.5.0): - - AFNetworking/Reachability - - AFNetworking/Security - - AFNetworking/Serialization - - AFNetworking/Reachability (2.5.0) - - AFNetworking/Security (2.5.0) - - AFNetworking/Serialization (2.5.0) - - AFNetworking/UIKit (2.5.0): - - AFNetworking/NSURLConnection - - AFNetworking/NSURLSession - - TSMarkdownParser (1.0.19) - -DEPENDENCIES: - - AFNetworkActivityLogger (= 2.0.3) - - AFNetworking (= 2.5.0) - - TSMarkdownParser - -SPEC CHECKSUMS: - AFNetworkActivityLogger: e82c9ba285b37042d86729bff5b14036c4312cd7 - AFNetworking: 96ac9bf3eda33582701cb1fcc5b896aa1e20311e - TSMarkdownParser: 0341662db14b17a13a79f3ddcb08ab7a4b6ed834 - -COCOAPODS: 0.38.2 diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworkActivityLogger/AFNetworkActivityLogger/AFNetworkActivityLogger.h b/ios/SAPTracker/src/xcode/Pods/AFNetworkActivityLogger/AFNetworkActivityLogger/AFNetworkActivityLogger.h deleted file mode 100644 index b47fc73f16b..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworkActivityLogger/AFNetworkActivityLogger/AFNetworkActivityLogger.h +++ /dev/null @@ -1,109 +0,0 @@ -// AFNetworkActivityLogger.h -// -// Copyright (c) 2013 AFNetworking (http://afnetworking.com/) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#import - -typedef NS_ENUM(NSUInteger, AFHTTPRequestLoggerLevel) { - AFLoggerLevelOff, - AFLoggerLevelDebug, - AFLoggerLevelInfo, - AFLoggerLevelWarn, - AFLoggerLevelError, - AFLoggerLevelFatal = AFLoggerLevelOff, -}; - -/** - `AFNetworkActivityLogger` logs requests and responses made by AFNetworking, with an adjustable level of detail. - - Applications should enable the shared instance of `AFNetworkActivityLogger` in `AppDelegate -application:didFinishLaunchingWithOptions:`: - - [[AFNetworkActivityLogger sharedLogger] startLogging]; - - `AFNetworkActivityLogger` listens for `AFNetworkingOperationDidStartNotification` and `AFNetworkingOperationDidFinishNotification` notifications, which are posted by AFNetworking as request operations are started and finish. For further customization of logging output, users are encouraged to implement desired functionality by listening for these notifications. - */ -@interface AFNetworkActivityLogger : NSObject - -/** - The level of logging detail. See "Logging Levels" for possible values. `AFLoggerLevelInfo` by default. - */ -@property (nonatomic, assign) AFHTTPRequestLoggerLevel level; - -/** - Only log requests conforming to the specified predicate, if specified. `nil` by default. - - @discussion Each notification has an associated `NSURLRequest`. To filter out request and response logging, such as all network activity made to a particular domain, this predicate can be set to match against the appropriate URL string pattern. - */ -@property (nonatomic, strong) NSPredicate *filterPredicate; - -/** - Returns the shared logger instance. - */ -+ (instancetype)sharedLogger; - -/** - Start logging requests and responses. - */ -- (void)startLogging; - -/** - Stop logging requests and responses. - */ -- (void)stopLogging; - -@end - -///---------------- -/// @name Constants -///---------------- - -/** - ## Logging Levels - - The following constants specify the available logging levels for `AFNetworkActivityLogger`: - - enum { - AFLoggerLevelOff, - AFLoggerLevelDebug, - AFLoggerLevelInfo, - AFLoggerLevelWarn, - AFLoggerLevelError, - AFLoggerLevelFatal = AFLoggerLevelOff, - } - - `AFLoggerLevelOff` - Do not log requests or responses. - - `AFLoggerLevelDebug` - Logs HTTP method, URL, header fields, & request body for requests, and status code, URL, header fields, response string, & elapsed time for responses. - - `AFLoggerLevelInfo` - Logs HTTP method & URL for requests, and status code, URL, & elapsed time for responses. - - `AFLoggerLevelWarn` - Logs HTTP method & URL for requests, and status code, URL, & elapsed time for responses, but only for failed requests. - - `AFLoggerLevelError` - Equivalent to `AFLoggerLevelWarn` - - `AFLoggerLevelFatal` - Equivalent to `AFLoggerLevelOff` -*/ diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworkActivityLogger/AFNetworkActivityLogger/AFNetworkActivityLogger.m b/ios/SAPTracker/src/xcode/Pods/AFNetworkActivityLogger/AFNetworkActivityLogger/AFNetworkActivityLogger.m deleted file mode 100644 index eb39c001aaa..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworkActivityLogger/AFNetworkActivityLogger/AFNetworkActivityLogger.m +++ /dev/null @@ -1,171 +0,0 @@ -// AFNetworkActivityLogger.h -// -// Copyright (c) 2013 AFNetworking (http://afnetworking.com/) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#import "AFNetworkActivityLogger.h" -#import "AFURLConnectionOperation.h" -#import "AFURLSessionManager.h" - -#import - -static NSURLRequest * AFNetworkRequestFromNotification(NSNotification *notification) { - NSURLRequest *request = nil; - if ([[notification object] isKindOfClass:[AFURLConnectionOperation class]]) { - request = [(AFURLConnectionOperation *)[notification object] request]; - } else if ([[notification object] respondsToSelector:@selector(originalRequest)]) { - request = [[notification object] originalRequest]; - } - - return request; -} - -@implementation AFNetworkActivityLogger - -+ (instancetype)sharedLogger { - static AFNetworkActivityLogger *_sharedLogger = nil; - - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - _sharedLogger = [[self alloc] init]; - }); - - return _sharedLogger; -} - -- (id)init { - self = [super init]; - if (!self) { - return nil; - } - - self.level = AFLoggerLevelInfo; - - return self; -} - -- (void)dealloc { - [self stopLogging]; -} - -- (void)startLogging { - [self stopLogging]; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkRequestDidStart:) name:AFNetworkingOperationDidStartNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkRequestDidFinish:) name:AFNetworkingOperationDidFinishNotification object:nil]; - -#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090) - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkRequestDidStart:) name:AFNetworkingTaskDidResumeNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkRequestDidFinish:) name:AFNetworkingTaskDidCompleteNotification object:nil]; -#endif -} - -- (void)stopLogging { - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -#pragma mark - NSNotification - -static void * AFNetworkRequestStartDate = &AFNetworkRequestStartDate; - -- (void)networkRequestDidStart:(NSNotification *)notification { - NSURLRequest *request = AFNetworkRequestFromNotification(notification); - - if (!request) { - return; - } - - if (request && self.filterPredicate && [self.filterPredicate evaluateWithObject:request]) { - return; - } - - objc_setAssociatedObject(notification.object, AFNetworkRequestStartDate, [NSDate date], OBJC_ASSOCIATION_RETAIN_NONATOMIC); - - NSString *body = nil; - if ([request HTTPBody]) { - body = [[NSString alloc] initWithData:[request HTTPBody] encoding:NSUTF8StringEncoding]; - } - - switch (self.level) { - case AFLoggerLevelDebug: - NSLog(@"%@ '%@': %@ %@", [request HTTPMethod], [[request URL] absoluteString], [request allHTTPHeaderFields], body); - break; - case AFLoggerLevelInfo: - NSLog(@"%@ '%@'", [request HTTPMethod], [[request URL] absoluteString]); - break; - default: - break; - } -} - -- (void)networkRequestDidFinish:(NSNotification *)notification { - NSURLRequest *request = AFNetworkRequestFromNotification(notification); - NSURLResponse *response = [notification.object response]; - NSError *error = [notification.object error]; - - if (!request && !response) { - return; - } - - if (request && self.filterPredicate && [self.filterPredicate evaluateWithObject:request]) { - return; - } - - NSUInteger responseStatusCode = 0; - NSDictionary *responseHeaderFields = nil; - if ([response isKindOfClass:[NSHTTPURLResponse class]]) { - responseStatusCode = (NSUInteger)[(NSHTTPURLResponse *)response statusCode]; - responseHeaderFields = [(NSHTTPURLResponse *)response allHeaderFields]; - } - - id responseObject = nil; - if ([[notification object] respondsToSelector:@selector(responseString)]) { - responseObject = [[notification object] responseString]; - } else if (notification.userInfo) { - responseObject = notification.userInfo[AFNetworkingTaskDidCompleteSerializedResponseKey]; - } - - NSTimeInterval elapsedTime = [[NSDate date] timeIntervalSinceDate:objc_getAssociatedObject(notification.object, AFNetworkRequestStartDate)]; - - if (error) { - switch (self.level) { - case AFLoggerLevelDebug: - case AFLoggerLevelInfo: - case AFLoggerLevelWarn: - case AFLoggerLevelError: - NSLog(@"[Error] %@ '%@' (%ld) [%.04f s]: %@", [request HTTPMethod], [[response URL] absoluteString], (long)responseStatusCode, elapsedTime, error); - default: - break; - } - } else { - switch (self.level) { - case AFLoggerLevelDebug: - NSLog(@"%ld '%@' [%.04f s]: %@ %@", (long)responseStatusCode, [[response URL] absoluteString], elapsedTime, responseHeaderFields, responseObject); - break; - case AFLoggerLevelInfo: - NSLog(@"%ld '%@' [%.04f s]", (long)responseStatusCode, [[response URL] absoluteString], elapsedTime); - break; - default: - break; - } - } -} - -@end diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworkActivityLogger/LICENSE b/ios/SAPTracker/src/xcode/Pods/AFNetworkActivityLogger/LICENSE deleted file mode 100644 index f20a847d2ae..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworkActivityLogger/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2013 AFNetworking (http://afnetworking.com/) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworkActivityLogger/README.md b/ios/SAPTracker/src/xcode/Pods/AFNetworkActivityLogger/README.md deleted file mode 100644 index fac03506672..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworkActivityLogger/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# AFNetworkActivityLogger - -`AFNetworkActivityLogger` is an extension for [AFNetworking](http://github.com/AFNetworking/AFNetworking/) 2.0 that logs network requests as they are sent and received. - -> `AFNetworkActivityLogger` listens for `AFNetworkingOperationDidStartNotification` / `AFNetworkingOperationDidFinishNotification` and `AFNetworkingTaskDidStartNotification` / `AFNetworkingTaskDidFinishNotification` notifications, which are posted by AFNetworking as request operations and session tasks are started and finish. For further customization of logging output, users are encouraged to implement desired functionality by listening for these notifications. - -## Usage - -Add the following code to `AppDelegate.m -application:didFinishLaunchingWithOptions:`: - -``` objective-c -[[AFNetworkActivityLogger sharedLogger] startLogging]; -``` - -Now all `AFURLConnectionOperation` and `NSURLSessionTask` objects created by an `AFURLSessionManager` will have their request and response logged to the console, a la: - -``` -GET http://example.com/foo/bar.json -200 http://example.com/foo/bar.json -``` - -If the default logging level is too verbose—say, if you only want to know when requests fail—then changing it is as simple as: - -``` objective-c -[[AFNetworkActivityLogger sharedLogger] setLevel:AFLoggerLevelError]; -``` - -## Contact - -Mattt Thompson - -- http://github.com/mattt -- http://twitter.com/mattt -- m@mattt.me - -## License - -AFNetworkActivityLogger is available under the MIT license. See the LICENSE file for more info. diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/LICENSE b/ios/SAPTracker/src/xcode/Pods/AFNetworking/LICENSE deleted file mode 100644 index 0616192d003..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com/) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/README.md b/ios/SAPTracker/src/xcode/Pods/AFNetworking/README.md deleted file mode 100644 index 13e080c0964..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/README.md +++ /dev/null @@ -1,383 +0,0 @@ -

- AFNetworking -

- -[![Build Status](https://travis-ci.org/AFNetworking/AFNetworking.svg)](https://travis-ci.org/AFNetworking/AFNetworking) - -AFNetworking is a delightful networking library for iOS and Mac OS X. It's built on top of the [Foundation URL Loading System](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/URLLoadingSystem/URLLoadingSystem.html), extending the powerful high-level networking abstractions built into Cocoa. It has a modular architecture with well-designed, feature-rich APIs that are a joy to use. - -Perhaps the most important feature of all, however, is the amazing community of developers who use and contribute to AFNetworking every day. AFNetworking powers some of the most popular and critically-acclaimed apps on the iPhone, iPad, and Mac. - -Choose AFNetworking for your next project, or migrate over your existing projects—you'll be happy you did! - -## How To Get Started - -- [Download AFNetworking](https://github.com/AFNetworking/AFNetworking/archive/master.zip) and try out the included Mac and iPhone example apps -- Read the ["Getting Started" guide](https://github.com/AFNetworking/AFNetworking/wiki/Getting-Started-with-AFNetworking), [FAQ](https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-FAQ), or [other articles on the Wiki](https://github.com/AFNetworking/AFNetworking/wiki) -- Check out the [documentation](http://cocoadocs.org/docsets/AFNetworking/) for a comprehensive look at all of the APIs available in AFNetworking -- Read the [AFNetworking 2.0 Migration Guide](https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-2.0-Migration-Guide) for an overview of the architectural changes from 1.0. - -## Communication - -- If you **need help**, use [Stack Overflow](http://stackoverflow.com/questions/tagged/afnetworking). (Tag 'afnetworking') -- If you'd like to **ask a general question**, use [Stack Overflow](http://stackoverflow.com/questions/tagged/afnetworking). -- If you **found a bug**, _and can provide steps to reliably reproduce it_, open an issue. -- If you **have a feature request**, open an issue. -- If you **want to contribute**, submit a pull request. - -### Installation with CocoaPods - -[CocoaPods](http://cocoapods.org) is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries like AFNetworking in your projects. See the ["Getting Started" guide for more information](https://github.com/AFNetworking/AFNetworking/wiki/Getting-Started-with-AFNetworking). - -#### Podfile - -```ruby -platform :ios, '7.0' -pod "AFNetworking", "~> 2.0" -``` - -## Requirements - -| AFNetworking Version | Minimum iOS Target | Minimum OS X Target | Notes | -|:--------------------:|:---------------------------:|:----------------------------:|:-------------------------------------------------------------------------:| -| 2.x | iOS 6 | OS X 10.8 | Xcode 5 is required. `AFHTTPSessionManager` requires iOS 7 or OS X 10.9. | -| [1.x](https://github.com/AFNetworking/AFNetworking/tree/1.x) | iOS 5 | Mac OS X 10.7 | | -| [0.10.x](https://github.com/AFNetworking/AFNetworking/tree/0.10.x) | iOS 4 | Mac OS X 10.6 | | - -(OS X projects must support [64-bit with modern Cocoa runtime](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtVersionsPlatforms.html)). - -## Architecture - -### NSURLConnection - -- `AFURLConnectionOperation` -- `AFHTTPRequestOperation` -- `AFHTTPRequestOperationManager` - -### NSURLSession _(iOS 7 / Mac OS X 10.9)_ - -- `AFURLSessionManager` -- `AFHTTPSessionManager` - -### Serialization - -* `` - - `AFHTTPRequestSerializer` - - `AFJSONRequestSerializer` - - `AFPropertyListRequestSerializer` -* `` - - `AFHTTPResponseSerializer` - - `AFJSONResponseSerializer` - - `AFXMLParserResponseSerializer` - - `AFXMLDocumentResponseSerializer` _(Mac OS X)_ - - `AFPropertyListResponseSerializer` - - `AFImageResponseSerializer` - - `AFCompoundResponseSerializer` - -### Additional Functionality - -- `AFSecurityPolicy` -- `AFNetworkReachabilityManager` - -## Usage - -### HTTP Request Operation Manager - -`AFHTTPRequestOperationManager` encapsulates the common patterns of communicating with a web application over HTTP, including request creation, response serialization, network reachability monitoring, and security, as well as request operation management. - -#### `GET` Request - -```objective-c -AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; -[manager GET:@"http://example.com/resources.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { - NSLog(@"JSON: %@", responseObject); -} failure:^(AFHTTPRequestOperation *operation, NSError *error) { - NSLog(@"Error: %@", error); -}]; -``` - -#### `POST` URL-Form-Encoded Request - -```objective-c -AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; -NSDictionary *parameters = @{@"foo": @"bar"}; -[manager POST:@"http://example.com/resources.json" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) { - NSLog(@"JSON: %@", responseObject); -} failure:^(AFHTTPRequestOperation *operation, NSError *error) { - NSLog(@"Error: %@", error); -}]; -``` - -#### `POST` Multi-Part Request - -```objective-c -AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; -NSDictionary *parameters = @{@"foo": @"bar"}; -NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"]; -[manager POST:@"http://example.com/resources.json" parameters:parameters constructingBodyWithBlock:^(id formData) { - [formData appendPartWithFileURL:filePath name:@"image" error:nil]; -} success:^(AFHTTPRequestOperation *operation, id responseObject) { - NSLog(@"Success: %@", responseObject); -} failure:^(AFHTTPRequestOperation *operation, NSError *error) { - NSLog(@"Error: %@", error); -}]; -``` - ---- - -### AFURLSessionManager - -`AFURLSessionManager` creates and manages an `NSURLSession` object based on a specified `NSURLSessionConfiguration` object, which conforms to ``, ``, ``, and ``. - -#### Creating a Download Task - -```objective-c -NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; -AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration]; - -NSURL *URL = [NSURL URLWithString:@"http://example.com/download.zip"]; -NSURLRequest *request = [NSURLRequest requestWithURL:URL]; - -NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) { - NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil]; - return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]]; -} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) { - NSLog(@"File downloaded to: %@", filePath); -}]; -[downloadTask resume]; -``` - -#### Creating an Upload Task - -```objective-c -NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; -AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration]; - -NSURL *URL = [NSURL URLWithString:@"http://example.com/upload"]; -NSURLRequest *request = [NSURLRequest requestWithURL:URL]; - -NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"]; -NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath progress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { - if (error) { - NSLog(@"Error: %@", error); - } else { - NSLog(@"Success: %@ %@", response, responseObject); - } -}]; -[uploadTask resume]; -``` - -#### Creating an Upload Task for a Multi-Part Request, with Progress - -```objective-c -NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(id formData) { - [formData appendPartWithFileURL:[NSURL fileURLWithPath:@"file://path/to/image.jpg"] name:@"file" fileName:@"filename.jpg" mimeType:@"image/jpeg" error:nil]; - } error:nil]; - -AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; -NSProgress *progress = nil; - -NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { - if (error) { - NSLog(@"Error: %@", error); - } else { - NSLog(@"%@ %@", response, responseObject); - } -}]; - -[uploadTask resume]; -``` - -#### Creating a Data Task - -```objective-c -NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; -AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration]; - -NSURL *URL = [NSURL URLWithString:@"http://example.com/upload"]; -NSURLRequest *request = [NSURLRequest requestWithURL:URL]; - -NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { - if (error) { - NSLog(@"Error: %@", error); - } else { - NSLog(@"%@ %@", response, responseObject); - } -}]; -[dataTask resume]; -``` - ---- - -### Request Serialization - -Request serializers create requests from URL strings, encoding parameters as either a query string or HTTP body. - -```objective-c -NSString *URLString = @"http://example.com"; -NSDictionary *parameters = @{@"foo": @"bar", @"baz": @[@1, @2, @3]}; -``` - -#### Query String Parameter Encoding - -```objective-c -[[AFHTTPRequestSerializer serializer] requestWithMethod:@"GET" URLString:URLString parameters:parameters error:nil]; -``` - - GET http://example.com?foo=bar&baz[]=1&baz[]=2&baz[]=3 - -#### URL Form Parameter Encoding - -```objective-c -[[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:URLString parameters:parameters]; -``` - - POST http://example.com/ - Content-Type: application/x-www-form-urlencoded - - foo=bar&baz[]=1&baz[]=2&baz[]=3 - -#### JSON Parameter Encoding - -```objective-c -[[AFJSONRequestSerializer serializer] requestWithMethod:@"POST" URLString:URLString parameters:parameters]; -``` - - POST http://example.com/ - Content-Type: application/json - - {"foo": "bar", "baz": [1,2,3]} - ---- - -### Network Reachability Manager - -`AFNetworkReachabilityManager` monitors the reachability of domains, and addresses for both WWAN and WiFi network interfaces. - -#### Shared Network Reachability - -```objective-c -[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { - NSLog(@"Reachability: %@", AFStringFromNetworkReachabilityStatus(status)); -}]; -``` - -#### HTTP Manager Reachability - -```objective-c -NSURL *baseURL = [NSURL URLWithString:@"http://example.com/"]; -AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:baseURL]; - -NSOperationQueue *operationQueue = manager.operationQueue; -[manager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { - switch (status) { - case AFNetworkReachabilityStatusReachableViaWWAN: - case AFNetworkReachabilityStatusReachableViaWiFi: - [operationQueue setSuspended:NO]; - break; - case AFNetworkReachabilityStatusNotReachable: - default: - [operationQueue setSuspended:YES]; - break; - } -}]; - -[manager.reachabilityManager startMonitoring]; -``` - ---- - -### Security Policy - -`AFSecurityPolicy` evaluates server trust against pinned X.509 certificates and public keys over secure connections. - -Adding pinned SSL certificates to your app helps prevent man-in-the-middle attacks and other vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged to route all communication over an HTTPS connection with SSL pinning configured and enabled. - -#### Allowing Invalid SSL Certificates - -```objective-c -AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; -manager.securityPolicy.allowInvalidCertificates = YES; // not recommended for production -``` - ---- - -### AFHTTPRequestOperation - -`AFHTTPRequestOperation` is a subclass of `AFURLConnectionOperation` for requests using the HTTP or HTTPS protocols. It encapsulates the concept of acceptable status codes and content types, which determine the success or failure of a request. - -Although `AFHTTPRequestOperationManager` is usually the best way to go about making requests, `AFHTTPRequestOperation` can be used by itself. - -#### `GET` with `AFHTTPRequestOperation` - -```objective-c -NSURL *URL = [NSURL URLWithString:@"http://example.com/resources/123.json"]; -NSURLRequest *request = [NSURLRequest requestWithURL:URL]; -AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request]; -op.responseSerializer = [AFJSONResponseSerializer serializer]; -[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { - NSLog(@"JSON: %@", responseObject); -} failure:^(AFHTTPRequestOperation *operation, NSError *error) { - NSLog(@"Error: %@", error); -}]; -[[NSOperationQueue mainQueue] addOperation:op]; -``` - -#### Batch of Operations - -```objective-c -NSMutableArray *mutableOperations = [NSMutableArray array]; -for (NSURL *fileURL in filesToUpload) { - NSURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(id formData) { - [formData appendPartWithFileURL:fileURL name:@"images[]" error:nil]; - }]; - - AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; - - [mutableOperations addObject:operation]; -} - -NSArray *operations = [AFURLConnectionOperation batchOfRequestOperations:@[...] progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) { - NSLog(@"%lu of %lu complete", numberOfFinishedOperations, totalNumberOfOperations); -} completionBlock:^(NSArray *operations) { - NSLog(@"All operations in batch complete"); -}]; -[[NSOperationQueue mainQueue] addOperations:operations waitUntilFinished:NO]; -``` - -## Unit Tests - -AFNetworking includes a suite of unit tests within the Tests subdirectory. In order to run the unit tests, you must install the testing dependencies via [CocoaPods](http://cocoapods.org/): - - $ cd Tests - $ pod install - -Once testing dependencies are installed, you can execute the test suite via the 'iOS Tests' and 'OS X Tests' schemes within Xcode. - -### Running Tests from the Command Line - -Tests can also be run from the command line or within a continuous integration environment. The [`xcpretty`](https://github.com/mneorr/xcpretty) utility needs to be installed before running the tests from the command line: - - $ gem install xcpretty - -Once `xcpretty` is installed, you can execute the suite via `rake test`. - -## Credits - -AFNetworking was originally created by [Scott Raymond](https://github.com/sco/) and [Mattt Thompson](https://github.com/mattt/) in the development of [Gowalla for iPhone](http://en.wikipedia.org/wiki/Gowalla). - -AFNetworking's logo was designed by [Alan Defibaugh](http://www.alandefibaugh.com/). - -And most of all, thanks to AFNetworking's [growing list of contributors](https://github.com/AFNetworking/AFNetworking/contributors). - -## Contact - -Follow AFNetworking on Twitter ([@AFNetworking](https://twitter.com/AFNetworking)) - -### Maintainers - -- [Mattt Thompson](http://github.com/mattt) ([@mattt](https://twitter.com/mattt)) - -## License - -AFNetworking is available under the MIT license. See the LICENSE file for more info. diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworkActivityLogger/AFNetworkActivityLogger.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworkActivityLogger/AFNetworkActivityLogger.h deleted file mode 120000 index e0d89901efb..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworkActivityLogger/AFNetworkActivityLogger.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworkActivityLogger/AFNetworkActivityLogger/AFNetworkActivityLogger.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFHTTPRequestOperation.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFHTTPRequestOperation.h deleted file mode 120000 index ac762c82387..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFHTTPRequestOperation.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFHTTPRequestOperation.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFHTTPRequestOperationManager.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFHTTPRequestOperationManager.h deleted file mode 120000 index 9dcc623c638..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFHTTPRequestOperationManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFHTTPRequestOperationManager.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFHTTPSessionManager.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFHTTPSessionManager.h deleted file mode 120000 index 56feb9fb85e..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFHTTPSessionManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFHTTPSessionManager.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFNetworkActivityIndicatorManager.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFNetworkActivityIndicatorManager.h deleted file mode 120000 index 67519d98485..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFNetworkActivityIndicatorManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFNetworkReachabilityManager.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFNetworkReachabilityManager.h deleted file mode 120000 index 68fc7744f28..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFNetworkReachabilityManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFNetworkReachabilityManager.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFNetworking.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFNetworking.h deleted file mode 120000 index a5a38da7dc9..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFNetworking.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFNetworking.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFSecurityPolicy.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFSecurityPolicy.h deleted file mode 120000 index fd1322db9c2..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFSecurityPolicy.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFSecurityPolicy.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFURLConnectionOperation.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFURLConnectionOperation.h deleted file mode 120000 index d9b35fb754f..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFURLConnectionOperation.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFURLConnectionOperation.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFURLRequestSerialization.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFURLRequestSerialization.h deleted file mode 120000 index ca8209b81f9..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFURLRequestSerialization.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFURLRequestSerialization.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFURLResponseSerialization.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFURLResponseSerialization.h deleted file mode 120000 index e36a765d826..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFURLResponseSerialization.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFURLResponseSerialization.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFURLSessionManager.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFURLSessionManager.h deleted file mode 120000 index 835101de7bf..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/AFURLSessionManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFURLSessionManager.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIActivityIndicatorView+AFNetworking.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIActivityIndicatorView+AFNetworking.h deleted file mode 120000 index c534ebfb02a..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIActivityIndicatorView+AFNetworking.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIAlertView+AFNetworking.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIAlertView+AFNetworking.h deleted file mode 120000 index f9928133851..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIAlertView+AFNetworking.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/UIKit+AFNetworking/UIAlertView+AFNetworking.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIButton+AFNetworking.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIButton+AFNetworking.h deleted file mode 120000 index 8f2e221939a..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIButton+AFNetworking.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIImageView+AFNetworking.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIImageView+AFNetworking.h deleted file mode 120000 index a95d67380f1..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIImageView+AFNetworking.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIKit+AFNetworking.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIKit+AFNetworking.h deleted file mode 120000 index 95017cce573..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIKit+AFNetworking.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/UIKit+AFNetworking/UIKit+AFNetworking.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIProgressView+AFNetworking.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIProgressView+AFNetworking.h deleted file mode 120000 index 730b167dcde..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIProgressView+AFNetworking.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/UIKit+AFNetworking/UIProgressView+AFNetworking.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIRefreshControl+AFNetworking.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIRefreshControl+AFNetworking.h deleted file mode 120000 index 8efd8262093..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIRefreshControl+AFNetworking.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIWebView+AFNetworking.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIWebView+AFNetworking.h deleted file mode 120000 index c8df6ef17b8..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/AFNetworking/UIWebView+AFNetworking.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/UIKit+AFNetworking/UIWebView+AFNetworking.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Private/TSMarkdownParser/TSMarkdownParser.h b/ios/SAPTracker/src/xcode/Pods/Headers/Private/TSMarkdownParser/TSMarkdownParser.h deleted file mode 120000 index d68206fa9b1..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Private/TSMarkdownParser/TSMarkdownParser.h +++ /dev/null @@ -1 +0,0 @@ -../../../TSMarkdownParser/TSMarkdownParser/TSMarkdownParser.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworkActivityLogger/AFNetworkActivityLogger.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworkActivityLogger/AFNetworkActivityLogger.h deleted file mode 120000 index e0d89901efb..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworkActivityLogger/AFNetworkActivityLogger.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworkActivityLogger/AFNetworkActivityLogger/AFNetworkActivityLogger.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFHTTPRequestOperation.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFHTTPRequestOperation.h deleted file mode 120000 index ac762c82387..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFHTTPRequestOperation.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFHTTPRequestOperation.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFHTTPRequestOperationManager.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFHTTPRequestOperationManager.h deleted file mode 120000 index 9dcc623c638..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFHTTPRequestOperationManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFHTTPRequestOperationManager.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFHTTPSessionManager.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFHTTPSessionManager.h deleted file mode 120000 index 56feb9fb85e..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFHTTPSessionManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFHTTPSessionManager.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFNetworkActivityIndicatorManager.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFNetworkActivityIndicatorManager.h deleted file mode 120000 index 67519d98485..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFNetworkActivityIndicatorManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFNetworkReachabilityManager.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFNetworkReachabilityManager.h deleted file mode 120000 index 68fc7744f28..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFNetworkReachabilityManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFNetworkReachabilityManager.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFNetworking.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFNetworking.h deleted file mode 120000 index a5a38da7dc9..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFNetworking.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFNetworking.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFSecurityPolicy.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFSecurityPolicy.h deleted file mode 120000 index fd1322db9c2..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFSecurityPolicy.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFSecurityPolicy.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFURLConnectionOperation.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFURLConnectionOperation.h deleted file mode 120000 index d9b35fb754f..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFURLConnectionOperation.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFURLConnectionOperation.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFURLRequestSerialization.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFURLRequestSerialization.h deleted file mode 120000 index ca8209b81f9..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFURLRequestSerialization.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFURLRequestSerialization.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFURLResponseSerialization.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFURLResponseSerialization.h deleted file mode 120000 index e36a765d826..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFURLResponseSerialization.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFURLResponseSerialization.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFURLSessionManager.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFURLSessionManager.h deleted file mode 120000 index 835101de7bf..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/AFURLSessionManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/AFNetworking/AFURLSessionManager.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIActivityIndicatorView+AFNetworking.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIActivityIndicatorView+AFNetworking.h deleted file mode 120000 index c534ebfb02a..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIActivityIndicatorView+AFNetworking.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIAlertView+AFNetworking.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIAlertView+AFNetworking.h deleted file mode 120000 index f9928133851..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIAlertView+AFNetworking.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/UIKit+AFNetworking/UIAlertView+AFNetworking.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIButton+AFNetworking.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIButton+AFNetworking.h deleted file mode 120000 index 8f2e221939a..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIButton+AFNetworking.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIImageView+AFNetworking.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIImageView+AFNetworking.h deleted file mode 120000 index a95d67380f1..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIImageView+AFNetworking.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIKit+AFNetworking.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIKit+AFNetworking.h deleted file mode 120000 index 95017cce573..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIKit+AFNetworking.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/UIKit+AFNetworking/UIKit+AFNetworking.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIProgressView+AFNetworking.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIProgressView+AFNetworking.h deleted file mode 120000 index 730b167dcde..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIProgressView+AFNetworking.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/UIKit+AFNetworking/UIProgressView+AFNetworking.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIRefreshControl+AFNetworking.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIRefreshControl+AFNetworking.h deleted file mode 120000 index 8efd8262093..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIRefreshControl+AFNetworking.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIWebView+AFNetworking.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIWebView+AFNetworking.h deleted file mode 120000 index c8df6ef17b8..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/AFNetworking/UIWebView+AFNetworking.h +++ /dev/null @@ -1 +0,0 @@ -../../../AFNetworking/UIKit+AFNetworking/UIWebView+AFNetworking.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Headers/Public/TSMarkdownParser/TSMarkdownParser.h b/ios/SAPTracker/src/xcode/Pods/Headers/Public/TSMarkdownParser/TSMarkdownParser.h deleted file mode 120000 index d68206fa9b1..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Headers/Public/TSMarkdownParser/TSMarkdownParser.h +++ /dev/null @@ -1 +0,0 @@ -../../../TSMarkdownParser/TSMarkdownParser/TSMarkdownParser.h \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Manifest.lock b/ios/SAPTracker/src/xcode/Pods/Manifest.lock deleted file mode 100644 index 63458c3dd76..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Manifest.lock +++ /dev/null @@ -1,38 +0,0 @@ -PODS: - - AFNetworkActivityLogger (2.0.3): - - AFNetworking/NSURLConnection (~> 2.0) - - AFNetworking/NSURLSession (~> 2.0) - - AFNetworking (2.5.0): - - AFNetworking/NSURLConnection (= 2.5.0) - - AFNetworking/NSURLSession (= 2.5.0) - - AFNetworking/Reachability (= 2.5.0) - - AFNetworking/Security (= 2.5.0) - - AFNetworking/Serialization (= 2.5.0) - - AFNetworking/UIKit (= 2.5.0) - - AFNetworking/NSURLConnection (2.5.0): - - AFNetworking/Reachability - - AFNetworking/Security - - AFNetworking/Serialization - - AFNetworking/NSURLSession (2.5.0): - - AFNetworking/Reachability - - AFNetworking/Security - - AFNetworking/Serialization - - AFNetworking/Reachability (2.5.0) - - AFNetworking/Security (2.5.0) - - AFNetworking/Serialization (2.5.0) - - AFNetworking/UIKit (2.5.0): - - AFNetworking/NSURLConnection - - AFNetworking/NSURLSession - - TSMarkdownParser (1.0.19) - -DEPENDENCIES: - - AFNetworkActivityLogger (= 2.0.3) - - AFNetworking (= 2.5.0) - - TSMarkdownParser - -SPEC CHECKSUMS: - AFNetworkActivityLogger: e82c9ba285b37042d86729bff5b14036c4312cd7 - AFNetworking: 96ac9bf3eda33582701cb1fcc5b896aa1e20311e - TSMarkdownParser: 0341662db14b17a13a79f3ddcb08ab7a4b6ed834 - -COCOAPODS: 0.38.2 diff --git a/ios/SAPTracker/src/xcode/Pods/Pods.xcodeproj/project.pbxproj b/ios/SAPTracker/src/xcode/Pods/Pods.xcodeproj/project.pbxproj deleted file mode 100644 index 03a972f6771..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Pods.xcodeproj/project.pbxproj +++ /dev/null @@ -1,914 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 00F13495CD861FCD285ED03B3E453F3D /* AFSecurityPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A51B0E777D84147A30CC590B977C098 /* AFSecurityPolicy.h */; }; - 02984C4C0CD4412BC46B888055B824C0 /* AFNetworkActivityIndicatorManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 776A15D9FA1F21612BC1B24C2D6A6D80 /* AFNetworkActivityIndicatorManager.h */; }; - 034CD09F7D7B800FED190D27C4DC30E4 /* UIWebView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 11C1015088E7BDAC858957480F69A924 /* UIWebView+AFNetworking.h */; }; - 083F2B6FF4750DA417FEF9EC21BDD5DE /* UIKit+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = EC348771F9FE09AA1191C619677EBADD /* UIKit+AFNetworking.h */; }; - 0CD28007E662894A2F515146ADAD1C1D /* UIButton+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = BA47487E0EE74700871CD6D9CB784A61 /* UIButton+AFNetworking.m */; }; - 1286B74800652B63CBD1243E0BF9B798 /* UIRefreshControl+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 988F67041028AEAE4C0F94C0D78B8771 /* UIRefreshControl+AFNetworking.m */; }; - 159B420BE5492E4CC3D8006F0E06A719 /* AFHTTPSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 06F869B3B2ACCB33F990C680BC60F048 /* AFHTTPSessionManager.m */; }; - 1B03FD45669CC092242861EB821E66E8 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E17C293AFDF4E4489F9CD7E09C06A3E /* MobileCoreServices.framework */; }; - 2CCDB74E04B26C170193439306C720D3 /* AFURLSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 8A940B7048FE0AB37E2375B5F6B59204 /* AFURLSessionManager.h */; }; - 38284C85FF5D6DEF5F23F9FD28F4B9EE /* AFURLRequestSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E16ABCA7D50F6CBBF64291269E82AE0 /* AFURLRequestSerialization.h */; }; - 3CC69282952C9B3C725BBCF377175570 /* AFNetworkActivityLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 73B81DD02D8B4CBE9C55433D5875FF58 /* AFNetworkActivityLogger.m */; }; - 3FBB2764BE67089028A61AB6C0E4D149 /* AFHTTPSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DCE01749587787B900515FEA48A541F3 /* AFHTTPSessionManager.h */; }; - 44846D154FC64637F5A8F146476221E8 /* UIButton+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = BA1EF8C0123FE26932E1D5C42C7A5CAA /* UIButton+AFNetworking.h */; }; - 4A9C4A2D5ECE963C44FDF53346B00572 /* AFNetworkActivityIndicatorManager.m in Sources */ = {isa = PBXBuildFile; fileRef = CBF5D5B41D71CB61161C39BC99A60BC0 /* AFNetworkActivityIndicatorManager.m */; }; - 4E091D90D19EC0B2E31A4C0A8DC6772D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC380E16B4B8B8B9A2AC5FC315D99FDC /* Foundation.framework */; }; - 4E9746934EF8633DD91BCD8A58F738B6 /* UIImageView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = AE939388615602DF7186BBCCC3950D0B /* UIImageView+AFNetworking.m */; }; - 50E2159204533918B5DEB3B70F8A89CC /* UIImageView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = D5E4A1F6E9E0E4D08B0385E745124193 /* UIImageView+AFNetworking.h */; }; - 533266707157930927F93B897D81807E /* AFURLRequestSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C88506C685A529E046542CFF0F82EA4 /* AFURLRequestSerialization.m */; }; - 5491D87237F6FCE5EF29360C32D266A6 /* UIActivityIndicatorView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AA745221382962C53E3878BAA53DA12 /* UIActivityIndicatorView+AFNetworking.m */; }; - 574E9B6B983972CE053CF24ADFD3C1D0 /* AFNetworkActivityLogger-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 998B00977C5A96D7F85AF6F797D33943 /* AFNetworkActivityLogger-dummy.m */; }; - 5849816D84E150DDC6BDDCB453818F23 /* TSMarkdownParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D5B9AEA428709F1C2E72D1752706DB1 /* TSMarkdownParser.m */; }; - 588CE6FD74211863EA95B062C9CB2D63 /* AFSecurityPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E40E3D855E2223264351C9CB49E55E1 /* AFSecurityPolicy.m */; }; - 5938800C4F2A3F6D69121DE034CC117E /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C0F5C68503E7B455936B87A5F2EE0E6 /* SystemConfiguration.framework */; }; - 5AE1B753420C9388AE411DD106B53C94 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B14767DC13CF5AE11E2289E2CB186192 /* CoreGraphics.framework */; }; - 63C4E9C965C32D38AF1FA0272CD99B8C /* AFURLConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DAA32BE3D3E1D59923F407C254E87F8F /* AFURLConnectionOperation.m */; }; - 6CDB3CD003FB78DBEF0BDFEDE8448CC4 /* TSMarkdownParser-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FE4778983A4CD72385DE39DB6F448F6 /* TSMarkdownParser-dummy.m */; }; - 7312E43A0FCEB0E0E1DDF33D8CA398C6 /* AFHTTPRequestOperationManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 83F228A7EDE4620305BE083CFA47C914 /* AFHTTPRequestOperationManager.h */; }; - 757CCBAFFC3CA37DEF7CAD82FEC9881E /* AFNetworkReachabilityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 155ED84A2C45CC606D8951996DCACE14 /* AFNetworkReachabilityManager.m */; }; - 7ABBB64B29140FEEF220AC3BC4F5C1D5 /* TSMarkdownParser.h in Headers */ = {isa = PBXBuildFile; fileRef = FAB97E4DF501809ACB777A55826B6F94 /* TSMarkdownParser.h */; }; - 7BC7921A4B33DA4DA64FDC9CC0F4D03B /* AFURLResponseSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = 818678E7E08DB47ABF205CE3A01756D3 /* AFURLResponseSerialization.h */; }; - 7D6D4EBA11FD60DCF0099244A4CA95FB /* UIActivityIndicatorView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = F9576F1E09576E83BB440F0336DAFBC8 /* UIActivityIndicatorView+AFNetworking.h */; }; - 81C301899C854FBB0A4FA2EFEDDCAA93 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC380E16B4B8B8B9A2AC5FC315D99FDC /* Foundation.framework */; }; - 8A27CCEA2AA61F3920D4A7CCB19F3424 /* Pods-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = C77E133EB29FE86050E4454168E7CDE6 /* Pods-dummy.m */; }; - 8E248334A1449C01D2B8F0C606EC547A /* AFHTTPRequestOperationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = EF1BA51CF5D9D2B9FDBA9F0C1F6A7264 /* AFHTTPRequestOperationManager.m */; }; - 916785CBEAE06783DBE8239BBC321D90 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC380E16B4B8B8B9A2AC5FC315D99FDC /* Foundation.framework */; }; - A60720ED530A32B72BF5BF6B1DBADD59 /* UIProgressView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 2339B3D0B69E6169B83362FC1E27E1B3 /* UIProgressView+AFNetworking.m */; }; - ADA5DCF5E4169B10AC6FB9D1CF52DC62 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 314C2B6C8D9C85B4B775C11AB43F5F51 /* UIKit.framework */; }; - B45A92D04B1EE449F6DF1FCFA9CB50AE /* UIAlertView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 806EDF7627B8C4D36E59AABA639E7C85 /* UIAlertView+AFNetworking.m */; }; - C08CC812BAA0989E9D8C48D29796E4E1 /* UIProgressView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 952AC86441B39C595715618AEC7B1369 /* UIProgressView+AFNetworking.h */; }; - C6633ABCC67F40C255A214136B72D438 /* AFHTTPRequestOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F5ABD55EF86E50C30535BAAD622396A /* AFHTTPRequestOperation.h */; }; - C7600E8DF244EA947C7693871920BA9A /* AFURLResponseSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 1544BD4F0C13C1C6E3F1AFCF3359B477 /* AFURLResponseSerialization.m */; }; - CB240B0C1B04A411B41499740D34B5B0 /* AFNetworkActivityLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = A3694B8E6DE3A9529170C2396475BC86 /* AFNetworkActivityLogger.h */; }; - DA3A309CC6E2E80D787987586B4FFEF6 /* AFURLSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = D33A7DD91D4459BC38E750527C5220B0 /* AFURLSessionManager.m */; }; - DB3CF9067FC4B8A4DB7DFECE3637B6DB /* AFURLConnectionOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 9087F7E86AA9E79B2AAD711E7B1E474C /* AFURLConnectionOperation.h */; }; - DC6A79F26EB1F8B33D893F5B03D12170 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D289C8C86FE0C9AE5CA772A2DBBF7A44 /* Security.framework */; }; - DCF8771B43F8F84442301D5960E30596 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC380E16B4B8B8B9A2AC5FC315D99FDC /* Foundation.framework */; }; - DDD6540F004FDC3F73163A31EC2EBFBC /* AFHTTPRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 986C07AADC26F84A66B4C03C16A82393 /* AFHTTPRequestOperation.m */; }; - E24A8F45990EADF7EB386E7C94080BB7 /* UIRefreshControl+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 546C1E890FED0FC20610A57F64113C86 /* UIRefreshControl+AFNetworking.h */; }; - E53C3B5F86CC8DD383EA4CC0FBA62B20 /* AFNetworkReachabilityManager.h in Headers */ = {isa = PBXBuildFile; fileRef = FC5B477D3431C39FF5629DC3A5FF3840 /* AFNetworkReachabilityManager.h */; }; - EF51F9344D2A953023A43BC00D179DA5 /* UIWebView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = B24A14B53F4FF4DCD48740B0E6120076 /* UIWebView+AFNetworking.m */; }; - F675988B5E38BF8C3CF0B2DB82D3EF88 /* UIAlertView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 4636B7327EE93D7D3596B91CE5A4F68B /* UIAlertView+AFNetworking.h */; }; - F7F5A6BDF29E914CBD8621A7381ED135 /* AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 7F71E3C3265BBB3BB525F4376E29679D /* AFNetworking.h */; }; - F91AEB50CAFAF0F5A3A3FB925F4DB96D /* AFNetworking-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 60DA9BE644C6406CDEC906B8E271CFEE /* AFNetworking-dummy.m */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 2849BC3222B5A4D1199A9B545FFCC92C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6284F0103A037A696FD0DD07686DE3CC; - remoteInfo = AFNetworkActivityLogger; - }; - 4C85286F7BE90E21085832AF40AAF346 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 5B18F572B65064722F49430CF2C153E8; - remoteInfo = TSMarkdownParser; - }; - 617CE06CA3460BB2CEA4DED51AEBFE64 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = F507FD4523B5E687F5E813CC23EC3689; - remoteInfo = AFNetworking; - }; - A386CA56B33F1618BEB031D4C819477D /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; - proxyType = 1; - remoteGlobalIDString = F507FD4523B5E687F5E813CC23EC3689; - remoteInfo = AFNetworking; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 01537CE1AB6B089C165D3DC4D1BC73C4 /* AFNetworking-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "AFNetworking-prefix.pch"; sourceTree = ""; }; - 06F869B3B2ACCB33F990C680BC60F048 /* AFHTTPSessionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFHTTPSessionManager.m; path = AFNetworking/AFHTTPSessionManager.m; sourceTree = ""; }; - 0A51B0E777D84147A30CC590B977C098 /* AFSecurityPolicy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFSecurityPolicy.h; path = AFNetworking/AFSecurityPolicy.h; sourceTree = ""; }; - 0A63E4CBF251757E251BDE1E6462BB94 /* TSMarkdownParser.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = TSMarkdownParser.xcconfig; sourceTree = ""; }; - 0DA8CD5475181D88BBDED6CC24B76B43 /* AFNetworkActivityLogger-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "AFNetworkActivityLogger-prefix.pch"; sourceTree = ""; }; - 0E6F0DFC51C35FED1EB27952544D6A0F /* AFNetworkActivityLogger-Private.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "AFNetworkActivityLogger-Private.xcconfig"; sourceTree = ""; }; - 11C1015088E7BDAC858957480F69A924 /* UIWebView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIWebView+AFNetworking.h"; path = "UIKit+AFNetworking/UIWebView+AFNetworking.h"; sourceTree = ""; }; - 1544BD4F0C13C1C6E3F1AFCF3359B477 /* AFURLResponseSerialization.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLResponseSerialization.m; path = AFNetworking/AFURLResponseSerialization.m; sourceTree = ""; }; - 155ED84A2C45CC606D8951996DCACE14 /* AFNetworkReachabilityManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFNetworkReachabilityManager.m; path = AFNetworking/AFNetworkReachabilityManager.m; sourceTree = ""; }; - 15A529C27057E4A57D259CBC6E6CE49C /* Pods-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-acknowledgements.markdown"; sourceTree = ""; }; - 1FB4C73FB1FCF1EF3D4140A0073F0AF7 /* AFNetworking-Private.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "AFNetworking-Private.xcconfig"; sourceTree = ""; }; - 1FE4778983A4CD72385DE39DB6F448F6 /* TSMarkdownParser-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "TSMarkdownParser-dummy.m"; sourceTree = ""; }; - 2339B3D0B69E6169B83362FC1E27E1B3 /* UIProgressView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIProgressView+AFNetworking.m"; path = "UIKit+AFNetworking/UIProgressView+AFNetworking.m"; sourceTree = ""; }; - 2AB098EE24DE871CEBF37C9966048792 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Pods.release.xcconfig; sourceTree = ""; }; - 2E17C293AFDF4E4489F9CD7E09C06A3E /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.3.sdk/System/Library/Frameworks/MobileCoreServices.framework; sourceTree = DEVELOPER_DIR; }; - 314C2B6C8D9C85B4B775C11AB43F5F51 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.3.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; - 3D5B9AEA428709F1C2E72D1752706DB1 /* TSMarkdownParser.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = TSMarkdownParser.m; path = TSMarkdownParser/TSMarkdownParser.m; sourceTree = ""; }; - 4636B7327EE93D7D3596B91CE5A4F68B /* UIAlertView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIAlertView+AFNetworking.h"; path = "UIKit+AFNetworking/UIAlertView+AFNetworking.h"; sourceTree = ""; }; - 5194A779FF11E324E407B128100CD1CA /* TSMarkdownParser-Private.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "TSMarkdownParser-Private.xcconfig"; sourceTree = ""; }; - 546C1E890FED0FC20610A57F64113C86 /* UIRefreshControl+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIRefreshControl+AFNetworking.h"; path = "UIKit+AFNetworking/UIRefreshControl+AFNetworking.h"; sourceTree = ""; }; - 5C88506C685A529E046542CFF0F82EA4 /* AFURLRequestSerialization.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLRequestSerialization.m; path = AFNetworking/AFURLRequestSerialization.m; sourceTree = ""; }; - 60DA9BE644C6406CDEC906B8E271CFEE /* AFNetworking-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "AFNetworking-dummy.m"; sourceTree = ""; }; - 641AE05DD55E5E6AC1590CD7B4A18F97 /* Pods-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-resources.sh"; sourceTree = ""; }; - 6E40E3D855E2223264351C9CB49E55E1 /* AFSecurityPolicy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFSecurityPolicy.m; path = AFNetworking/AFSecurityPolicy.m; sourceTree = ""; }; - 73B81DD02D8B4CBE9C55433D5875FF58 /* AFNetworkActivityLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFNetworkActivityLogger.m; path = AFNetworkActivityLogger/AFNetworkActivityLogger.m; sourceTree = ""; }; - 776A15D9FA1F21612BC1B24C2D6A6D80 /* AFNetworkActivityIndicatorManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworkActivityIndicatorManager.h; path = "UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h"; sourceTree = ""; }; - 7F71E3C3265BBB3BB525F4376E29679D /* AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworking.h; path = AFNetworking/AFNetworking.h; sourceTree = ""; }; - 7FBF055A5C18DA41BAA151F0A729FC08 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Pods.debug.xcconfig; sourceTree = ""; }; - 806EDF7627B8C4D36E59AABA639E7C85 /* UIAlertView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIAlertView+AFNetworking.m"; path = "UIKit+AFNetworking/UIAlertView+AFNetworking.m"; sourceTree = ""; }; - 818678E7E08DB47ABF205CE3A01756D3 /* AFURLResponseSerialization.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLResponseSerialization.h; path = AFNetworking/AFURLResponseSerialization.h; sourceTree = ""; }; - 83F228A7EDE4620305BE083CFA47C914 /* AFHTTPRequestOperationManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFHTTPRequestOperationManager.h; path = AFNetworking/AFHTTPRequestOperationManager.h; sourceTree = ""; }; - 8A940B7048FE0AB37E2375B5F6B59204 /* AFURLSessionManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLSessionManager.h; path = AFNetworking/AFURLSessionManager.h; sourceTree = ""; }; - 8FC739D532E373E38AFCF317DFA76500 /* libTSMarkdownParser.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTSMarkdownParser.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 9087F7E86AA9E79B2AAD711E7B1E474C /* AFURLConnectionOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLConnectionOperation.h; path = AFNetworking/AFURLConnectionOperation.h; sourceTree = ""; }; - 952AC86441B39C595715618AEC7B1369 /* UIProgressView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIProgressView+AFNetworking.h"; path = "UIKit+AFNetworking/UIProgressView+AFNetworking.h"; sourceTree = ""; }; - 986C07AADC26F84A66B4C03C16A82393 /* AFHTTPRequestOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFHTTPRequestOperation.m; path = AFNetworking/AFHTTPRequestOperation.m; sourceTree = ""; }; - 988F67041028AEAE4C0F94C0D78B8771 /* UIRefreshControl+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIRefreshControl+AFNetworking.m"; path = "UIKit+AFNetworking/UIRefreshControl+AFNetworking.m"; sourceTree = ""; }; - 998B00977C5A96D7F85AF6F797D33943 /* AFNetworkActivityLogger-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "AFNetworkActivityLogger-dummy.m"; sourceTree = ""; }; - 9AA745221382962C53E3878BAA53DA12 /* UIActivityIndicatorView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIActivityIndicatorView+AFNetworking.m"; path = "UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m"; sourceTree = ""; }; - 9C0F5C68503E7B455936B87A5F2EE0E6 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.3.sdk/System/Library/Frameworks/SystemConfiguration.framework; sourceTree = DEVELOPER_DIR; }; - 9E16ABCA7D50F6CBBF64291269E82AE0 /* AFURLRequestSerialization.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLRequestSerialization.h; path = AFNetworking/AFURLRequestSerialization.h; sourceTree = ""; }; - 9F5ABD55EF86E50C30535BAAD622396A /* AFHTTPRequestOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFHTTPRequestOperation.h; path = AFNetworking/AFHTTPRequestOperation.h; sourceTree = ""; }; - A3694B8E6DE3A9529170C2396475BC86 /* AFNetworkActivityLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworkActivityLogger.h; path = AFNetworkActivityLogger/AFNetworkActivityLogger.h; sourceTree = ""; }; - AE939388615602DF7186BBCCC3950D0B /* UIImageView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+AFNetworking.m"; path = "UIKit+AFNetworking/UIImageView+AFNetworking.m"; sourceTree = ""; }; - B14767DC13CF5AE11E2289E2CB186192 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.3.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; }; - B24A14B53F4FF4DCD48740B0E6120076 /* UIWebView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIWebView+AFNetworking.m"; path = "UIKit+AFNetworking/UIWebView+AFNetworking.m"; sourceTree = ""; }; - BA1EF8C0123FE26932E1D5C42C7A5CAA /* UIButton+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIButton+AFNetworking.h"; path = "UIKit+AFNetworking/UIButton+AFNetworking.h"; sourceTree = ""; }; - BA47487E0EE74700871CD6D9CB784A61 /* UIButton+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIButton+AFNetworking.m"; path = "UIKit+AFNetworking/UIButton+AFNetworking.m"; sourceTree = ""; }; - BA6428E9F66FD5A23C0A2E06ED26CD2F /* Podfile */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - BF59BC15D23E1E1912C8F334E7236813 /* Pods-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-acknowledgements.plist"; sourceTree = ""; }; - C76239D7B9BE1AB3129DFF0F8F9D8173 /* AFNetworking.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = AFNetworking.xcconfig; sourceTree = ""; }; - C77E133EB29FE86050E4454168E7CDE6 /* Pods-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-dummy.m"; sourceTree = ""; }; - CBF5D5B41D71CB61161C39BC99A60BC0 /* AFNetworkActivityIndicatorManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFNetworkActivityIndicatorManager.m; path = "UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m"; sourceTree = ""; }; - D289C8C86FE0C9AE5CA772A2DBBF7A44 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.3.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; - D33A7DD91D4459BC38E750527C5220B0 /* AFURLSessionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLSessionManager.m; path = AFNetworking/AFURLSessionManager.m; sourceTree = ""; }; - D5E4A1F6E9E0E4D08B0385E745124193 /* UIImageView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+AFNetworking.h"; path = "UIKit+AFNetworking/UIImageView+AFNetworking.h"; sourceTree = ""; }; - DAA32BE3D3E1D59923F407C254E87F8F /* AFURLConnectionOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLConnectionOperation.m; path = AFNetworking/AFURLConnectionOperation.m; sourceTree = ""; }; - DC380E16B4B8B8B9A2AC5FC315D99FDC /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - DCE01749587787B900515FEA48A541F3 /* AFHTTPSessionManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFHTTPSessionManager.h; path = AFNetworking/AFHTTPSessionManager.h; sourceTree = ""; }; - DF38413643856D1477B39193D7328E2C /* AFNetworkActivityLogger.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = AFNetworkActivityLogger.xcconfig; sourceTree = ""; }; - E92816EA757C971CEDA692EE3FC8FA5A /* libAFNetworking.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libAFNetworking.a; sourceTree = BUILT_PRODUCTS_DIR; }; - EC348771F9FE09AA1191C619677EBADD /* UIKit+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIKit+AFNetworking.h"; path = "UIKit+AFNetworking/UIKit+AFNetworking.h"; sourceTree = ""; }; - EE0F37D5AE588125871C50E34CF995E7 /* libAFNetworkActivityLogger.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libAFNetworkActivityLogger.a; sourceTree = BUILT_PRODUCTS_DIR; }; - EF1BA51CF5D9D2B9FDBA9F0C1F6A7264 /* AFHTTPRequestOperationManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFHTTPRequestOperationManager.m; path = AFNetworking/AFHTTPRequestOperationManager.m; sourceTree = ""; }; - F3139D6AE8D5D85215C7024D946702C4 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; - F939B1F8F3049868EDD58F90C3C17B8F /* TSMarkdownParser-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "TSMarkdownParser-prefix.pch"; sourceTree = ""; }; - F9576F1E09576E83BB440F0336DAFBC8 /* UIActivityIndicatorView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIActivityIndicatorView+AFNetworking.h"; path = "UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h"; sourceTree = ""; }; - FAB97E4DF501809ACB777A55826B6F94 /* TSMarkdownParser.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = TSMarkdownParser.h; path = TSMarkdownParser/TSMarkdownParser.h; sourceTree = ""; }; - FC5B477D3431C39FF5629DC3A5FF3840 /* AFNetworkReachabilityManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworkReachabilityManager.h; path = AFNetworking/AFNetworkReachabilityManager.h; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 01A2B80EFFB21CABBFEF07675CE56B8B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 81C301899C854FBB0A4FA2EFEDDCAA93 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 555214CCCECBC5ACB2F286016160F1D6 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - DCF8771B43F8F84442301D5960E30596 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 6C9560EAE0B0CDED0CBB7A55BC95132C /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 5AE1B753420C9388AE411DD106B53C94 /* CoreGraphics.framework in Frameworks */, - 4E091D90D19EC0B2E31A4C0A8DC6772D /* Foundation.framework in Frameworks */, - 1B03FD45669CC092242861EB821E66E8 /* MobileCoreServices.framework in Frameworks */, - DC6A79F26EB1F8B33D893F5B03D12170 /* Security.framework in Frameworks */, - 5938800C4F2A3F6D69121DE034CC117E /* SystemConfiguration.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - D009DECF132F655B97C0D78FF8212AB2 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 916785CBEAE06783DBE8239BBC321D90 /* Foundation.framework in Frameworks */, - ADA5DCF5E4169B10AC6FB9D1CF52DC62 /* UIKit.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 08F3F35DF065DE922C5525E925D30360 /* Support Files */ = { - isa = PBXGroup; - children = ( - 0A63E4CBF251757E251BDE1E6462BB94 /* TSMarkdownParser.xcconfig */, - 5194A779FF11E324E407B128100CD1CA /* TSMarkdownParser-Private.xcconfig */, - 1FE4778983A4CD72385DE39DB6F448F6 /* TSMarkdownParser-dummy.m */, - F939B1F8F3049868EDD58F90C3C17B8F /* TSMarkdownParser-prefix.pch */, - ); - name = "Support Files"; - path = "../Target Support Files/TSMarkdownParser"; - sourceTree = ""; - }; - 0F75DF6C7C5F002280EC53F48E80B587 /* Frameworks */ = { - isa = PBXGroup; - children = ( - DC3C9AFE6BE4B17F9949D74C04D9458C /* iOS */, - ); - name = Frameworks; - sourceTree = ""; - }; - 26C552B86B17F5437DB92E8FEB20AE24 /* Security */ = { - isa = PBXGroup; - children = ( - 0A51B0E777D84147A30CC590B977C098 /* AFSecurityPolicy.h */, - 6E40E3D855E2223264351C9CB49E55E1 /* AFSecurityPolicy.m */, - ); - name = Security; - sourceTree = ""; - }; - 6D60C3B5518ACDB5E0D95EC23B44BCA9 /* UIKit */ = { - isa = PBXGroup; - children = ( - 776A15D9FA1F21612BC1B24C2D6A6D80 /* AFNetworkActivityIndicatorManager.h */, - CBF5D5B41D71CB61161C39BC99A60BC0 /* AFNetworkActivityIndicatorManager.m */, - F9576F1E09576E83BB440F0336DAFBC8 /* UIActivityIndicatorView+AFNetworking.h */, - 9AA745221382962C53E3878BAA53DA12 /* UIActivityIndicatorView+AFNetworking.m */, - 4636B7327EE93D7D3596B91CE5A4F68B /* UIAlertView+AFNetworking.h */, - 806EDF7627B8C4D36E59AABA639E7C85 /* UIAlertView+AFNetworking.m */, - BA1EF8C0123FE26932E1D5C42C7A5CAA /* UIButton+AFNetworking.h */, - BA47487E0EE74700871CD6D9CB784A61 /* UIButton+AFNetworking.m */, - D5E4A1F6E9E0E4D08B0385E745124193 /* UIImageView+AFNetworking.h */, - AE939388615602DF7186BBCCC3950D0B /* UIImageView+AFNetworking.m */, - EC348771F9FE09AA1191C619677EBADD /* UIKit+AFNetworking.h */, - 952AC86441B39C595715618AEC7B1369 /* UIProgressView+AFNetworking.h */, - 2339B3D0B69E6169B83362FC1E27E1B3 /* UIProgressView+AFNetworking.m */, - 546C1E890FED0FC20610A57F64113C86 /* UIRefreshControl+AFNetworking.h */, - 988F67041028AEAE4C0F94C0D78B8771 /* UIRefreshControl+AFNetworking.m */, - 11C1015088E7BDAC858957480F69A924 /* UIWebView+AFNetworking.h */, - B24A14B53F4FF4DCD48740B0E6120076 /* UIWebView+AFNetworking.m */, - ); - name = UIKit; - sourceTree = ""; - }; - 7DB346D0F39D3F0E887471402A8071AB = { - isa = PBXGroup; - children = ( - BA6428E9F66FD5A23C0A2E06ED26CD2F /* Podfile */, - 0F75DF6C7C5F002280EC53F48E80B587 /* Frameworks */, - B36D0922A45901051C8ECCE7C54764C1 /* Pods */, - CCA510CFBEA2D207524CDA0D73C3B561 /* Products */, - D2411A5FE7F7A004607BED49990C37F4 /* Targets Support Files */, - ); - sourceTree = ""; - }; - 8A8B11C17BC7D50F469147B2D1185662 /* Serialization */ = { - isa = PBXGroup; - children = ( - 9E16ABCA7D50F6CBBF64291269E82AE0 /* AFURLRequestSerialization.h */, - 5C88506C685A529E046542CFF0F82EA4 /* AFURLRequestSerialization.m */, - 818678E7E08DB47ABF205CE3A01756D3 /* AFURLResponseSerialization.h */, - 1544BD4F0C13C1C6E3F1AFCF3359B477 /* AFURLResponseSerialization.m */, - ); - name = Serialization; - sourceTree = ""; - }; - 901F4C6B9C825A7AE5597F8DF51398D4 /* TSMarkdownParser */ = { - isa = PBXGroup; - children = ( - FAB97E4DF501809ACB777A55826B6F94 /* TSMarkdownParser.h */, - 3D5B9AEA428709F1C2E72D1752706DB1 /* TSMarkdownParser.m */, - 08F3F35DF065DE922C5525E925D30360 /* Support Files */, - ); - path = TSMarkdownParser; - sourceTree = ""; - }; - 952EEBFAF8F7E620423C9F156F25A506 /* Pods */ = { - isa = PBXGroup; - children = ( - 15A529C27057E4A57D259CBC6E6CE49C /* Pods-acknowledgements.markdown */, - BF59BC15D23E1E1912C8F334E7236813 /* Pods-acknowledgements.plist */, - C77E133EB29FE86050E4454168E7CDE6 /* Pods-dummy.m */, - 641AE05DD55E5E6AC1590CD7B4A18F97 /* Pods-resources.sh */, - 7FBF055A5C18DA41BAA151F0A729FC08 /* Pods.debug.xcconfig */, - 2AB098EE24DE871CEBF37C9966048792 /* Pods.release.xcconfig */, - ); - name = Pods; - path = "Target Support Files/Pods"; - sourceTree = ""; - }; - A89DBDCF06515E8004DD9CBDA87FA8EC /* Support Files */ = { - isa = PBXGroup; - children = ( - DF38413643856D1477B39193D7328E2C /* AFNetworkActivityLogger.xcconfig */, - 0E6F0DFC51C35FED1EB27952544D6A0F /* AFNetworkActivityLogger-Private.xcconfig */, - 998B00977C5A96D7F85AF6F797D33943 /* AFNetworkActivityLogger-dummy.m */, - 0DA8CD5475181D88BBDED6CC24B76B43 /* AFNetworkActivityLogger-prefix.pch */, - ); - name = "Support Files"; - path = "../Target Support Files/AFNetworkActivityLogger"; - sourceTree = ""; - }; - B36D0922A45901051C8ECCE7C54764C1 /* Pods */ = { - isa = PBXGroup; - children = ( - F3724A97A55DB9899A7BC23F730B7098 /* AFNetworkActivityLogger */, - DB7BFDBE47709136B0C5A67566E49861 /* AFNetworking */, - 901F4C6B9C825A7AE5597F8DF51398D4 /* TSMarkdownParser */, - ); - name = Pods; - sourceTree = ""; - }; - BFB8009D15A06C68C8766911C26E8696 /* Reachability */ = { - isa = PBXGroup; - children = ( - FC5B477D3431C39FF5629DC3A5FF3840 /* AFNetworkReachabilityManager.h */, - 155ED84A2C45CC606D8951996DCACE14 /* AFNetworkReachabilityManager.m */, - ); - name = Reachability; - sourceTree = ""; - }; - C1C4B5C2A54E69587297450DF440938A /* Support Files */ = { - isa = PBXGroup; - children = ( - C76239D7B9BE1AB3129DFF0F8F9D8173 /* AFNetworking.xcconfig */, - 1FB4C73FB1FCF1EF3D4140A0073F0AF7 /* AFNetworking-Private.xcconfig */, - 60DA9BE644C6406CDEC906B8E271CFEE /* AFNetworking-dummy.m */, - 01537CE1AB6B089C165D3DC4D1BC73C4 /* AFNetworking-prefix.pch */, - ); - name = "Support Files"; - path = "../Target Support Files/AFNetworking"; - sourceTree = ""; - }; - C23C656451378D3EB609D045656C42C7 /* NSURLConnection */ = { - isa = PBXGroup; - children = ( - 9F5ABD55EF86E50C30535BAAD622396A /* AFHTTPRequestOperation.h */, - 986C07AADC26F84A66B4C03C16A82393 /* AFHTTPRequestOperation.m */, - 83F228A7EDE4620305BE083CFA47C914 /* AFHTTPRequestOperationManager.h */, - EF1BA51CF5D9D2B9FDBA9F0C1F6A7264 /* AFHTTPRequestOperationManager.m */, - 9087F7E86AA9E79B2AAD711E7B1E474C /* AFURLConnectionOperation.h */, - DAA32BE3D3E1D59923F407C254E87F8F /* AFURLConnectionOperation.m */, - ); - name = NSURLConnection; - sourceTree = ""; - }; - CCA510CFBEA2D207524CDA0D73C3B561 /* Products */ = { - isa = PBXGroup; - children = ( - EE0F37D5AE588125871C50E34CF995E7 /* libAFNetworkActivityLogger.a */, - E92816EA757C971CEDA692EE3FC8FA5A /* libAFNetworking.a */, - F3139D6AE8D5D85215C7024D946702C4 /* libPods.a */, - 8FC739D532E373E38AFCF317DFA76500 /* libTSMarkdownParser.a */, - ); - name = Products; - sourceTree = ""; - }; - CEDE19D88035E8360E9EB27A37D1E5E4 /* NSURLSession */ = { - isa = PBXGroup; - children = ( - DCE01749587787B900515FEA48A541F3 /* AFHTTPSessionManager.h */, - 06F869B3B2ACCB33F990C680BC60F048 /* AFHTTPSessionManager.m */, - 8A940B7048FE0AB37E2375B5F6B59204 /* AFURLSessionManager.h */, - D33A7DD91D4459BC38E750527C5220B0 /* AFURLSessionManager.m */, - ); - name = NSURLSession; - sourceTree = ""; - }; - D2411A5FE7F7A004607BED49990C37F4 /* Targets Support Files */ = { - isa = PBXGroup; - children = ( - 952EEBFAF8F7E620423C9F156F25A506 /* Pods */, - ); - name = "Targets Support Files"; - sourceTree = ""; - }; - DB7BFDBE47709136B0C5A67566E49861 /* AFNetworking */ = { - isa = PBXGroup; - children = ( - 7F71E3C3265BBB3BB525F4376E29679D /* AFNetworking.h */, - C23C656451378D3EB609D045656C42C7 /* NSURLConnection */, - CEDE19D88035E8360E9EB27A37D1E5E4 /* NSURLSession */, - BFB8009D15A06C68C8766911C26E8696 /* Reachability */, - 26C552B86B17F5437DB92E8FEB20AE24 /* Security */, - 8A8B11C17BC7D50F469147B2D1185662 /* Serialization */, - C1C4B5C2A54E69587297450DF440938A /* Support Files */, - 6D60C3B5518ACDB5E0D95EC23B44BCA9 /* UIKit */, - ); - path = AFNetworking; - sourceTree = ""; - }; - DC3C9AFE6BE4B17F9949D74C04D9458C /* iOS */ = { - isa = PBXGroup; - children = ( - B14767DC13CF5AE11E2289E2CB186192 /* CoreGraphics.framework */, - DC380E16B4B8B8B9A2AC5FC315D99FDC /* Foundation.framework */, - 2E17C293AFDF4E4489F9CD7E09C06A3E /* MobileCoreServices.framework */, - D289C8C86FE0C9AE5CA772A2DBBF7A44 /* Security.framework */, - 9C0F5C68503E7B455936B87A5F2EE0E6 /* SystemConfiguration.framework */, - 314C2B6C8D9C85B4B775C11AB43F5F51 /* UIKit.framework */, - ); - name = iOS; - sourceTree = ""; - }; - F3724A97A55DB9899A7BC23F730B7098 /* AFNetworkActivityLogger */ = { - isa = PBXGroup; - children = ( - A3694B8E6DE3A9529170C2396475BC86 /* AFNetworkActivityLogger.h */, - 73B81DD02D8B4CBE9C55433D5875FF58 /* AFNetworkActivityLogger.m */, - A89DBDCF06515E8004DD9CBDA87FA8EC /* Support Files */, - ); - path = AFNetworkActivityLogger; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 032985B600EFD9B51BE880B5758572DB /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - C6633ABCC67F40C255A214136B72D438 /* AFHTTPRequestOperation.h in Headers */, - 7312E43A0FCEB0E0E1DDF33D8CA398C6 /* AFHTTPRequestOperationManager.h in Headers */, - 3FBB2764BE67089028A61AB6C0E4D149 /* AFHTTPSessionManager.h in Headers */, - 02984C4C0CD4412BC46B888055B824C0 /* AFNetworkActivityIndicatorManager.h in Headers */, - E53C3B5F86CC8DD383EA4CC0FBA62B20 /* AFNetworkReachabilityManager.h in Headers */, - F7F5A6BDF29E914CBD8621A7381ED135 /* AFNetworking.h in Headers */, - 00F13495CD861FCD285ED03B3E453F3D /* AFSecurityPolicy.h in Headers */, - DB3CF9067FC4B8A4DB7DFECE3637B6DB /* AFURLConnectionOperation.h in Headers */, - 38284C85FF5D6DEF5F23F9FD28F4B9EE /* AFURLRequestSerialization.h in Headers */, - 7BC7921A4B33DA4DA64FDC9CC0F4D03B /* AFURLResponseSerialization.h in Headers */, - 2CCDB74E04B26C170193439306C720D3 /* AFURLSessionManager.h in Headers */, - 7D6D4EBA11FD60DCF0099244A4CA95FB /* UIActivityIndicatorView+AFNetworking.h in Headers */, - F675988B5E38BF8C3CF0B2DB82D3EF88 /* UIAlertView+AFNetworking.h in Headers */, - 44846D154FC64637F5A8F146476221E8 /* UIButton+AFNetworking.h in Headers */, - 50E2159204533918B5DEB3B70F8A89CC /* UIImageView+AFNetworking.h in Headers */, - 083F2B6FF4750DA417FEF9EC21BDD5DE /* UIKit+AFNetworking.h in Headers */, - C08CC812BAA0989E9D8C48D29796E4E1 /* UIProgressView+AFNetworking.h in Headers */, - E24A8F45990EADF7EB386E7C94080BB7 /* UIRefreshControl+AFNetworking.h in Headers */, - 034CD09F7D7B800FED190D27C4DC30E4 /* UIWebView+AFNetworking.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 858DE9AC553D1BDD4A7BC5B461505551 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - CB240B0C1B04A411B41499740D34B5B0 /* AFNetworkActivityLogger.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B2B22D0C283E7EBA0D80BD9D123BA1A1 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 7ABBB64B29140FEEF220AC3BC4F5C1D5 /* TSMarkdownParser.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 467DF12115DC5581D85E26096CC7D16D /* Pods */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1F1383529F68EA0B680474D727B57DF9 /* Build configuration list for PBXNativeTarget "Pods" */; - buildPhases = ( - 5C73047DD440AEBE1766764ED29B52FE /* Sources */, - 555214CCCECBC5ACB2F286016160F1D6 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 20A57CCED090D01D50E0B5045C83DE5C /* PBXTargetDependency */, - 63BFFD3FCFC7318FC47ED523B323796E /* PBXTargetDependency */, - C49647CCCDFBAC0F2AD86C47B8259870 /* PBXTargetDependency */, - ); - name = Pods; - productName = Pods; - productReference = F3139D6AE8D5D85215C7024D946702C4 /* libPods.a */; - productType = "com.apple.product-type.library.static"; - }; - 5B18F572B65064722F49430CF2C153E8 /* TSMarkdownParser */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3508CF84E99097860CE603F12BD60F13 /* Build configuration list for PBXNativeTarget "TSMarkdownParser" */; - buildPhases = ( - AC3B82C070F2567C5FF61AA11E3BF3D6 /* Sources */, - D009DECF132F655B97C0D78FF8212AB2 /* Frameworks */, - B2B22D0C283E7EBA0D80BD9D123BA1A1 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = TSMarkdownParser; - productName = TSMarkdownParser; - productReference = 8FC739D532E373E38AFCF317DFA76500 /* libTSMarkdownParser.a */; - productType = "com.apple.product-type.library.static"; - }; - 6284F0103A037A696FD0DD07686DE3CC /* AFNetworkActivityLogger */ = { - isa = PBXNativeTarget; - buildConfigurationList = EBD7014B523CF65433B7E1541DCA3C25 /* Build configuration list for PBXNativeTarget "AFNetworkActivityLogger" */; - buildPhases = ( - C6A9EABFB62B65DEF0B7531A4B9FE9B7 /* Sources */, - 01A2B80EFFB21CABBFEF07675CE56B8B /* Frameworks */, - 858DE9AC553D1BDD4A7BC5B461505551 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - 4171E47BAF99F37C2048DE5C43290CDC /* PBXTargetDependency */, - ); - name = AFNetworkActivityLogger; - productName = AFNetworkActivityLogger; - productReference = EE0F37D5AE588125871C50E34CF995E7 /* libAFNetworkActivityLogger.a */; - productType = "com.apple.product-type.library.static"; - }; - F507FD4523B5E687F5E813CC23EC3689 /* AFNetworking */ = { - isa = PBXNativeTarget; - buildConfigurationList = 517E4D901DE37337DB21AACEDC138D6A /* Build configuration list for PBXNativeTarget "AFNetworking" */; - buildPhases = ( - A73DF93AD3B8127EC08F4315BB19877F /* Sources */, - 6C9560EAE0B0CDED0CBB7A55BC95132C /* Frameworks */, - 032985B600EFD9B51BE880B5758572DB /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = AFNetworking; - productName = AFNetworking; - productReference = E92816EA757C971CEDA692EE3FC8FA5A /* libAFNetworking.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0700; - }; - buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 7DB346D0F39D3F0E887471402A8071AB; - productRefGroup = CCA510CFBEA2D207524CDA0D73C3B561 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6284F0103A037A696FD0DD07686DE3CC /* AFNetworkActivityLogger */, - F507FD4523B5E687F5E813CC23EC3689 /* AFNetworking */, - 467DF12115DC5581D85E26096CC7D16D /* Pods */, - 5B18F572B65064722F49430CF2C153E8 /* TSMarkdownParser */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 5C73047DD440AEBE1766764ED29B52FE /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 8A27CCEA2AA61F3920D4A7CCB19F3424 /* Pods-dummy.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A73DF93AD3B8127EC08F4315BB19877F /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - DDD6540F004FDC3F73163A31EC2EBFBC /* AFHTTPRequestOperation.m in Sources */, - 8E248334A1449C01D2B8F0C606EC547A /* AFHTTPRequestOperationManager.m in Sources */, - 159B420BE5492E4CC3D8006F0E06A719 /* AFHTTPSessionManager.m in Sources */, - 4A9C4A2D5ECE963C44FDF53346B00572 /* AFNetworkActivityIndicatorManager.m in Sources */, - 757CCBAFFC3CA37DEF7CAD82FEC9881E /* AFNetworkReachabilityManager.m in Sources */, - F91AEB50CAFAF0F5A3A3FB925F4DB96D /* AFNetworking-dummy.m in Sources */, - 588CE6FD74211863EA95B062C9CB2D63 /* AFSecurityPolicy.m in Sources */, - 63C4E9C965C32D38AF1FA0272CD99B8C /* AFURLConnectionOperation.m in Sources */, - 533266707157930927F93B897D81807E /* AFURLRequestSerialization.m in Sources */, - C7600E8DF244EA947C7693871920BA9A /* AFURLResponseSerialization.m in Sources */, - DA3A309CC6E2E80D787987586B4FFEF6 /* AFURLSessionManager.m in Sources */, - 5491D87237F6FCE5EF29360C32D266A6 /* UIActivityIndicatorView+AFNetworking.m in Sources */, - B45A92D04B1EE449F6DF1FCFA9CB50AE /* UIAlertView+AFNetworking.m in Sources */, - 0CD28007E662894A2F515146ADAD1C1D /* UIButton+AFNetworking.m in Sources */, - 4E9746934EF8633DD91BCD8A58F738B6 /* UIImageView+AFNetworking.m in Sources */, - A60720ED530A32B72BF5BF6B1DBADD59 /* UIProgressView+AFNetworking.m in Sources */, - 1286B74800652B63CBD1243E0BF9B798 /* UIRefreshControl+AFNetworking.m in Sources */, - EF51F9344D2A953023A43BC00D179DA5 /* UIWebView+AFNetworking.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - AC3B82C070F2567C5FF61AA11E3BF3D6 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6CDB3CD003FB78DBEF0BDFEDE8448CC4 /* TSMarkdownParser-dummy.m in Sources */, - 5849816D84E150DDC6BDDCB453818F23 /* TSMarkdownParser.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C6A9EABFB62B65DEF0B7531A4B9FE9B7 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 574E9B6B983972CE053CF24ADFD3C1D0 /* AFNetworkActivityLogger-dummy.m in Sources */, - 3CC69282952C9B3C725BBCF377175570 /* AFNetworkActivityLogger.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 20A57CCED090D01D50E0B5045C83DE5C /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = AFNetworkActivityLogger; - target = 6284F0103A037A696FD0DD07686DE3CC /* AFNetworkActivityLogger */; - targetProxy = 2849BC3222B5A4D1199A9B545FFCC92C /* PBXContainerItemProxy */; - }; - 4171E47BAF99F37C2048DE5C43290CDC /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = AFNetworking; - target = F507FD4523B5E687F5E813CC23EC3689 /* AFNetworking */; - targetProxy = 617CE06CA3460BB2CEA4DED51AEBFE64 /* PBXContainerItemProxy */; - }; - 63BFFD3FCFC7318FC47ED523B323796E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = AFNetworking; - target = F507FD4523B5E687F5E813CC23EC3689 /* AFNetworking */; - targetProxy = A386CA56B33F1618BEB031D4C819477D /* PBXContainerItemProxy */; - }; - C49647CCCDFBAC0F2AD86C47B8259870 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = TSMarkdownParser; - target = 5B18F572B65064722F49430CF2C153E8 /* TSMarkdownParser */; - targetProxy = 4C85286F7BE90E21085832AF40AAF346 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 03CA91998D6773EC5D02B3DB87B8353E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_PREPROCESSOR_DEFINITIONS = "RELEASE=1"; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; - STRIP_INSTALLED_PRODUCT = NO; - SYMROOT = "${SRCROOT}/../build"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 0B57334D6C23DADAA4F7D802A5760EB2 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; - ONLY_ACTIVE_ARCH = YES; - STRIP_INSTALLED_PRODUCT = NO; - SYMROOT = "${SRCROOT}/../build"; - }; - name = Debug; - }; - 46A03B9B810B9EA6439242E6B27458C4 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7FBF055A5C18DA41BAA151F0A729FC08 /* Pods.debug.xcconfig */; - buildSettings = { - ENABLE_STRICT_OBJC_MSGSEND = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 67AA1E135C2EAB0673046DD8E04B5903 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1FB4C73FB1FCF1EF3D4140A0073F0AF7 /* AFNetworking-Private.xcconfig */; - buildSettings = { - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_PREFIX_HEADER = "Target Support Files/AFNetworking/AFNetworking-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 8DF5F0F029F0A035D414DE93B81D8EC5 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 0E6F0DFC51C35FED1EB27952544D6A0F /* AFNetworkActivityLogger-Private.xcconfig */; - buildSettings = { - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_PREFIX_HEADER = "Target Support Files/AFNetworkActivityLogger/AFNetworkActivityLogger-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - C5DF67389A855DF2598A0B07633A33CF /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 2AB098EE24DE871CEBF37C9966048792 /* Pods.release.xcconfig */; - buildSettings = { - ENABLE_STRICT_OBJC_MSGSEND = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Release; - }; - D28B5C5B21F14529B856E84FC3AD067E /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 5194A779FF11E324E407B128100CD1CA /* TSMarkdownParser-Private.xcconfig */; - buildSettings = { - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_PREFIX_HEADER = "Target Support Files/TSMarkdownParser/TSMarkdownParser-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - DA41A50E3EEDCF87A297BB2609B9AE38 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1FB4C73FB1FCF1EF3D4140A0073F0AF7 /* AFNetworking-Private.xcconfig */; - buildSettings = { - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_PREFIX_HEADER = "Target Support Files/AFNetworking/AFNetworking-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Release; - }; - E07D79EB7B71E83A5E16DAE7D1D9633F /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 0E6F0DFC51C35FED1EB27952544D6A0F /* AFNetworkActivityLogger-Private.xcconfig */; - buildSettings = { - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_PREFIX_HEADER = "Target Support Files/AFNetworkActivityLogger/AFNetworkActivityLogger-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Release; - }; - E78F65210E3A360FC5F8389C570689FC /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 5194A779FF11E324E407B128100CD1CA /* TSMarkdownParser-Private.xcconfig */; - buildSettings = { - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_PREFIX_HEADER = "Target Support Files/TSMarkdownParser/TSMarkdownParser-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 1F1383529F68EA0B680474D727B57DF9 /* Build configuration list for PBXNativeTarget "Pods" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 46A03B9B810B9EA6439242E6B27458C4 /* Debug */, - C5DF67389A855DF2598A0B07633A33CF /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0B57334D6C23DADAA4F7D802A5760EB2 /* Debug */, - 03CA91998D6773EC5D02B3DB87B8353E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3508CF84E99097860CE603F12BD60F13 /* Build configuration list for PBXNativeTarget "TSMarkdownParser" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - D28B5C5B21F14529B856E84FC3AD067E /* Debug */, - E78F65210E3A360FC5F8389C570689FC /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 517E4D901DE37337DB21AACEDC138D6A /* Build configuration list for PBXNativeTarget "AFNetworking" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 67AA1E135C2EAB0673046DD8E04B5903 /* Debug */, - DA41A50E3EEDCF87A297BB2609B9AE38 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - EBD7014B523CF65433B7E1541DCA3C25 /* Build configuration list for PBXNativeTarget "AFNetworkActivityLogger" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 8DF5F0F029F0A035D414DE93B81D8EC5 /* Debug */, - E07D79EB7B71E83A5E16DAE7D1D9633F /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; -} diff --git a/ios/SAPTracker/src/xcode/Pods/TSMarkdownParser/LICENSE.md b/ios/SAPTracker/src/xcode/Pods/TSMarkdownParser/LICENSE.md deleted file mode 100644 index 97ed8ceb8f1..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/TSMarkdownParser/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Tobias Sundstrand - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/TSMarkdownParser/README.md b/ios/SAPTracker/src/xcode/Pods/TSMarkdownParser/README.md deleted file mode 100644 index 4e1be209a78..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/TSMarkdownParser/README.md +++ /dev/null @@ -1,84 +0,0 @@ -TSMarkdownParser -================ - -[![Build Status](https://travis-ci.org/laptobbe/TSMarkdownParser.svg)](https://travis-ci.org/laptobbe/TSMarkdownParser) -[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) -[![Version](https://img.shields.io/cocoapods/v/TSMarkdownParser.svg)](http://cocoadocs.org/docsets/TSMarkdownParser) -[![Platform](https://img.shields.io/cocoapods/p/TSMarkdownParser.svg)](http://cocoadocs.org/docsets/TSMarkdownParser) -[![Licence](https://img.shields.io/cocoapods/l/TSMarkdownParser.svg)](http://cocoadocs.org/docsets/TSMarkdownParser) - - -TSMarkdownParser is a markdown to NSAttributedString parser for iOS implemented using NSRegularExpressions. It supports many of the standard tags layed out by John Gruber on his site [Daring Fireball](http://daringfireball.net/projects/markdown/syntax). It is also very extendable via Regular Expressions making it easy to add your own custom tags or a totally different parsing syntax if you like. - -#Supported tags -Below is a list of tags supported by the parser out of the box, to add your own tags see "Adding custom parsing" - -```` -Headings -# H1 -## H2 -### H3 -#### H4 -##### H5 -###### H5 - -Lists -* item -+ item -- item - -Images -![Alternative text](image.png) - -URL -[Link text](https://www.example.net) - -Emphasis -`code` -*Em* -_Em_ -**Strong** -__Strong__ - - -```` - -#Installation -TSMarkdownParser is distributed via CocoaPods - -```` -pod 'TSMarkdownParser' - -```` - -alternativly you can clone the project and build the static library setup in the project, or drag the source files into you project. - - -#Usage -The standardParser class method provides a new instance of the parser configured to parse the tags listed above. You can also just create a new instance of TSMarkdownParser and add your own parsing. See "Adding custom parsing" for information on how to do this. - -```` -NSAttributedString *string = [[TSMarkdownParser standardParser] attributedStringFromMarkdown:markdown]; - -```` - -#Customizing appearance -You can configure how the markdown is to be displayed by changing the different properties on a TSMarkdownParser instance. Alternatively you could implement the parsing yourself and add custom attributes to the attributed string. You can also alter the attributed string returned from the parser. - -#Adding custom parsing -Below is an example of how parsing of the bold tag is implemented. You can add your own parsing using the same addParsingRuleWithRegularExpression:withBlock: method. You can add a parsing rule to the standardParser or to your own instance of the parser. If you want to use any of the configuration properties within makesure you use a weak reference to the parser so you don't create a retain cycle. - -```` -NSRegularExpression *boldParsing = [NSRegularExpression regularExpressionWithPattern:@"(\\*|_){2}.*(\\*|_){2}" options:NSRegularExpressionCaseInsensitive error:nil]; -__weak TSMarkdownParser *weakSelf = self; -[self addParsingRuleWithRegularExpression:boldParsing withBlock:^(NSTextCheckingResult *match, NSMutableAttributedString *attributedString) { - [attributedString addAttribute:NSFontAttributeName - value:weakSelf.strongFont - range:match.range]; - [attributedString deleteCharactersInRange:NSMakeRange(match.range.location, 2)]; - [attributedString deleteCharactersInRange:NSMakeRange(match.range.location+match.range.length-4, 2)]; -}]; -```` - -#License -TSMarkdownParser is distributed under a MIT licence, see the licence file for more info. diff --git a/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworkActivityLogger/AFNetworkActivityLogger-Private.xcconfig b/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworkActivityLogger/AFNetworkActivityLogger-Private.xcconfig deleted file mode 100644 index a10ad446912..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworkActivityLogger/AFNetworkActivityLogger-Private.xcconfig +++ /dev/null @@ -1,5 +0,0 @@ -#include "AFNetworkActivityLogger.xcconfig" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/AFNetworkActivityLogger" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/AFNetworkActivityLogger" "${PODS_ROOT}/Headers/Public/AFNetworking" "${PODS_ROOT}/Headers/Public/TSMarkdownParser" -PODS_ROOT = ${SRCROOT} -SKIP_INSTALL = YES \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworkActivityLogger/AFNetworkActivityLogger-dummy.m b/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworkActivityLogger/AFNetworkActivityLogger-dummy.m deleted file mode 100644 index 740d1d5861a..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworkActivityLogger/AFNetworkActivityLogger-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_AFNetworkActivityLogger : NSObject -@end -@implementation PodsDummy_AFNetworkActivityLogger -@end diff --git a/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworkActivityLogger/AFNetworkActivityLogger-prefix.pch b/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworkActivityLogger/AFNetworkActivityLogger-prefix.pch deleted file mode 100644 index aa992a4adb2..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworkActivityLogger/AFNetworkActivityLogger-prefix.pch +++ /dev/null @@ -1,4 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - diff --git a/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworkActivityLogger/AFNetworkActivityLogger.xcconfig b/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworkActivityLogger/AFNetworkActivityLogger.xcconfig deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworking/AFNetworking-Private.xcconfig b/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworking/AFNetworking-Private.xcconfig deleted file mode 100644 index 631dc0b365f..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworking/AFNetworking-Private.xcconfig +++ /dev/null @@ -1,6 +0,0 @@ -#include "AFNetworking.xcconfig" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/AFNetworking" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/AFNetworkActivityLogger" "${PODS_ROOT}/Headers/Public/AFNetworking" "${PODS_ROOT}/Headers/Public/TSMarkdownParser" -OTHER_LDFLAGS = ${AFNETWORKING_OTHER_LDFLAGS} -PODS_ROOT = ${SRCROOT} -SKIP_INSTALL = YES \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworking/AFNetworking-dummy.m b/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworking/AFNetworking-dummy.m deleted file mode 100644 index 6a29cf8dadb..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworking/AFNetworking-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_AFNetworking : NSObject -@end -@implementation PodsDummy_AFNetworking -@end diff --git a/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworking/AFNetworking-prefix.pch b/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworking/AFNetworking-prefix.pch deleted file mode 100644 index aa992a4adb2..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworking/AFNetworking-prefix.pch +++ /dev/null @@ -1,4 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - diff --git a/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworking/AFNetworking.xcconfig b/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworking/AFNetworking.xcconfig deleted file mode 100644 index b0b2d5292eb..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Target Support Files/AFNetworking/AFNetworking.xcconfig +++ /dev/null @@ -1 +0,0 @@ -AFNETWORKING_OTHER_LDFLAGS = -framework "CoreGraphics" -framework "MobileCoreServices" -framework "Security" -framework "SystemConfiguration" \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Target Support Files/Pods/Pods-acknowledgements.markdown b/ios/SAPTracker/src/xcode/Pods/Target Support Files/Pods/Pods-acknowledgements.markdown deleted file mode 100644 index dccc1675689..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Target Support Files/Pods/Pods-acknowledgements.markdown +++ /dev/null @@ -1,73 +0,0 @@ -# Acknowledgements -This application makes use of the following third party libraries: - -## AFNetworkActivityLogger - -Copyright (c) 2013 AFNetworking (http://afnetworking.com/) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -## AFNetworking - -Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com/) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -## TSMarkdownParser - -The MIT License (MIT) - -Copyright (c) 2014 Tobias Sundstrand - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -Generated by CocoaPods - http://cocoapods.org diff --git a/ios/SAPTracker/src/xcode/Pods/Target Support Files/Pods/Pods-acknowledgements.plist b/ios/SAPTracker/src/xcode/Pods/Target Support Files/Pods/Pods-acknowledgements.plist deleted file mode 100644 index c8cc5a5f681..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Target Support Files/Pods/Pods-acknowledgements.plist +++ /dev/null @@ -1,111 +0,0 @@ - - - - - PreferenceSpecifiers - - - FooterText - This application makes use of the following third party libraries: - Title - Acknowledgements - Type - PSGroupSpecifier - - - FooterText - Copyright (c) 2013 AFNetworking (http://afnetworking.com/) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - Title - AFNetworkActivityLogger - Type - PSGroupSpecifier - - - FooterText - Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com/) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - Title - AFNetworking - Type - PSGroupSpecifier - - - FooterText - The MIT License (MIT) - -Copyright (c) 2014 Tobias Sundstrand - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - Title - TSMarkdownParser - Type - PSGroupSpecifier - - - FooterText - Generated by CocoaPods - http://cocoapods.org - Title - - Type - PSGroupSpecifier - - - StringsTable - Acknowledgements - Title - Acknowledgements - - diff --git a/ios/SAPTracker/src/xcode/Pods/Target Support Files/Pods/Pods-dummy.m b/ios/SAPTracker/src/xcode/Pods/Target Support Files/Pods/Pods-dummy.m deleted file mode 100644 index ade64bd1a9b..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Target Support Files/Pods/Pods-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods : NSObject -@end -@implementation PodsDummy_Pods -@end diff --git a/ios/SAPTracker/src/xcode/Pods/Target Support Files/Pods/Pods-resources.sh b/ios/SAPTracker/src/xcode/Pods/Target Support Files/Pods/Pods-resources.sh deleted file mode 100755 index ea685a22b1d..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Target Support Files/Pods/Pods-resources.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/sh -set -e - -mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" - -RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt -> "$RESOURCES_TO_COPY" - -XCASSET_FILES=() - -realpath() { - DIRECTORY="$(cd "${1%/*}" && pwd)" - FILENAME="${1##*/}" - echo "$DIRECTORY/$FILENAME" -} - -install_resource() -{ - case $1 in - *.storyboard) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}" - ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" - ;; - *.xib) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}" - ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" - ;; - *.framework) - echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - ;; - *.xcdatamodel) - echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\"" - xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom" - ;; - *.xcdatamodeld) - echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\"" - xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd" - ;; - *.xcmappingmodel) - echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\"" - xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm" - ;; - *.xcassets) - ABSOLUTE_XCASSET_FILE=$(realpath "${PODS_ROOT}/$1") - XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") - ;; - /*) - echo "$1" - echo "$1" >> "$RESOURCES_TO_COPY" - ;; - *) - echo "${PODS_ROOT}/$1" - echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY" - ;; - esac -} - -mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -if [[ "${ACTION}" == "install" ]]; then - mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" - rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -fi -rm -f "$RESOURCES_TO_COPY" - -if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] -then - case "${TARGETED_DEVICE_FAMILY}" in - 1,2) - TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" - ;; - 1) - TARGET_DEVICE_ARGS="--target-device iphone" - ;; - 2) - TARGET_DEVICE_ARGS="--target-device ipad" - ;; - *) - TARGET_DEVICE_ARGS="--target-device mac" - ;; - esac - - # Find all other xcassets (this unfortunately includes those of path pods and other targets). - OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) - while read line; do - if [[ $line != "`realpath $PODS_ROOT`*" ]]; then - XCASSET_FILES+=("$line") - fi - done <<<"$OTHER_XCASSETS" - - printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -fi diff --git a/ios/SAPTracker/src/xcode/Pods/Target Support Files/Pods/Pods.debug.xcconfig b/ios/SAPTracker/src/xcode/Pods/Target Support Files/Pods/Pods.debug.xcconfig deleted file mode 100644 index 042fe497840..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Target Support Files/Pods/Pods.debug.xcconfig +++ /dev/null @@ -1,5 +0,0 @@ -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/AFNetworkActivityLogger" "${PODS_ROOT}/Headers/Public/AFNetworking" "${PODS_ROOT}/Headers/Public/TSMarkdownParser" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/AFNetworkActivityLogger" -isystem "${PODS_ROOT}/Headers/Public/AFNetworking" -isystem "${PODS_ROOT}/Headers/Public/TSMarkdownParser" -OTHER_LDFLAGS = $(inherited) -ObjC -l"AFNetworkActivityLogger" -l"AFNetworking" -l"TSMarkdownParser" -framework "CoreGraphics" -framework "MobileCoreServices" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" -PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Target Support Files/Pods/Pods.release.xcconfig b/ios/SAPTracker/src/xcode/Pods/Target Support Files/Pods/Pods.release.xcconfig deleted file mode 100644 index 1749e4dab42..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Target Support Files/Pods/Pods.release.xcconfig +++ /dev/null @@ -1,5 +0,0 @@ -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/AFNetworkActivityLogger" "${PODS_ROOT}/Headers/Public/AFNetworking" "${PODS_ROOT}/Headers/Public/TSMarkdownParser" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/AFNetworkActivityLogger" -isystem "${PODS_ROOT}/Headers/Public/AFNetworking" -isystem "${PODS_ROOT}/Headers/Public/TSMarkdownParser" -OTHER_LDFLAGS = $(inherited) -ObjC -l"AFNetworking" -l"TSMarkdownParser" -framework "CoreGraphics" -framework "MobileCoreServices" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" -PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Target Support Files/TSMarkdownParser/TSMarkdownParser-Private.xcconfig b/ios/SAPTracker/src/xcode/Pods/Target Support Files/TSMarkdownParser/TSMarkdownParser-Private.xcconfig deleted file mode 100644 index bedfae427e5..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Target Support Files/TSMarkdownParser/TSMarkdownParser-Private.xcconfig +++ /dev/null @@ -1,6 +0,0 @@ -#include "TSMarkdownParser.xcconfig" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/TSMarkdownParser" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/AFNetworkActivityLogger" "${PODS_ROOT}/Headers/Public/AFNetworking" "${PODS_ROOT}/Headers/Public/TSMarkdownParser" -OTHER_LDFLAGS = ${TSMARKDOWNPARSER_OTHER_LDFLAGS} -PODS_ROOT = ${SRCROOT} -SKIP_INSTALL = YES \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/Target Support Files/TSMarkdownParser/TSMarkdownParser-dummy.m b/ios/SAPTracker/src/xcode/Pods/Target Support Files/TSMarkdownParser/TSMarkdownParser-dummy.m deleted file mode 100644 index 80165d4ff76..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Target Support Files/TSMarkdownParser/TSMarkdownParser-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_TSMarkdownParser : NSObject -@end -@implementation PodsDummy_TSMarkdownParser -@end diff --git a/ios/SAPTracker/src/xcode/Pods/Target Support Files/TSMarkdownParser/TSMarkdownParser-prefix.pch b/ios/SAPTracker/src/xcode/Pods/Target Support Files/TSMarkdownParser/TSMarkdownParser-prefix.pch deleted file mode 100644 index aa992a4adb2..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Target Support Files/TSMarkdownParser/TSMarkdownParser-prefix.pch +++ /dev/null @@ -1,4 +0,0 @@ -#ifdef __OBJC__ -#import -#endif - diff --git a/ios/SAPTracker/src/xcode/Pods/Target Support Files/TSMarkdownParser/TSMarkdownParser.xcconfig b/ios/SAPTracker/src/xcode/Pods/Target Support Files/TSMarkdownParser/TSMarkdownParser.xcconfig deleted file mode 100644 index 9760b16d766..00000000000 --- a/ios/SAPTracker/src/xcode/Pods/Target Support Files/TSMarkdownParser/TSMarkdownParser.xcconfig +++ /dev/null @@ -1 +0,0 @@ -TSMARKDOWNPARSER_OTHER_LDFLAGS = -framework "UIKit" \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker.xcodeproj/project.pbxproj b/ios/SAPTracker/src/xcode/SAPTracker.xcodeproj/project.pbxproj index 2832567d902..498a7a248c7 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker.xcodeproj/project.pbxproj +++ b/ios/SAPTracker/src/xcode/SAPTracker.xcodeproj/project.pbxproj @@ -7,10 +7,8 @@ objects = { /* Begin PBXBuildFile section */ - 7F03FD3E19FA44CD00FA1327 /* APIManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F03FD3D19FA44CD00FA1327 /* APIManager.swift */; }; 7F0658FD19F7D6700077FF95 /* ScanViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F0658FC19F7D6700077FF95 /* ScanViewController.swift */; }; - 7F0658FF19F7EE910077FF95 /* QRCodeData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F0658FE19F7EE910077FF95 /* QRCodeData.swift */; }; - 7F06590419F8094C0077FF95 /* DeviceUDIDManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F06590319F8094C0077FF95 /* DeviceUDIDManager.swift */; }; + 7F0658FF19F7EE910077FF95 /* RegattaData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F0658FE19F7EE910077FF95 /* RegattaData.swift */; }; 7F14A10A1A13B9A6001C1ECB /* _abkhazia.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F14A0041A13B9A6001C1ECB /* _abkhazia.png */; }; 7F14A10B1A13B9A6001C1ECB /* _basque-country.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F14A0051A13B9A6001C1ECB /* _basque-country.png */; }; 7F14A10C1A13B9A6001C1ECB /* _british-antarctic-territory.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F14A0061A13B9A6001C1ECB /* _british-antarctic-territory.png */; }; @@ -277,39 +275,28 @@ 7F193A8F1A39ACF500D71773 /* TimerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F193A8E1A39ACF500D71773 /* TimerViewController.swift */; }; 7F193A911A39E54600D71773 /* GPSAccuracyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F193A901A39E54600D71773 /* GPSAccuracyView.swift */; }; 7F1B66F91A0CDCF600904A41 /* BatteryManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F1B66F81A0CDCF600904A41 /* BatteryManager.swift */; }; - 7F23F0881A1A3DEF00F03F1C /* QRCodeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F23F0871A1A3DEF00F03F1C /* QRCodeManager.swift */; }; + 7F23F0881A1A3DEF00F03F1C /* CheckInController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F23F0871A1A3DEF00F03F1C /* CheckInController.swift */; }; 7F2C605A19F160E400C32D93 /* LocationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F2C605919F160E400C32D93 /* LocationManager.swift */; }; - 7F3AA7C81A1CD7D700F8861F /* SendGPSFixController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F3AA7C71A1CD7D700F8861F /* SendGPSFixController.swift */; }; 7F44095B19F65B5B0021BF22 /* CoreData.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 7F44095919F65B5B0021BF22 /* CoreData.xcdatamodeld */; }; 7F4D2F541A1C8EE50038E7D1 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7F4D2F531A1C8EE50038E7D1 /* Images.xcassets */; }; - 7F4EEDBA1A6D2BAC0026F711 /* CheckIn.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F4EEDB91A6D2BAC0026F711 /* CheckIn.swift */; }; 7F83F15619F154F000C53328 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F83F15519F154F000C53328 /* AppDelegate.swift */; }; 7F83F15819F154F000C53328 /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F83F15719F154F000C53328 /* HomeViewController.swift */; }; - 7F83F15B19F154F000C53328 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7F83F15919F154F000C53328 /* Main.storyboard */; }; 7F83F16C19F154F000C53328 /* SAPTrackerAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F83F16B19F154F000C53328 /* SAPTrackerAPITests.swift */; }; 7F83F17619F1574700C53328 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F83F17519F1574700C53328 /* CoreLocation.framework */; }; 7F87CAA11A2CCE8B0076C617 /* OpenSans-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7F87CA9D1A2CCE8B0076C617 /* OpenSans-Bold.ttf */; }; 7F87CAA21A2CCE8B0076C617 /* OpenSans-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7F87CA9E1A2CCE8B0076C617 /* OpenSans-Light.ttf */; }; 7F87CAA31A2CCE8B0076C617 /* OpenSans-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7F87CA9F1A2CCE8B0076C617 /* OpenSans-Regular.ttf */; }; 7F87CAA41A2CCE8B0076C617 /* OpenSans-Semibold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7F87CAA01A2CCE8B0076C617 /* OpenSans-Semibold.ttf */; }; - 7F87CAA71A2CD6BA0076C617 /* Appearance.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F87CAA61A2CD6BA0076C617 /* Appearance.m */; }; - 7F87DDDB1A97339300704AC4 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7F87DDDD1A97339300704AC4 /* Localizable.strings */; }; - 7F87DDE01A973C7400704AC4 /* eula-ios.html in Resources */ = {isa = PBXBuildFile; fileRef = 7F87DDE21A973C7400704AC4 /* eula-ios.html */; }; 7F8B8D3F1A37356C00C34B88 /* TrackingPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F8B8D3E1A37356C00C34B88 /* TrackingPageViewController.swift */; }; 7F8B8D411A373B0200C34B88 /* SpeedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F8B8D401A373B0200C34B88 /* SpeedViewController.swift */; }; 7F8B8D431A373D4400C34B88 /* CourseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F8B8D421A373D4400C34B88 /* CourseViewController.swift */; }; 7F8CC2081A10D47A00C56D7F /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F8CC2071A10D47A00C56D7F /* SettingsViewController.swift */; }; - 7F950A911A35E967003C8C5C /* LeaderBoardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F950A901A35E967003C8C5C /* LeaderBoardViewController.swift */; }; + 7F950A911A35E967003C8C5C /* LeaderboardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F950A901A35E967003C8C5C /* LeaderboardViewController.swift */; }; 7F99DE3C1A126554009B3619 /* RegattaViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F99DE3B1A126554009B3619 /* RegattaViewController.swift */; }; - 7FA2220A1A25E54F00FD364B /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 06377F0B2F2854497073FC0E /* libPods.a */; }; 7FA2220B1A25E55400FD364B /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F83F17519F1574700C53328 /* CoreLocation.framework */; }; - 7FA6551A19F6661900A1B92D /* DataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FA6551919F6661900A1B92D /* DataManager.swift */; }; + 7FA6551A19F6661900A1B92D /* CoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FA6551919F6661900A1B92D /* CoreDataManager.swift */; }; 7FAFA7951A126B5700D230F1 /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FAFA7941A126B5700D230F1 /* AboutViewController.swift */; }; 7FC5232D19F6AEE800BBFDCC /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7FC5232C19F6AEE800BBFDCC /* AVFoundation.framework */; }; - 7FCDB6621A1636610075D7D9 /* GPSFix.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FCDB65E1A1636610075D7D9 /* GPSFix.swift */; }; - 7FCDB6631A1636610075D7D9 /* Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FCDB65F1A1636610075D7D9 /* Event.swift */; }; - 7FCDB6641A1636610075D7D9 /* LeaderBoard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FCDB6601A1636610075D7D9 /* LeaderBoard.swift */; }; - 7FCDB6651A1636610075D7D9 /* Competitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FCDB6611A1636610075D7D9 /* Competitor.swift */; }; 7FD9D3031A1236080058FEAD /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FD9D3021A1236080058FEAD /* Extensions.swift */; }; 7FED44AE1A25E6110022505F /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7FC5232C19F6AEE800BBFDCC /* AVFoundation.framework */; }; 7FED45C81A25F5900022505F /* competitor1.json in Resources */ = {isa = PBXBuildFile; fileRef = 7FED45C21A25F5900022505F /* competitor1.json */; }; @@ -317,10 +304,63 @@ 7FED45CC1A25F5910022505F /* leaderboard1.json in Resources */ = {isa = PBXBuildFile; fileRef = 7FED45C61A25F5900022505F /* leaderboard1.json */; }; 9E95C3D61C723AB30016632B /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E95C3D51C723AB30016632B /* Constants.swift */; }; 9ECBDDAE1C9C4F0300F76AEB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9ECBDDAD1C9C4F0300F76AEB /* LaunchScreen.storyboard */; }; - C8603D4A1C528832002B2F28 /* Acknowledgements.markdown in Sources */ = {isa = PBXBuildFile; fileRef = C8603D491C528832002B2F28 /* Acknowledgements.markdown */; }; + C84936181D40D295000F30E8 /* GPSFixController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C84936171D40D295000F30E8 /* GPSFixController.swift */; }; + C84936291D47645F000F30E8 /* HomeViewRegattaCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C84936281D47645F000F30E8 /* HomeViewRegattaCell.swift */; }; + C852914F1D48FB91009E9A9D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = C85291511D48FB91009E9A9D /* Localizable.strings */; }; + C852BAA21CF5E1EA0093B0C5 /* RequestManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C852BAA11CF5E1EA0093B0C5 /* RequestManager.swift */; }; + C852BAAB1CF736680093B0C5 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = C852BAAA1CF736680093B0C5 /* Preferences.swift */; }; C8603D511C52892A002B2F28 /* Acknowledgements.markdown in Resources */ = {isa = PBXBuildFile; fileRef = C8603D491C528832002B2F28 /* Acknowledgements.markdown */; }; + C8739E041D2AA2A500A89F3C /* Regatta+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DFA1D2AA2A500A89F3C /* Regatta+CoreDataProperties.swift */; }; + C8739E051D2AA2A500A89F3C /* Regatta.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DFB1D2AA2A500A89F3C /* Regatta.swift */; }; + C8739E061D2AA2A500A89F3C /* GPSFix+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DFC1D2AA2A500A89F3C /* GPSFix+CoreDataProperties.swift */; }; + C8739E071D2AA2A500A89F3C /* GPSFix.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DFD1D2AA2A500A89F3C /* GPSFix.swift */; }; + C8739E081D2AA2A500A89F3C /* Leaderboard+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DFE1D2AA2A500A89F3C /* Leaderboard+CoreDataProperties.swift */; }; + C8739E091D2AA2A500A89F3C /* Leaderboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DFF1D2AA2A500A89F3C /* Leaderboard.swift */; }; + C8739E0A1D2AA2A500A89F3C /* Competitor+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E001D2AA2A500A89F3C /* Competitor+CoreDataProperties.swift */; }; + C8739E0B1D2AA2A500A89F3C /* Competitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E011D2AA2A500A89F3C /* Competitor.swift */; }; + C8739E0C1D2AA2A500A89F3C /* Event+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E021D2AA2A500A89F3C /* Event+CoreDataProperties.swift */; }; + C8739E0D1D2AA2A500A89F3C /* Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E031D2AA2A500A89F3C /* Event.swift */; }; + C8739E0F1D2BEE7900A89F3C /* RegattaController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E0E1D2BEE7900A89F3C /* RegattaController.swift */; }; + C8739E121D2BF14F00A89F3C /* EventData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E111D2BF14F00A89F3C /* EventData.swift */; }; + C8739E141D2BF16300A89F3C /* LeaderboardData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E131D2BF16300A89F3C /* LeaderboardData.swift */; }; + C8739E161D2BF17900A89F3C /* CompetitorData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E151D2BF17900A89F3C /* CompetitorData.swift */; }; + C8739E181D2BF2DC00A89F3C /* BaseData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E171D2BF2DC00A89F3C /* BaseData.swift */; }; + C8739E1C1D2D5F1700A89F3C /* LocationData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E1B1D2D5F1700A89F3C /* LocationData.swift */; }; + C89C5FC51D06A289002AAAD2 /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C5FC41D06A289002AAAD2 /* GradientView.swift */; }; + C89C5FCA1D06CECD002AAAD2 /* TrackingViewStatusCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C5FC91D06CECD002AAAD2 /* TrackingViewStatusCell.swift */; }; + C89C5FCC1D06CF0C002AAAD2 /* TrackingViewGPSAccuracyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C5FCB1D06CF0C002AAAD2 /* TrackingViewGPSAccuracyCell.swift */; }; + C89C5FCE1D06CF26002AAAD2 /* TrackingViewGPSFixesCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C5FCD1D06CF26002AAAD2 /* TrackingViewGPSFixesCell.swift */; }; + C89C5FD01D06CF46002AAAD2 /* TrackingViewModeCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C5FCF1D06CF46002AAAD2 /* TrackingViewModeCell.swift */; }; C8A4400B1C18153600DF70A0 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = C8A4400A1C18153600DF70A0 /* Settings.bundle */; }; C8BBAC791C52649E004CA551 /* LicenseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8BBAC781C52649E004CA551 /* LicenseViewController.swift */; }; + C8BFCCC41D51C53500FC1A27 /* TeamData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8BFCCC31D51C53500FC1A27 /* TeamData.swift */; }; + C8BFCCCC1D523C5D00FC1A27 /* TitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8BFCCCB1D523C5D00FC1A27 /* TitleView.swift */; }; + C8D5E81D1D479FA800DA0D61 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C8D5E81C1D479FA800DA0D61 /* Main.storyboard */; }; + C8F1B1E11D488B6D004C3379 /* Translation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8F1B1E01D488B6D004C3379 /* Translation.swift */; }; + C8F71EDA1D8691F700826DE4 /* AFHTTPRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71EA61D8691F700826DE4 /* AFHTTPRequestOperation.m */; }; + C8F71EDB1D8691F700826DE4 /* AFHTTPRequestOperationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71EA81D8691F700826DE4 /* AFHTTPRequestOperationManager.m */; }; + C8F71EDC1D8691F700826DE4 /* AFHTTPSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71EAA1D8691F700826DE4 /* AFHTTPSessionManager.m */; }; + C8F71EDD1D8691F700826DE4 /* AFNetworkReachabilityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71EAD1D8691F700826DE4 /* AFNetworkReachabilityManager.m */; }; + C8F71EDE1D8691F700826DE4 /* AFSecurityPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71EAF1D8691F700826DE4 /* AFSecurityPolicy.m */; }; + C8F71EDF1D8691F700826DE4 /* AFURLConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71EB11D8691F700826DE4 /* AFURLConnectionOperation.m */; }; + C8F71EE01D8691F700826DE4 /* AFURLRequestSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71EB31D8691F700826DE4 /* AFURLRequestSerialization.m */; }; + C8F71EE11D8691F700826DE4 /* AFURLResponseSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71EB51D8691F700826DE4 /* AFURLResponseSerialization.m */; }; + C8F71EE21D8691F700826DE4 /* AFURLSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71EB71D8691F700826DE4 /* AFURLSessionManager.m */; }; + C8F71EE31D8691F700826DE4 /* SVIndefiniteAnimatedView.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71EBA1D8691F700826DE4 /* SVIndefiniteAnimatedView.m */; }; + C8F71EE41D8691F700826DE4 /* SVProgressAnimatedView.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71EBC1D8691F700826DE4 /* SVProgressAnimatedView.m */; }; + C8F71EE51D8691F700826DE4 /* SVProgressHUD.bundle in Resources */ = {isa = PBXBuildFile; fileRef = C8F71EBE1D8691F700826DE4 /* SVProgressHUD.bundle */; }; + C8F71EE61D8691F700826DE4 /* SVProgressHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71EC01D8691F700826DE4 /* SVProgressHUD.m */; }; + C8F71EE71D8691F700826DE4 /* SVRadialGradientLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71EC21D8691F700826DE4 /* SVRadialGradientLayer.m */; }; + C8F71EE81D8691F700826DE4 /* TSMarkdownParser.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71EC61D8691F700826DE4 /* TSMarkdownParser.m */; }; + C8F71EE91D8691F700826DE4 /* AFNetworkActivityIndicatorManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71EC91D8691F700826DE4 /* AFNetworkActivityIndicatorManager.m */; }; + C8F71EEA1D8691F700826DE4 /* UIActivityIndicatorView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71ECB1D8691F700826DE4 /* UIActivityIndicatorView+AFNetworking.m */; }; + C8F71EEB1D8691F700826DE4 /* UIAlertView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71ECD1D8691F700826DE4 /* UIAlertView+AFNetworking.m */; }; + C8F71EEC1D8691F700826DE4 /* UIButton+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71ECF1D8691F700826DE4 /* UIButton+AFNetworking.m */; }; + C8F71EED1D8691F700826DE4 /* UIImageView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71ED21D8691F700826DE4 /* UIImageView+AFNetworking.m */; }; + C8F71EEE1D8691F700826DE4 /* UIProgressView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71ED51D8691F700826DE4 /* UIProgressView+AFNetworking.m */; }; + C8F71EEF1D8691F700826DE4 /* UIRefreshControl+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71ED71D8691F700826DE4 /* UIRefreshControl+AFNetworking.m */; }; + C8F71EF01D8691F700826DE4 /* UIWebView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71ED91D8691F700826DE4 /* UIWebView+AFNetworking.m */; }; + C8F71EF31D86A15F00826DE4 /* SMTWiFiStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = C8F71EF21D86A15F00826DE4 /* SMTWiFiStatus.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -331,50 +371,12 @@ remoteGlobalIDString = 7F83F14F19F154F000C53328; remoteInfo = SAPTracker; }; - C8603D4E1C528832002B2F28 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = C8B31F771B68DAD400C8A809 /* Pods.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 8FC739D532E373E38AFCF317DFA76500; - remoteInfo = TSMarkdownParser; - }; - C89A171B1B6A27CF00CE6814 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = C8B31F771B68DAD400C8A809 /* Pods.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = A25D0CBC0C6347F3CD6A0FF8B5EAA94E; - remoteInfo = AFNetworkActivityLogger; - }; - C89A171D1B6A27CF00CE6814 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = C8B31F771B68DAD400C8A809 /* Pods.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 491F530684ABE0C250361CF89F4D98F2; - remoteInfo = AFNetworking; - }; - C8B31F7D1B68DAD500C8A809 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = C8B31F771B68DAD400C8A809 /* Pods.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = AA2D50EF0C96F46B694820F2; - remoteInfo = Pods; - }; - C8B31F831B68DAEE00C8A809 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = C8B31F771B68DAD400C8A809 /* Pods.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 467DF12115DC5581D85E26096CC7D16D; - remoteInfo = Pods; - }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 06377F0B2F2854497073FC0E /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 7F03FD3D19FA44CD00FA1327 /* APIManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = APIManager.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 7F03FD3F19FA4D7400FA1327 /* bridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bridge.h; sourceTree = ""; }; 7F0658FC19F7D6700077FF95 /* ScanViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ScanViewController.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; - 7F0658FE19F7EE910077FF95 /* QRCodeData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = QRCodeData.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; - 7F06590319F8094C0077FF95 /* DeviceUDIDManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceUDIDManager.swift; sourceTree = ""; }; + 7F0658FE19F7EE910077FF95 /* RegattaData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = RegattaData.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 7F14A0041A13B9A6001C1ECB /* _abkhazia.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = _abkhazia.png; sourceTree = ""; }; 7F14A0051A13B9A6001C1ECB /* _basque-country.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "_basque-country.png"; sourceTree = ""; }; 7F14A0061A13B9A6001C1ECB /* _british-antarctic-territory.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "_british-antarctic-territory.png"; sourceTree = ""; }; @@ -641,17 +643,14 @@ 7F193A8E1A39ACF500D71773 /* TimerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimerViewController.swift; sourceTree = ""; }; 7F193A901A39E54600D71773 /* GPSAccuracyView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GPSAccuracyView.swift; sourceTree = ""; }; 7F1B66F81A0CDCF600904A41 /* BatteryManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BatteryManager.swift; sourceTree = ""; }; - 7F23F0871A1A3DEF00F03F1C /* QRCodeManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QRCodeManager.swift; sourceTree = ""; }; + 7F23F0871A1A3DEF00F03F1C /* CheckInController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckInController.swift; sourceTree = ""; }; 7F2C605919F160E400C32D93 /* LocationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationManager.swift; sourceTree = ""; }; - 7F3AA7C71A1CD7D700F8861F /* SendGPSFixController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendGPSFixController.swift; sourceTree = ""; }; 7F44095A19F65B5B0021BF22 /* CoreData.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = CoreData.xcdatamodel; sourceTree = ""; }; 7F4D2F531A1C8EE50038E7D1 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 7F4EEDB91A6D2BAC0026F711 /* CheckIn.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckIn.swift; sourceTree = ""; }; 7F83F15019F154F000C53328 /* SAPTracker.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SAPTracker.app; sourceTree = BUILT_PRODUCTS_DIR; }; 7F83F15419F154F000C53328 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 7F83F15519F154F000C53328 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7F83F15719F154F000C53328 /* HomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewController.swift; sourceTree = ""; }; - 7F83F15A19F154F000C53328 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 7F83F16519F154F000C53328 /* SAPTrackerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SAPTrackerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7F83F16A19F154F000C53328 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 7F83F16B19F154F000C53328 /* SAPTrackerAPITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SAPTrackerAPITests.swift; sourceTree = ""; }; @@ -660,39 +659,108 @@ 7F87CA9E1A2CCE8B0076C617 /* OpenSans-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "OpenSans-Light.ttf"; sourceTree = ""; }; 7F87CA9F1A2CCE8B0076C617 /* OpenSans-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "OpenSans-Regular.ttf"; sourceTree = ""; }; 7F87CAA01A2CCE8B0076C617 /* OpenSans-Semibold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "OpenSans-Semibold.ttf"; sourceTree = ""; }; - 7F87CAA51A2CD6BA0076C617 /* Appearance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Appearance.h; sourceTree = ""; }; - 7F87CAA61A2CD6BA0076C617 /* Appearance.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Appearance.m; sourceTree = ""; }; - 7F87DDDC1A97339300704AC4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; - 7F87DDDF1A9733B200704AC4 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; - 7F87DDE11A973C7400704AC4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = Base; path = "Base.lproj/eula-ios.html"; sourceTree = ""; }; - 7F87DDE31A973C7900704AC4 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = de; path = "de.lproj/eula-ios.html"; sourceTree = ""; }; 7F8B8D3E1A37356C00C34B88 /* TrackingPageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrackingPageViewController.swift; sourceTree = ""; }; 7F8B8D401A373B0200C34B88 /* SpeedViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpeedViewController.swift; sourceTree = ""; }; 7F8B8D421A373D4400C34B88 /* CourseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CourseViewController.swift; sourceTree = ""; }; 7F8CC2071A10D47A00C56D7F /* SettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = ""; }; - 7F950A901A35E967003C8C5C /* LeaderBoardViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeaderBoardViewController.swift; sourceTree = ""; }; + 7F950A901A35E967003C8C5C /* LeaderboardViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeaderboardViewController.swift; sourceTree = ""; }; 7F99DE3B1A126554009B3619 /* RegattaViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegattaViewController.swift; sourceTree = ""; }; - 7FA6551919F6661900A1B92D /* DataManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = DataManager.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 7FA6551919F6661900A1B92D /* CoreDataManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = CoreDataManager.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 7FAFA7941A126B5700D230F1 /* AboutViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutViewController.swift; sourceTree = ""; }; - 7FAFB0B51A603C3E0054D457 /* LICENSE.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE.txt; sourceTree = ""; }; 7FC5232C19F6AEE800BBFDCC /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; - 7FCDB65E1A1636610075D7D9 /* GPSFix.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GPSFix.swift; sourceTree = ""; }; - 7FCDB65F1A1636610075D7D9 /* Event.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Event.swift; sourceTree = ""; }; - 7FCDB6601A1636610075D7D9 /* LeaderBoard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeaderBoard.swift; sourceTree = ""; }; - 7FCDB6611A1636610075D7D9 /* Competitor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Competitor.swift; sourceTree = ""; }; 7FD9D3021A1236080058FEAD /* Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = ""; }; 7FED45C21A25F5900022505F /* competitor1.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = competitor1.json; sourceTree = ""; }; 7FED45C41A25F5900022505F /* event1.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = event1.json; sourceTree = ""; }; 7FED45C61A25F5900022505F /* leaderboard1.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = leaderboard1.json; sourceTree = ""; }; 9E95C3D51C723AB30016632B /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; 9ECBDDAD1C9C4F0300F76AEB /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; + C84936171D40D295000F30E8 /* GPSFixController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GPSFixController.swift; sourceTree = ""; }; + C84936281D47645F000F30E8 /* HomeViewRegattaCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeViewRegattaCell.swift; sourceTree = ""; }; + C85291501D48FB91009E9A9D /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; + C852BAA11CF5E1EA0093B0C5 /* RequestManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestManager.swift; sourceTree = ""; }; + C852BAAA1CF736680093B0C5 /* Preferences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = ""; }; + C85FAA501D4F84460087C2A2 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; C8603D491C528832002B2F28 /* Acknowledgements.markdown */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Acknowledgements.markdown; sourceTree = ""; }; + C8739D9A1D25317100A89F3C /* CoreData 2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "CoreData 2.xcdatamodel"; sourceTree = ""; }; + C8739DFA1D2AA2A500A89F3C /* Regatta+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Regatta+CoreDataProperties.swift"; sourceTree = ""; }; + C8739DFB1D2AA2A500A89F3C /* Regatta.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Regatta.swift; sourceTree = ""; }; + C8739DFC1D2AA2A500A89F3C /* GPSFix+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GPSFix+CoreDataProperties.swift"; sourceTree = ""; }; + C8739DFD1D2AA2A500A89F3C /* GPSFix.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GPSFix.swift; sourceTree = ""; }; + C8739DFE1D2AA2A500A89F3C /* Leaderboard+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Leaderboard+CoreDataProperties.swift"; sourceTree = ""; }; + C8739DFF1D2AA2A500A89F3C /* Leaderboard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Leaderboard.swift; sourceTree = ""; }; + C8739E001D2AA2A500A89F3C /* Competitor+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Competitor+CoreDataProperties.swift"; sourceTree = ""; }; + C8739E011D2AA2A500A89F3C /* Competitor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Competitor.swift; sourceTree = ""; }; + C8739E021D2AA2A500A89F3C /* Event+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Event+CoreDataProperties.swift"; sourceTree = ""; }; + C8739E031D2AA2A500A89F3C /* Event.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Event.swift; sourceTree = ""; }; + C8739E0E1D2BEE7900A89F3C /* RegattaController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegattaController.swift; sourceTree = ""; }; + C8739E111D2BF14F00A89F3C /* EventData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventData.swift; sourceTree = ""; }; + C8739E131D2BF16300A89F3C /* LeaderboardData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeaderboardData.swift; sourceTree = ""; }; + C8739E151D2BF17900A89F3C /* CompetitorData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompetitorData.swift; sourceTree = ""; }; + C8739E171D2BF2DC00A89F3C /* BaseData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseData.swift; sourceTree = ""; }; + C8739E1B1D2D5F1700A89F3C /* LocationData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationData.swift; sourceTree = ""; }; + C89C5FC41D06A289002AAAD2 /* GradientView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = ""; }; + C89C5FC91D06CECD002AAAD2 /* TrackingViewStatusCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrackingViewStatusCell.swift; sourceTree = ""; }; + C89C5FCB1D06CF0C002AAAD2 /* TrackingViewGPSAccuracyCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrackingViewGPSAccuracyCell.swift; sourceTree = ""; }; + C89C5FCD1D06CF26002AAAD2 /* TrackingViewGPSFixesCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrackingViewGPSFixesCell.swift; sourceTree = ""; }; + C89C5FCF1D06CF46002AAAD2 /* TrackingViewModeCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrackingViewModeCell.swift; sourceTree = ""; }; C8A4400A1C18153600DF70A0 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; - C8B31F771B68DAD400C8A809 /* Pods.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Pods.xcodeproj; path = Pods/Pods.xcodeproj; sourceTree = ""; }; C8BBAC781C52649E004CA551 /* LicenseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LicenseViewController.swift; sourceTree = ""; }; - C8CF3F181C526CCA00FB1604 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Main.strings; sourceTree = ""; }; - CF98F25F363113C51C7CB1F3 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; - EA431711E588F5A2B31A62AC /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; + C8BFCCC31D51C53500FC1A27 /* TeamData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TeamData.swift; sourceTree = ""; }; + C8BFCCCB1D523C5D00FC1A27 /* TitleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TitleView.swift; sourceTree = ""; }; + C8D5E81C1D479FA800DA0D61 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; + C8F1B1E01D488B6D004C3379 /* Translation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Translation.swift; sourceTree = ""; }; + C8F71EA51D8691F700826DE4 /* AFHTTPRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFHTTPRequestOperation.h; sourceTree = ""; }; + C8F71EA61D8691F700826DE4 /* AFHTTPRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPRequestOperation.m; sourceTree = ""; }; + C8F71EA71D8691F700826DE4 /* AFHTTPRequestOperationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFHTTPRequestOperationManager.h; sourceTree = ""; }; + C8F71EA81D8691F700826DE4 /* AFHTTPRequestOperationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPRequestOperationManager.m; sourceTree = ""; }; + C8F71EA91D8691F700826DE4 /* AFHTTPSessionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFHTTPSessionManager.h; sourceTree = ""; }; + C8F71EAA1D8691F700826DE4 /* AFHTTPSessionManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPSessionManager.m; sourceTree = ""; }; + C8F71EAB1D8691F700826DE4 /* AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFNetworking.h; sourceTree = ""; }; + C8F71EAC1D8691F700826DE4 /* AFNetworkReachabilityManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFNetworkReachabilityManager.h; sourceTree = ""; }; + C8F71EAD1D8691F700826DE4 /* AFNetworkReachabilityManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFNetworkReachabilityManager.m; sourceTree = ""; }; + C8F71EAE1D8691F700826DE4 /* AFSecurityPolicy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFSecurityPolicy.h; sourceTree = ""; }; + C8F71EAF1D8691F700826DE4 /* AFSecurityPolicy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFSecurityPolicy.m; sourceTree = ""; }; + C8F71EB01D8691F700826DE4 /* AFURLConnectionOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLConnectionOperation.h; sourceTree = ""; }; + C8F71EB11D8691F700826DE4 /* AFURLConnectionOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLConnectionOperation.m; sourceTree = ""; }; + C8F71EB21D8691F700826DE4 /* AFURLRequestSerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLRequestSerialization.h; sourceTree = ""; }; + C8F71EB31D8691F700826DE4 /* AFURLRequestSerialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLRequestSerialization.m; sourceTree = ""; }; + C8F71EB41D8691F700826DE4 /* AFURLResponseSerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLResponseSerialization.h; sourceTree = ""; }; + C8F71EB51D8691F700826DE4 /* AFURLResponseSerialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLResponseSerialization.m; sourceTree = ""; }; + C8F71EB61D8691F700826DE4 /* AFURLSessionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLSessionManager.h; sourceTree = ""; }; + C8F71EB71D8691F700826DE4 /* AFURLSessionManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLSessionManager.m; sourceTree = ""; }; + C8F71EB91D8691F700826DE4 /* SVIndefiniteAnimatedView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVIndefiniteAnimatedView.h; sourceTree = ""; }; + C8F71EBA1D8691F700826DE4 /* SVIndefiniteAnimatedView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SVIndefiniteAnimatedView.m; sourceTree = ""; }; + C8F71EBB1D8691F700826DE4 /* SVProgressAnimatedView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVProgressAnimatedView.h; sourceTree = ""; }; + C8F71EBC1D8691F700826DE4 /* SVProgressAnimatedView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SVProgressAnimatedView.m; sourceTree = ""; }; + C8F71EBD1D8691F700826DE4 /* SVProgressHUD-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SVProgressHUD-Prefix.pch"; sourceTree = ""; }; + C8F71EBE1D8691F700826DE4 /* SVProgressHUD.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = SVProgressHUD.bundle; sourceTree = ""; }; + C8F71EBF1D8691F700826DE4 /* SVProgressHUD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVProgressHUD.h; sourceTree = ""; }; + C8F71EC01D8691F700826DE4 /* SVProgressHUD.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SVProgressHUD.m; sourceTree = ""; }; + C8F71EC11D8691F700826DE4 /* SVRadialGradientLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVRadialGradientLayer.h; sourceTree = ""; }; + C8F71EC21D8691F700826DE4 /* SVRadialGradientLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SVRadialGradientLayer.m; sourceTree = ""; }; + C8F71EC41D8691F700826DE4 /* TSMarkdownParser-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TSMarkdownParser-Prefix.pch"; sourceTree = ""; }; + C8F71EC51D8691F700826DE4 /* TSMarkdownParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSMarkdownParser.h; sourceTree = ""; }; + C8F71EC61D8691F700826DE4 /* TSMarkdownParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSMarkdownParser.m; sourceTree = ""; }; + C8F71EC81D8691F700826DE4 /* AFNetworkActivityIndicatorManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFNetworkActivityIndicatorManager.h; sourceTree = ""; }; + C8F71EC91D8691F700826DE4 /* AFNetworkActivityIndicatorManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFNetworkActivityIndicatorManager.m; sourceTree = ""; }; + C8F71ECA1D8691F700826DE4 /* UIActivityIndicatorView+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIActivityIndicatorView+AFNetworking.h"; sourceTree = ""; }; + C8F71ECB1D8691F700826DE4 /* UIActivityIndicatorView+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIActivityIndicatorView+AFNetworking.m"; sourceTree = ""; }; + C8F71ECC1D8691F700826DE4 /* UIAlertView+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIAlertView+AFNetworking.h"; sourceTree = ""; }; + C8F71ECD1D8691F700826DE4 /* UIAlertView+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIAlertView+AFNetworking.m"; sourceTree = ""; }; + C8F71ECE1D8691F700826DE4 /* UIButton+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIButton+AFNetworking.h"; sourceTree = ""; }; + C8F71ECF1D8691F700826DE4 /* UIButton+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIButton+AFNetworking.m"; sourceTree = ""; }; + C8F71ED01D8691F700826DE4 /* UIImage+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+AFNetworking.h"; sourceTree = ""; }; + C8F71ED11D8691F700826DE4 /* UIImageView+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImageView+AFNetworking.h"; sourceTree = ""; }; + C8F71ED21D8691F700826DE4 /* UIImageView+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImageView+AFNetworking.m"; sourceTree = ""; }; + C8F71ED31D8691F700826DE4 /* UIKit+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIKit+AFNetworking.h"; sourceTree = ""; }; + C8F71ED41D8691F700826DE4 /* UIProgressView+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIProgressView+AFNetworking.h"; sourceTree = ""; }; + C8F71ED51D8691F700826DE4 /* UIProgressView+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIProgressView+AFNetworking.m"; sourceTree = ""; }; + C8F71ED61D8691F700826DE4 /* UIRefreshControl+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIRefreshControl+AFNetworking.h"; sourceTree = ""; }; + C8F71ED71D8691F700826DE4 /* UIRefreshControl+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIRefreshControl+AFNetworking.m"; sourceTree = ""; }; + C8F71ED81D8691F700826DE4 /* UIWebView+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIWebView+AFNetworking.h"; sourceTree = ""; }; + C8F71ED91D8691F700826DE4 /* UIWebView+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIWebView+AFNetworking.m"; sourceTree = ""; }; + C8F71EF11D86A15F00826DE4 /* SMTWiFiStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SMTWiFiStatus.h; path = Libraries/SMTWiFiStatus/SMTWiFiStatus.h; sourceTree = ""; }; + C8F71EF21D86A15F00826DE4 /* SMTWiFiStatus.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SMTWiFiStatus.m; path = Libraries/SMTWiFiStatus/SMTWiFiStatus.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -710,7 +778,6 @@ buildActionMask = 2147483647; files = ( 7FA2220B1A25E55400FD364B /* CoreLocation.framework in Frameworks */, - 7FA2220A1A25E54F00FD364B /* libPods.a in Frameworks */, 7FED44AE1A25E6110022505F /* AVFoundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -718,76 +785,60 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 55CB522899730E933A8A1A9B /* Pods */ = { - isa = PBXGroup; - children = ( - EA431711E588F5A2B31A62AC /* Pods.debug.xcconfig */, - CF98F25F363113C51C7CB1F3 /* Pods.release.xcconfig */, - ); - name = Pods; - sourceTree = ""; - }; 7AC6457280AEA3EC18F5E846 /* Frameworks */ = { isa = PBXGroup; children = ( 7FC5232C19F6AEE800BBFDCC /* AVFoundation.framework */, 7F83F17519F1574700C53328 /* CoreLocation.framework */, - 06377F0B2F2854497073FC0E /* libPods.a */, ); name = Frameworks; sourceTree = ""; }; - 7F06590019F7FE750077FF95 /* Model */ = { + 7F06590019F7FE750077FF95 /* CoreData */ = { isa = PBXGroup; children = ( - 7F0658FE19F7EE910077FF95 /* QRCodeData.swift */, - 7F4EEDB91A6D2BAC0026F711 /* CheckIn.swift */, - 7FCDB65F1A1636610075D7D9 /* Event.swift */, - 7FCDB6601A1636610075D7D9 /* LeaderBoard.swift */, - 7FCDB6611A1636610075D7D9 /* Competitor.swift */, - 7FCDB65E1A1636610075D7D9 /* GPSFix.swift */, + 7FA6551919F6661900A1B92D /* CoreDataManager.swift */, 7F44095919F65B5B0021BF22 /* CoreData.xcdatamodeld */, + C8739DFA1D2AA2A500A89F3C /* Regatta+CoreDataProperties.swift */, + C8739DFB1D2AA2A500A89F3C /* Regatta.swift */, + C8739DFC1D2AA2A500A89F3C /* GPSFix+CoreDataProperties.swift */, + C8739DFD1D2AA2A500A89F3C /* GPSFix.swift */, + C8739DFE1D2AA2A500A89F3C /* Leaderboard+CoreDataProperties.swift */, + C8739DFF1D2AA2A500A89F3C /* Leaderboard.swift */, + C8739E001D2AA2A500A89F3C /* Competitor+CoreDataProperties.swift */, + C8739E011D2AA2A500A89F3C /* Competitor.swift */, + C8739E021D2AA2A500A89F3C /* Event+CoreDataProperties.swift */, + C8739E031D2AA2A500A89F3C /* Event.swift */, ); - name = Model; + name = CoreData; sourceTree = ""; }; - 7F06590119F7FE920077FF95 /* View */ = { + 7F06590119F7FE920077FF95 /* ViewController */ = { isa = PBXGroup; children = ( - 7F83F15719F154F000C53328 /* HomeViewController.swift */, - 7F0658FC19F7D6700077FF95 /* ScanViewController.swift */, + C8BBAC781C52649E004CA551 /* LicenseViewController.swift */, 7F8CC2071A10D47A00C56D7F /* SettingsViewController.swift */, 7FAFA7941A126B5700D230F1 /* AboutViewController.swift */, - 7F99DE3B1A126554009B3619 /* RegattaViewController.swift */, - 7F950A901A35E967003C8C5C /* LeaderBoardViewController.swift */, - 7F1875B21A10F1B800C25BE0 /* TrackingViewController.swift */, - 7F193A901A39E54600D71773 /* GPSAccuracyView.swift */, - 7F8B8D3E1A37356C00C34B88 /* TrackingPageViewController.swift */, - 7F193A8E1A39ACF500D71773 /* TimerViewController.swift */, - 7F8B8D401A373B0200C34B88 /* SpeedViewController.swift */, - 7F8B8D421A373D4400C34B88 /* CourseViewController.swift */, - 7F72C73F1A2DEA2100F48EE8 /* Resources */, - 7F72C7401A2DEA3300F48EE8 /* Helpers */, - C8BBAC781C52649E004CA551 /* LicenseViewController.swift */, + 7F83F15719F154F000C53328 /* HomeViewController.swift */, + C84936281D47645F000F30E8 /* HomeViewRegattaCell.swift */, + 7F0658FC19F7D6700077FF95 /* ScanViewController.swift */, + C89C60101D0FF036002AAAD2 /* Regatta */, ); - name = View; + name = ViewController; sourceTree = ""; }; - 7F06590219F7FEA40077FF95 /* Controller */ = { + 7F06590219F7FEA40077FF95 /* DataController */ = { isa = PBXGroup; children = ( - 7F23F0871A1A3DEF00F03F1C /* QRCodeManager.swift */, - 7F2C605919F160E400C32D93 /* LocationManager.swift */, - 7FA6551919F6661900A1B92D /* DataManager.swift */, - 7F03FD3D19FA44CD00FA1327 /* APIManager.swift */, - 7F06590319F8094C0077FF95 /* DeviceUDIDManager.swift */, - 7F1B66F81A0CDCF600904A41 /* BatteryManager.swift */, - 7F3AA7C71A1CD7D700F8861F /* SendGPSFixController.swift */, + 7F23F0871A1A3DEF00F03F1C /* CheckInController.swift */, + C84936171D40D295000F30E8 /* GPSFixController.swift */, + C8739E0E1D2BEE7900A89F3C /* RegattaController.swift */, + C8739E101D2BF13200A89F3C /* Data */, ); - name = Controller; + name = DataController; sourceTree = ""; }; - 7F14A0031A13B9A6001C1ECB /* flags */ = { + 7F14A0031A13B9A6001C1ECB /* Flags */ = { isa = PBXGroup; children = ( 7F14A0041A13B9A6001C1ECB /* _abkhazia.png */, @@ -1053,45 +1104,16 @@ 7F14A1081A13B9A6001C1ECB /* ZM.png */, 7F14A1091A13B9A6001C1ECB /* ZW.png */, ); + name = Flags; path = flags; sourceTree = ""; }; - 7F72C73F1A2DEA2100F48EE8 /* Resources */ = { - isa = PBXGroup; - children = ( - 9ECBDDAD1C9C4F0300F76AEB /* LaunchScreen.storyboard */, - 7F83F15919F154F000C53328 /* Main.storyboard */, - 7F4D2F531A1C8EE50038E7D1 /* Images.xcassets */, - 7F87CA9D1A2CCE8B0076C617 /* OpenSans-Bold.ttf */, - 7F87CA9E1A2CCE8B0076C617 /* OpenSans-Light.ttf */, - 7F87CA9F1A2CCE8B0076C617 /* OpenSans-Regular.ttf */, - 7F87CAA01A2CCE8B0076C617 /* OpenSans-Semibold.ttf */, - 7F87DDE21A973C7400704AC4 /* eula-ios.html */, - 7F87DDDD1A97339300704AC4 /* Localizable.strings */, - ); - name = Resources; - sourceTree = ""; - }; - 7F72C7401A2DEA3300F48EE8 /* Helpers */ = { - isa = PBXGroup; - children = ( - 7FD9D3021A1236080058FEAD /* Extensions.swift */, - 7F87CAA51A2CD6BA0076C617 /* Appearance.h */, - 7F87CAA61A2CD6BA0076C617 /* Appearance.m */, - 9E95C3D51C723AB30016632B /* Constants.swift */, - ); - name = Helpers; - sourceTree = ""; - }; 7F83F14719F154F000C53328 = { isa = PBXGroup; children = ( - C8B31F771B68DAD400C8A809 /* Pods.xcodeproj */, - 7FAFB0B51A603C3E0054D457 /* LICENSE.txt */, 7F83F15219F154F000C53328 /* SAPTracker */, 7F83F16819F154F000C53328 /* SAPTrackerTests */, 7F83F15119F154F000C53328 /* Products */, - 55CB522899730E933A8A1A9B /* Pods */, 7AC6457280AEA3EC18F5E846 /* Frameworks */, ); sourceTree = ""; @@ -1108,11 +1130,10 @@ 7F83F15219F154F000C53328 /* SAPTracker */ = { isa = PBXGroup; children = ( + C8F71EA31D8691F700826DE4 /* Libraries */, 7F83F15519F154F000C53328 /* AppDelegate.swift */, - 7F06590119F7FE920077FF95 /* View */, - 7F06590219F7FEA40077FF95 /* Controller */, - 7F06590019F7FE750077FF95 /* Model */, - 7F14A0031A13B9A6001C1ECB /* flags */, + C8739DC71D2A653F00A89F3C /* Classes */, + C89C60131D0FF61E002AAAD2 /* Resources */, 7F83F15319F154F000C53328 /* Supporting Files */, ); path = SAPTracker; @@ -1121,10 +1142,17 @@ 7F83F15319F154F000C53328 /* Supporting Files */ = { isa = PBXGroup; children = ( + C85291511D48FB91009E9A9D /* Localizable.strings */, + C8D5E81C1D479FA800DA0D61 /* Main.storyboard */, + 9ECBDDAD1C9C4F0300F76AEB /* LaunchScreen.storyboard */, + 7F4D2F531A1C8EE50038E7D1 /* Images.xcassets */, + 7FD9D3021A1236080058FEAD /* Extensions.swift */, + 9E95C3D51C723AB30016632B /* Constants.swift */, C8603D491C528832002B2F28 /* Acknowledgements.markdown */, 7F83F15419F154F000C53328 /* Info.plist */, 7F03FD3F19FA4D7400FA1327 /* bridge.h */, C8A4400A1C18153600DF70A0 /* Settings.bundle */, + C8F1B1E01D488B6D004C3379 /* Translation.swift */, ); name = "Supporting Files"; sourceTree = ""; @@ -1157,15 +1185,221 @@ name = JSON; sourceTree = ""; }; - C8B31F781B68DAD400C8A809 /* Products */ = { + C852BAA91CF736440093B0C5 /* Preferences */ = { isa = PBXGroup; children = ( - C89A171C1B6A27CF00CE6814 /* libAFNetworkActivityLogger.a */, - C89A171E1B6A27CF00CE6814 /* libAFNetworking.a */, - C8B31F7E1B68DAD500C8A809 /* libPods.a */, - C8603D4F1C528832002B2F28 /* libTSMarkdownParser.a */, + C852BAAA1CF736680093B0C5 /* Preferences.swift */, ); - name = Products; + name = Preferences; + sourceTree = ""; + }; + C8739D8B1D23C01500A89F3C /* Managers */ = { + isa = PBXGroup; + children = ( + 7F2C605919F160E400C32D93 /* LocationManager.swift */, + 7F1B66F81A0CDCF600904A41 /* BatteryManager.swift */, + C852BAA11CF5E1EA0093B0C5 /* RequestManager.swift */, + ); + name = Managers; + sourceTree = ""; + }; + C8739DC71D2A653F00A89F3C /* Classes */ = { + isa = PBXGroup; + children = ( + 7F06590019F7FE750077FF95 /* CoreData */, + 7F06590219F7FEA40077FF95 /* DataController */, + C8739D8B1D23C01500A89F3C /* Managers */, + C852BAA91CF736440093B0C5 /* Preferences */, + 7F06590119F7FE920077FF95 /* ViewController */, + C89C5FC31D06A269002AAAD2 /* Views */, + ); + name = Classes; + sourceTree = ""; + }; + C8739E101D2BF13200A89F3C /* Data */ = { + isa = PBXGroup; + children = ( + 7F0658FE19F7EE910077FF95 /* RegattaData.swift */, + C8739E111D2BF14F00A89F3C /* EventData.swift */, + C8739E131D2BF16300A89F3C /* LeaderboardData.swift */, + C8739E151D2BF17900A89F3C /* CompetitorData.swift */, + C8739E171D2BF2DC00A89F3C /* BaseData.swift */, + C8739E1B1D2D5F1700A89F3C /* LocationData.swift */, + C8BFCCC31D51C53500FC1A27 /* TeamData.swift */, + ); + name = Data; + sourceTree = ""; + }; + C89C5FC31D06A269002AAAD2 /* Views */ = { + isa = PBXGroup; + children = ( + 7F193A901A39E54600D71773 /* GPSAccuracyView.swift */, + C89C5FC41D06A289002AAAD2 /* GradientView.swift */, + C8BFCCCB1D523C5D00FC1A27 /* TitleView.swift */, + ); + name = Views; + sourceTree = ""; + }; + C89C5FC61D06CE62002AAAD2 /* Tracking */ = { + isa = PBXGroup; + children = ( + C89C5FC81D06CEA0002AAAD2 /* Cells */, + C89C5FC71D06CE87002AAAD2 /* Pages */, + 7F1875B21A10F1B800C25BE0 /* TrackingViewController.swift */, + 7F8B8D3E1A37356C00C34B88 /* TrackingPageViewController.swift */, + ); + name = Tracking; + sourceTree = ""; + }; + C89C5FC71D06CE87002AAAD2 /* Pages */ = { + isa = PBXGroup; + children = ( + 7F193A8E1A39ACF500D71773 /* TimerViewController.swift */, + 7F8B8D401A373B0200C34B88 /* SpeedViewController.swift */, + 7F8B8D421A373D4400C34B88 /* CourseViewController.swift */, + ); + name = Pages; + sourceTree = ""; + }; + C89C5FC81D06CEA0002AAAD2 /* Cells */ = { + isa = PBXGroup; + children = ( + C89C5FC91D06CECD002AAAD2 /* TrackingViewStatusCell.swift */, + C89C5FCB1D06CF0C002AAAD2 /* TrackingViewGPSAccuracyCell.swift */, + C89C5FCD1D06CF26002AAAD2 /* TrackingViewGPSFixesCell.swift */, + C89C5FCF1D06CF46002AAAD2 /* TrackingViewModeCell.swift */, + ); + name = Cells; + sourceTree = ""; + }; + C89C60101D0FF036002AAAD2 /* Regatta */ = { + isa = PBXGroup; + children = ( + 7F99DE3B1A126554009B3619 /* RegattaViewController.swift */, + 7F950A901A35E967003C8C5C /* LeaderboardViewController.swift */, + C89C5FC61D06CE62002AAAD2 /* Tracking */, + ); + name = Regatta; + sourceTree = ""; + }; + C89C60131D0FF61E002AAAD2 /* Resources */ = { + isa = PBXGroup; + children = ( + 7F14A0031A13B9A6001C1ECB /* Flags */, + C89C60141D0FF63C002AAAD2 /* Fonts */, + ); + name = Resources; + sourceTree = ""; + }; + C89C60141D0FF63C002AAAD2 /* Fonts */ = { + isa = PBXGroup; + children = ( + 7F87CA9D1A2CCE8B0076C617 /* OpenSans-Bold.ttf */, + 7F87CA9E1A2CCE8B0076C617 /* OpenSans-Light.ttf */, + 7F87CA9F1A2CCE8B0076C617 /* OpenSans-Regular.ttf */, + 7F87CAA01A2CCE8B0076C617 /* OpenSans-Semibold.ttf */, + ); + name = Fonts; + sourceTree = ""; + }; + C8BFCC1B1D50F17800FC1A27 /* SMTWiFiStatus */ = { + isa = PBXGroup; + children = ( + C8F71EF11D86A15F00826DE4 /* SMTWiFiStatus.h */, + C8F71EF21D86A15F00826DE4 /* SMTWiFiStatus.m */, + ); + name = SMTWiFiStatus; + path = ..; + sourceTree = ""; + }; + C8F71EA31D8691F700826DE4 /* Libraries */ = { + isa = PBXGroup; + children = ( + C8BFCC1B1D50F17800FC1A27 /* SMTWiFiStatus */, + C8F71EA41D8691F700826DE4 /* AFNetworking */, + C8F71EB81D8691F700826DE4 /* SVProgressHUD */, + C8F71EC31D8691F700826DE4 /* TSMarkdownParser */, + C8F71EC71D8691F700826DE4 /* UIKit+AFNetworking */, + ); + path = Libraries; + sourceTree = ""; + }; + C8F71EA41D8691F700826DE4 /* AFNetworking */ = { + isa = PBXGroup; + children = ( + C8F71EA51D8691F700826DE4 /* AFHTTPRequestOperation.h */, + C8F71EA61D8691F700826DE4 /* AFHTTPRequestOperation.m */, + C8F71EA71D8691F700826DE4 /* AFHTTPRequestOperationManager.h */, + C8F71EA81D8691F700826DE4 /* AFHTTPRequestOperationManager.m */, + C8F71EA91D8691F700826DE4 /* AFHTTPSessionManager.h */, + C8F71EAA1D8691F700826DE4 /* AFHTTPSessionManager.m */, + C8F71EAB1D8691F700826DE4 /* AFNetworking.h */, + C8F71EAC1D8691F700826DE4 /* AFNetworkReachabilityManager.h */, + C8F71EAD1D8691F700826DE4 /* AFNetworkReachabilityManager.m */, + C8F71EAE1D8691F700826DE4 /* AFSecurityPolicy.h */, + C8F71EAF1D8691F700826DE4 /* AFSecurityPolicy.m */, + C8F71EB01D8691F700826DE4 /* AFURLConnectionOperation.h */, + C8F71EB11D8691F700826DE4 /* AFURLConnectionOperation.m */, + C8F71EB21D8691F700826DE4 /* AFURLRequestSerialization.h */, + C8F71EB31D8691F700826DE4 /* AFURLRequestSerialization.m */, + C8F71EB41D8691F700826DE4 /* AFURLResponseSerialization.h */, + C8F71EB51D8691F700826DE4 /* AFURLResponseSerialization.m */, + C8F71EB61D8691F700826DE4 /* AFURLSessionManager.h */, + C8F71EB71D8691F700826DE4 /* AFURLSessionManager.m */, + ); + path = AFNetworking; + sourceTree = ""; + }; + C8F71EB81D8691F700826DE4 /* SVProgressHUD */ = { + isa = PBXGroup; + children = ( + C8F71EB91D8691F700826DE4 /* SVIndefiniteAnimatedView.h */, + C8F71EBA1D8691F700826DE4 /* SVIndefiniteAnimatedView.m */, + C8F71EBB1D8691F700826DE4 /* SVProgressAnimatedView.h */, + C8F71EBC1D8691F700826DE4 /* SVProgressAnimatedView.m */, + C8F71EBD1D8691F700826DE4 /* SVProgressHUD-Prefix.pch */, + C8F71EBE1D8691F700826DE4 /* SVProgressHUD.bundle */, + C8F71EBF1D8691F700826DE4 /* SVProgressHUD.h */, + C8F71EC01D8691F700826DE4 /* SVProgressHUD.m */, + C8F71EC11D8691F700826DE4 /* SVRadialGradientLayer.h */, + C8F71EC21D8691F700826DE4 /* SVRadialGradientLayer.m */, + ); + path = SVProgressHUD; + sourceTree = ""; + }; + C8F71EC31D8691F700826DE4 /* TSMarkdownParser */ = { + isa = PBXGroup; + children = ( + C8F71EC41D8691F700826DE4 /* TSMarkdownParser-Prefix.pch */, + C8F71EC51D8691F700826DE4 /* TSMarkdownParser.h */, + C8F71EC61D8691F700826DE4 /* TSMarkdownParser.m */, + ); + path = TSMarkdownParser; + sourceTree = ""; + }; + C8F71EC71D8691F700826DE4 /* UIKit+AFNetworking */ = { + isa = PBXGroup; + children = ( + C8F71EC81D8691F700826DE4 /* AFNetworkActivityIndicatorManager.h */, + C8F71EC91D8691F700826DE4 /* AFNetworkActivityIndicatorManager.m */, + C8F71ECA1D8691F700826DE4 /* UIActivityIndicatorView+AFNetworking.h */, + C8F71ECB1D8691F700826DE4 /* UIActivityIndicatorView+AFNetworking.m */, + C8F71ECC1D8691F700826DE4 /* UIAlertView+AFNetworking.h */, + C8F71ECD1D8691F700826DE4 /* UIAlertView+AFNetworking.m */, + C8F71ECE1D8691F700826DE4 /* UIButton+AFNetworking.h */, + C8F71ECF1D8691F700826DE4 /* UIButton+AFNetworking.m */, + C8F71ED01D8691F700826DE4 /* UIImage+AFNetworking.h */, + C8F71ED11D8691F700826DE4 /* UIImageView+AFNetworking.h */, + C8F71ED21D8691F700826DE4 /* UIImageView+AFNetworking.m */, + C8F71ED31D8691F700826DE4 /* UIKit+AFNetworking.h */, + C8F71ED41D8691F700826DE4 /* UIProgressView+AFNetworking.h */, + C8F71ED51D8691F700826DE4 /* UIProgressView+AFNetworking.m */, + C8F71ED61D8691F700826DE4 /* UIRefreshControl+AFNetworking.h */, + C8F71ED71D8691F700826DE4 /* UIRefreshControl+AFNetworking.m */, + C8F71ED81D8691F700826DE4 /* UIWebView+AFNetworking.h */, + C8F71ED91D8691F700826DE4 /* UIWebView+AFNetworking.m */, + ); + path = "UIKit+AFNetworking"; sourceTree = ""; }; /* End PBXGroup section */ @@ -1183,7 +1417,6 @@ buildRules = ( ); dependencies = ( - C8B31F841B68DAEE00C8A809 /* PBXTargetDependency */, ); name = SAPTracker; productName = SAPTracker; @@ -1219,6 +1452,7 @@ TargetAttributes = { 7F83F14F19F154F000C53328 = { CreatedOnToolsVersion = 6.0.1; + DevelopmentTeam = RRE8EFVCE3; }; 7F83F16419F154F000C53328 = { CreatedOnToolsVersion = 6.0.1; @@ -1238,12 +1472,6 @@ mainGroup = 7F83F14719F154F000C53328; productRefGroup = 7F83F15119F154F000C53328 /* Products */; projectDirPath = ""; - projectReferences = ( - { - ProductGroup = C8B31F781B68DAD400C8A809 /* Products */; - ProjectRef = C8B31F771B68DAD400C8A809 /* Pods.xcodeproj */; - }, - ); projectRoot = ""; targets = ( 7F83F14F19F154F000C53328 /* SAPTracker */, @@ -1252,37 +1480,6 @@ }; /* End PBXProject section */ -/* Begin PBXReferenceProxy section */ - C8603D4F1C528832002B2F28 /* libTSMarkdownParser.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libTSMarkdownParser.a; - remoteRef = C8603D4E1C528832002B2F28 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - C89A171C1B6A27CF00CE6814 /* libAFNetworkActivityLogger.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libAFNetworkActivityLogger.a; - remoteRef = C89A171B1B6A27CF00CE6814 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - C89A171E1B6A27CF00CE6814 /* libAFNetworking.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libAFNetworking.a; - remoteRef = C89A171D1B6A27CF00CE6814 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - C8B31F7E1B68DAD500C8A809 /* libPods.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libPods.a; - remoteRef = C8B31F7D1B68DAD500C8A809 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - /* Begin PBXResourcesBuildPhase section */ 7F83F14E19F154F000C53328 /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -1366,7 +1563,6 @@ 7F14A15E1A13B9A6001C1ECB /* ER.png in Resources */, 7F14A12F1A13B9A6001C1ECB /* BB.png in Resources */, 7F14A13B1A13B9A6001C1ECB /* BR.png in Resources */, - 7F83F15B19F154F000C53328 /* Main.storyboard in Resources */, 7F14A1E01A13B9A6001C1ECB /* SH.png in Resources */, 7F14A1261A13B9A6001C1ECB /* AQ.png in Resources */, 7F14A1A41A13B9A6001C1ECB /* MA.png in Resources */, @@ -1375,7 +1571,6 @@ 7F14A1351A13B9A6001C1ECB /* BI.png in Resources */, 7F14A1BB1A13B9A6001C1ECB /* NA.png in Resources */, 7F14A1B71A13B9A6001C1ECB /* MW.png in Resources */, - 7F87DDDB1A97339300704AC4 /* Localizable.strings in Resources */, 7F14A1711A13B9A6001C1ECB /* GN.png in Resources */, 7F14A19C1A13B9A6001C1ECB /* LICENSE.txt in Resources */, 7F14A18C1A13B9A6001C1ECB /* JP.png in Resources */, @@ -1402,6 +1597,7 @@ 7F14A17C1A13B9A6001C1ECB /* HR.png in Resources */, 7F14A11F1A13B9A6001C1ECB /* AF.png in Resources */, 7F14A1D31A13B9A6001C1ECB /* PW.png in Resources */, + C8F71EE51D8691F700826DE4 /* SVProgressHUD.bundle in Resources */, 7F14A1871A13B9A6001C1ECB /* IS.png in Resources */, 7F14A1DA1A13B9A6001C1ECB /* SA.png in Resources */, 7F14A1BD1A13B9A6001C1ECB /* NE.png in Resources */, @@ -1440,6 +1636,7 @@ 7F14A1561A13B9A6001C1ECB /* DK.png in Resources */, 7F14A18B1A13B9A6001C1ECB /* JO.png in Resources */, 7F14A1441A13B9A6001C1ECB /* CF.png in Resources */, + C852914F1D48FB91009E9A9D /* Localizable.strings in Resources */, 7F14A1BC1A13B9A6001C1ECB /* NC.png in Resources */, 7F14A1FA1A13B9A6001C1ECB /* TV.png in Resources */, 7F14A1EA1A13B9A6001C1ECB /* SV.png in Resources */, @@ -1478,6 +1675,7 @@ 7F14A1FC1A13B9A6001C1ECB /* TZ.png in Resources */, 7F14A1A91A13B9A6001C1ECB /* MG.png in Resources */, 7F4D2F541A1C8EE50038E7D1 /* Images.xcassets in Resources */, + C8D5E81D1D479FA800DA0D61 /* Main.storyboard in Resources */, 7F14A1D51A13B9A6001C1ECB /* QA.png in Resources */, 7F14A10A1A13B9A6001C1ECB /* _abkhazia.png in Resources */, 7F14A1851A13B9A6001C1ECB /* IQ.png in Resources */, @@ -1525,7 +1723,6 @@ 7F14A12B1A13B9A6001C1ECB /* AW.png in Resources */, 7F14A10D1A13B9A6001C1ECB /* _commonwealth.png in Resources */, 7F14A1521A13B9A6001C1ECB /* CY.png in Resources */, - 7F87DDE01A973C7400704AC4 /* eula-ios.html in Resources */, 7F14A1391A13B9A6001C1ECB /* BN.png in Resources */, 7F14A1231A13B9A6001C1ECB /* AM.png in Resources */, 7F14A10F1A13B9A6001C1ECB /* _gosquared.png in Resources */, @@ -1597,38 +1794,79 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + C8F71EDA1D8691F700826DE4 /* AFHTTPRequestOperation.m in Sources */, 7F1875B31A10F1B800C25BE0 /* TrackingViewController.swift in Sources */, + C8739E081D2AA2A500A89F3C /* Leaderboard+CoreDataProperties.swift in Sources */, + C8739E121D2BF14F00A89F3C /* EventData.swift in Sources */, + C8F71EDF1D8691F700826DE4 /* AFURLConnectionOperation.m in Sources */, + C8F71EE31D8691F700826DE4 /* SVIndefiniteAnimatedView.m in Sources */, + C8739E0F1D2BEE7900A89F3C /* RegattaController.swift in Sources */, + C8739E1C1D2D5F1700A89F3C /* LocationData.swift in Sources */, 7F83F15819F154F000C53328 /* HomeViewController.swift in Sources */, 7F8B8D431A373D4400C34B88 /* CourseViewController.swift in Sources */, 7FAFA7951A126B5700D230F1 /* AboutViewController.swift in Sources */, + C8739E161D2BF17900A89F3C /* CompetitorData.swift in Sources */, + C8739E0A1D2AA2A500A89F3C /* Competitor+CoreDataProperties.swift in Sources */, + C8739E0C1D2AA2A500A89F3C /* Event+CoreDataProperties.swift in Sources */, + C8739E071D2AA2A500A89F3C /* GPSFix.swift in Sources */, + C8F71EEE1D8691F700826DE4 /* UIProgressView+AFNetworking.m in Sources */, 7F44095B19F65B5B0021BF22 /* CoreData.xcdatamodeld in Sources */, + C89C5FD01D06CF46002AAAD2 /* TrackingViewModeCell.swift in Sources */, + C8F71EEA1D8691F700826DE4 /* UIActivityIndicatorView+AFNetworking.m in Sources */, 7F1B66F91A0CDCF600904A41 /* BatteryManager.swift in Sources */, - 7F03FD3E19FA44CD00FA1327 /* APIManager.swift in Sources */, - 7FA6551A19F6661900A1B92D /* DataManager.swift in Sources */, + 7FA6551A19F6661900A1B92D /* CoreDataManager.swift in Sources */, + C8F71EE71D8691F700826DE4 /* SVRadialGradientLayer.m in Sources */, + C852BAA21CF5E1EA0093B0C5 /* RequestManager.swift in Sources */, + C8F71EE01D8691F700826DE4 /* AFURLRequestSerialization.m in Sources */, C8BBAC791C52649E004CA551 /* LicenseViewController.swift in Sources */, - 7F23F0881A1A3DEF00F03F1C /* QRCodeManager.swift in Sources */, + C8BFCCC41D51C53500FC1A27 /* TeamData.swift in Sources */, + 7F23F0881A1A3DEF00F03F1C /* CheckInController.swift in Sources */, + C8F71EDC1D8691F700826DE4 /* AFHTTPSessionManager.m in Sources */, + C8F71EE91D8691F700826DE4 /* AFNetworkActivityIndicatorManager.m in Sources */, + C84936291D47645F000F30E8 /* HomeViewRegattaCell.swift in Sources */, 7F2C605A19F160E400C32D93 /* LocationManager.swift in Sources */, - 7FCDB6631A1636610075D7D9 /* Event.swift in Sources */, + C89C5FCC1D06CF0C002AAAD2 /* TrackingViewGPSAccuracyCell.swift in Sources */, + C8739E041D2AA2A500A89F3C /* Regatta+CoreDataProperties.swift in Sources */, + C89C5FCA1D06CECD002AAAD2 /* TrackingViewStatusCell.swift in Sources */, + C8739E051D2AA2A500A89F3C /* Regatta.swift in Sources */, + C8F71EDE1D8691F700826DE4 /* AFSecurityPolicy.m in Sources */, + C8F71EDB1D8691F700826DE4 /* AFHTTPRequestOperationManager.m in Sources */, 7F8B8D3F1A37356C00C34B88 /* TrackingPageViewController.swift in Sources */, - 7FCDB6621A1636610075D7D9 /* GPSFix.swift in Sources */, + C84936181D40D295000F30E8 /* GPSFixController.swift in Sources */, 7F99DE3C1A126554009B3619 /* RegattaViewController.swift in Sources */, + C8BFCCCC1D523C5D00FC1A27 /* TitleView.swift in Sources */, + C8F71EF31D86A15F00826DE4 /* SMTWiFiStatus.m in Sources */, 7F8CC2081A10D47A00C56D7F /* SettingsViewController.swift in Sources */, - 7F4EEDBA1A6D2BAC0026F711 /* CheckIn.swift in Sources */, - 7F06590419F8094C0077FF95 /* DeviceUDIDManager.swift in Sources */, - 7F3AA7C81A1CD7D700F8861F /* SendGPSFixController.swift in Sources */, - 7FCDB6641A1636610075D7D9 /* LeaderBoard.swift in Sources */, - C8603D4A1C528832002B2F28 /* Acknowledgements.markdown in Sources */, + C8739E0D1D2AA2A500A89F3C /* Event.swift in Sources */, 7F8B8D411A373B0200C34B88 /* SpeedViewController.swift in Sources */, 9E95C3D61C723AB30016632B /* Constants.swift in Sources */, + C8F71EF01D8691F700826DE4 /* UIWebView+AFNetworking.m in Sources */, 7FD9D3031A1236080058FEAD /* Extensions.swift in Sources */, + C8739E091D2AA2A500A89F3C /* Leaderboard.swift in Sources */, + C8739E141D2BF16300A89F3C /* LeaderboardData.swift in Sources */, + C89C5FC51D06A289002AAAD2 /* GradientView.swift in Sources */, + C8F71EEF1D8691F700826DE4 /* UIRefreshControl+AFNetworking.m in Sources */, + C8F71EE21D8691F700826DE4 /* AFURLSessionManager.m in Sources */, + C8F71EDD1D8691F700826DE4 /* AFNetworkReachabilityManager.m in Sources */, + C852BAAB1CF736680093B0C5 /* Preferences.swift in Sources */, 7F0658FD19F7D6700077FF95 /* ScanViewController.swift in Sources */, - 7FCDB6651A1636610075D7D9 /* Competitor.swift in Sources */, - 7F87CAA71A2CD6BA0076C617 /* Appearance.m in Sources */, + C8F71EEC1D8691F700826DE4 /* UIButton+AFNetworking.m in Sources */, + C8F1B1E11D488B6D004C3379 /* Translation.swift in Sources */, + C8F71EE81D8691F700826DE4 /* TSMarkdownParser.m in Sources */, + C8739E061D2AA2A500A89F3C /* GPSFix+CoreDataProperties.swift in Sources */, 7F193A8F1A39ACF500D71773 /* TimerViewController.swift in Sources */, + C8739E181D2BF2DC00A89F3C /* BaseData.swift in Sources */, 7F83F15619F154F000C53328 /* AppDelegate.swift in Sources */, - 7F950A911A35E967003C8C5C /* LeaderBoardViewController.swift in Sources */, - 7F0658FF19F7EE910077FF95 /* QRCodeData.swift in Sources */, + 7F950A911A35E967003C8C5C /* LeaderboardViewController.swift in Sources */, + C8F71EED1D8691F700826DE4 /* UIImageView+AFNetworking.m in Sources */, + C8F71EEB1D8691F700826DE4 /* UIAlertView+AFNetworking.m in Sources */, + C89C5FCE1D06CF26002AAAD2 /* TrackingViewGPSFixesCell.swift in Sources */, + C8739E0B1D2AA2A500A89F3C /* Competitor.swift in Sources */, + C8F71EE11D8691F700826DE4 /* AFURLResponseSerialization.m in Sources */, + C8F71EE61D8691F700826DE4 /* SVProgressHUD.m in Sources */, + 7F0658FF19F7EE910077FF95 /* RegattaData.swift in Sources */, 7F193A911A39E54600D71773 /* GPSAccuracyView.swift in Sources */, + C8F71EE41D8691F700826DE4 /* SVProgressAnimatedView.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1648,41 +1886,18 @@ target = 7F83F14F19F154F000C53328 /* SAPTracker */; targetProxy = 7F83F16619F154F000C53328 /* PBXContainerItemProxy */; }; - C8B31F841B68DAEE00C8A809 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Pods; - targetProxy = C8B31F831B68DAEE00C8A809 /* PBXContainerItemProxy */; - }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ - 7F83F15919F154F000C53328 /* Main.storyboard */ = { + C85291511D48FB91009E9A9D /* Localizable.strings */ = { isa = PBXVariantGroup; children = ( - 7F83F15A19F154F000C53328 /* Base */, - C8CF3F181C526CCA00FB1604 /* de */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 7F87DDDD1A97339300704AC4 /* Localizable.strings */ = { - isa = PBXVariantGroup; - children = ( - 7F87DDDC1A97339300704AC4 /* Base */, - 7F87DDDF1A9733B200704AC4 /* de */, + C85291501D48FB91009E9A9D /* Base */, + C85FAA501D4F84460087C2A2 /* de */, ); name = Localizable.strings; sourceTree = ""; }; - 7F87DDE21A973C7400704AC4 /* eula-ios.html */ = { - isa = PBXVariantGroup; - children = ( - 7F87DDE11A973C7400704AC4 /* Base */, - 7F87DDE31A973C7900704AC4 /* de */, - ); - name = "eula-ios.html"; - sourceTree = ""; - }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ @@ -1722,17 +1937,9 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(PROJECT_DIR)/Pods/**", - "${PROJECT_DIR}/Pods/build/${BUILD_STYLE}-${PLATFORM_NAME}/**", - ); IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LIBRARY_SEARCH_PATHS = "${PROJECT_DIR}/Pods/build/${BUILD_STYLE}-${PLATFORM_NAME}/**"; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; - PODS_ROOT = "$(PROJECT_DIR)/Pods"; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; @@ -1767,17 +1974,9 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(PROJECT_DIR)/Pods/**", - "${PROJECT_DIR}/Pods/build/${BUILD_STYLE}-${PLATFORM_NAME}/**", - ); IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LIBRARY_SEARCH_PATHS = "${PROJECT_DIR}/Pods/build/${BUILD_STYLE}-${PLATFORM_NAME}/**"; MTL_ENABLE_DEBUG_INFO = NO; ONLY_ACTIVE_ARCH = NO; - PODS_ROOT = "$(PROJECT_DIR)/Pods"; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; @@ -1785,20 +1984,15 @@ }; 7F83F17019F154F000C53328 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = EA431711E588F5A2B31A62AC /* Pods.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; INFOPLIST_FILE = SAPTracker/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_SWIFT_FLAGS = "-D DEBUG"; - PODS_ROOT = "$(PROJECT_DIR)/Pods"; PRODUCT_BUNDLE_IDENTIFIER = "com.sap.sailing.ios.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; SWIFT_OBJC_BRIDGING_HEADER = SAPTracker/bridge.h; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -1806,20 +2000,15 @@ }; 7F83F17119F154F000C53328 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = CF98F25F363113C51C7CB1F3 /* Pods.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; INFOPLIST_FILE = SAPTracker/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_SWIFT_FLAGS = ""; - PODS_ROOT = "$(PROJECT_DIR)/Pods"; PRODUCT_BUNDLE_IDENTIFIER = "com.sap.sailing.ios.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; SWIFT_OBJC_BRIDGING_HEADER = SAPTracker/bridge.h; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -1827,20 +2016,14 @@ }; 7F83F17319F154F000C53328 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = EA431711E588F5A2B31A62AC /* Pods.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); INFOPLIST_FILE = SAPTrackerTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PODS_ROOT = "$(PROJECT_DIR)/Pods"; PRODUCT_BUNDLE_IDENTIFIER = "com.sap.sailing.ios.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = SAPTracker/bridge.h; @@ -1850,16 +2033,10 @@ }; 7F83F17419F154F000C53328 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = CF98F25F363113C51C7CB1F3 /* Pods.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); INFOPLIST_FILE = SAPTrackerTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PODS_ROOT = "$(PROJECT_DIR)/Pods"; PRODUCT_BUNDLE_IDENTIFIER = "com.sap.sailing.ios.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = SAPTracker/bridge.h; @@ -1903,9 +2080,10 @@ 7F44095919F65B5B0021BF22 /* CoreData.xcdatamodeld */ = { isa = XCVersionGroup; children = ( + C8739D9A1D25317100A89F3C /* CoreData 2.xcdatamodel */, 7F44095A19F65B5B0021BF22 /* CoreData.xcdatamodel */, ); - currentVersion = 7F44095A19F65B5B0021BF22 /* CoreData.xcdatamodel */; + currentVersion = C8739D9A1D25317100A89F3C /* CoreData 2.xcdatamodel */; path = CoreData.xcdatamodeld; sourceTree = ""; versionGroupType = wrapper.xcdatamodel; diff --git a/ios/SAPTracker/src/xcode/SAPTracker/APIManager.swift b/ios/SAPTracker/src/xcode/SAPTracker/APIManager.swift deleted file mode 100644 index ad3b99ccbe2..00000000000 --- a/ios/SAPTracker/src/xcode/SAPTracker/APIManager.swift +++ /dev/null @@ -1,195 +0,0 @@ -// -// APIManager.swift -// SAPTracker -// -// Created by computing on 24/10/14. -// Copyright (c) 2014 com.sap.sailing. All rights reserved. -// - -import Foundation -import CoreData - -public class APIManager: NSObject { - - struct NotificationType { - static let networkAvailabilityChanged = "networkAvailabilityChanged" - } - - /* Constants */ - struct Constants { - /* Max number of fix objects to be sent per POST request. */ - static let maxSendGPSFix = 100 - } - - /* Server URL */ - private var serverUrlString: String? - - /* Base url of all requests, contains serverUrlString */ - private let baseUrlString = "/sailingserver/api/v1" - - /* AFNetworking operation manager */ - private var manager: AFHTTPRequestOperationManager? - - var networkAvailable: Bool { - get { - if manager == nil { - return false - } - return !manager!.operationQueue.suspended - } - } - - /* Singleton */ - public class var sharedManager: APIManager { - struct Singleton { - static let sharedManager = APIManager() - } - return Singleton.sharedManager - } - - /* Sets base URL for all requests. Request and response are JSON. Starts reachability listener. Starts timer for uploading data. */ - public func initManager(serverUrlString: String) { - if self.serverUrlString == serverUrlString { - return - } - - self.serverUrlString = serverUrlString - - manager = AFHTTPRequestOperationManager(baseURL: NSURL(string: self.serverUrlString!)) // baseUrl needed for checking reachability - - // encode/decode body as JSON - manager!.requestSerializer = AFJSONRequestSerializer() as AFHTTPRequestSerializer - manager!.responseSerializer = AFJSONResponseSerializer() as AFHTTPResponseSerializer - - // set up reachability - let operationQueue = manager!.operationQueue - manager!.reachabilityManager.setReachabilityStatusChangeBlock({(status) -> Void in - switch (status) { - case AFNetworkReachabilityStatus.ReachableViaWWAN, AFNetworkReachabilityStatus.ReachableViaWiFi: - operationQueue?.suspended = false - break - default: - operationQueue?.suspended = true - } - - // send notification (e.g. to tracker view controller) - let notification = NSNotification(name: NotificationType.networkAvailabilityChanged, object: self) - NSNotificationQueue.defaultQueue().enqueueNotification(notification, postingStyle: NSPostingStyle.PostASAP) - }) - manager!.reachabilityManager.startMonitoring() - } - - // MARK: - REST API - - /* Get event */ - public func getEvent(eventId: String!, success: (AFHTTPRequestOperation!, AnyObject!) -> Void, failure: (AFHTTPRequestOperation!, AnyObject!) -> Void) { - let urlString = baseUrlString + "/events/\(eventId)" - manager!.GET(urlString, parameters: nil, success: success, failure: failure) - } - - /* Get leader board */ - public func getLeaderBoard(leaderBoardName: String!, success: (AFHTTPRequestOperation!, AnyObject!) -> Void, failure: (AFHTTPRequestOperation!, AnyObject!) -> Void) { - let urlString = baseUrlString + "/leaderboards/\(leaderBoardName.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)" - manager!.GET(urlString, parameters: nil, success: success, failure: failure) - } - - /* Get competitor */ - public func getCompetitor(competitorId: String!, success: (AFHTTPRequestOperation!, AnyObject!) -> Void, failure: (AFHTTPRequestOperation!, AnyObject!) -> Void) { - let urlString = baseUrlString + "/competitors/\(competitorId)" - manager!.GET(urlString, parameters: nil, success: success, failure: failure) - } - - /* Get team */ - public func getTeam(competitorId: String!, success: (AFHTTPRequestOperation!, AnyObject!) -> Void, failure: (AFHTTPRequestOperation!, AnyObject!) -> Void) { - let urlString = baseUrlString + "/competitors/\(competitorId)/team" - manager!.GET(urlString, parameters: nil, success: success, failure: failure) - } - - public func teamImage(competitorId: String!, result: (imageUrl: String?) -> Void) { - getTeam(competitorId, success: { (operation, teamResponseObject) -> Void in - - if let team = teamResponseObject as? [String: AnyObject], - let imageUrl = team["imageUri"] as? String { - result(imageUrl: imageUrl) - } else { - result(imageUrl: nil) - } - - }, failure: { (operation, error) -> Void in - // No image & that's ok - result(imageUrl: nil) - }) - } - - /* Map a device to competitor. */ - public func checkIn(leaderBoardName: String!, competitorId: String!, deviceUuid: String!, pushDeviceId: String!, fromMillis: Int64!, success: (AFHTTPRequestOperation!, AnyObject!) -> Void, failure: (AFHTTPRequestOperation!, AnyObject!) -> Void) { - - let urlString = baseUrlString + "/leaderboards/\(leaderBoardName.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())!)/device_mappings/start" - - var body = [String: AnyObject]() - body["competitorId"] = competitorId - body["deviceType"] = "ios" - body["deviceUuid"] = deviceUuid - body["pushDeviceId"] = pushDeviceId - body["fromMillis"] = NSNumber(longLong: fromMillis) - - manager!.POST(urlString, parameters: body, success: success, failure: failure) - } - - /* Disconnect a device from competitor. */ - public func checkOut(leaderBoardName: String!, competitorId: String!, deviceUuid: String!, toMillis: Int64!, success:(AFHTTPRequestOperation!, AnyObject!) -> Void, failure: (AFHTTPRequestOperation!, AnyObject!) -> Void) { - - let urlString = baseUrlString + "/leaderboards/\(leaderBoardName.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())!)/device_mappings/end" - - var body = [String: AnyObject]() - body["competitorId"] = competitorId - body["deviceUuid"] = deviceUuid - body["toMillis"] = NSNumber(longLong: toMillis) - - manager!.POST(urlString, parameters: body, success: success, failure: failure) - } - - /* Send GPS location to server. Delete row from cache. */ - public func postGPSFixes(deviceUuid: String!, gpsFixes: [GPSFix]!, success: (AFHTTPRequestOperation!, AnyObject!) -> Void, failure: (AFHTTPRequestOperation!, AnyObject!) -> Void) { - if gpsFixes.count == 0 { - return - } - - let urlString = baseUrlString + "/gps_fixes" - - var body = [String: AnyObject]() - body["deviceUuid"] = deviceUuid - var array: [[String: AnyObject]] = [] - for gpsFix in gpsFixes { - array.append(gpsFix.dictionary()) - } - body["fixes"] = array - - manager!.POST(urlString, parameters: body, success: success, failure: failure) - } - - - /* Send GPS location to server. Delete row from cache. */ - public func postTeamImage(competitorId: String!, imageData: NSData!, success: (AnyObject!) -> Void, failure: (AnyObject!) -> Void) { - let urlString = baseUrlString + "/competitors/\(competitorId)/team/image" - let configuration = NSURLSessionConfiguration.defaultSessionConfiguration() - let sessionManager = AFURLSessionManager(sessionConfiguration: configuration) - sessionManager.responseSerializer = AFJSONResponseSerializer() as AFHTTPResponseSerializer - let url = NSURL(string: self.serverUrlString! + urlString) - let request = NSMutableURLRequest(URL: url!) - request.setValue("image/jpeg", forHTTPHeaderField: "Content-Type") - request.HTTPBody = imageData; - request.HTTPMethod = "POST" - let dataTask = sessionManager.dataTaskWithRequest(request, completionHandler:{ (response, responseObject, error) in - if (error != nil) { - failure(error) - } - else { - success(responseObject) - } - }) - dataTask.resume(); - - } - -} \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker/AboutViewController.swift b/ios/SAPTracker/src/xcode/SAPTracker/AboutViewController.swift index a7f68a6caab..833985296f3 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/AboutViewController.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/AboutViewController.swift @@ -2,43 +2,62 @@ // AboutViewController.swift // SAPTracker // -// Created by computing on 11/11/14. -// Copyright (c) 2014 com.sap.sailing. All rights reserved. +// Created by Raimund Wege on 04.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. // import Foundation class AboutViewController: UIViewController { - @IBOutlet weak var versionDescriptionLabel: UILabel! + @IBOutlet weak var partnershipTextView: UITextView! + @IBOutlet weak var licenseInformationButton: UIButton! + @IBOutlet weak var termsButton: UIButton! + @IBOutlet weak var versionTitleLabel: UILabel! @IBOutlet weak var versionLabel: UILabel! - @IBOutlet weak var textView: UITextView! override func viewDidLoad() { - super.viewDidLoad(); - versionDescriptionLabel.text = NSLocalizedString("Version", comment: "") - if let text = NSBundle.mainBundle().infoDictionary?["CFBundleVersion"] as? String { - versionLabel.text = text - } else { - versionLabel.text = "-" - } - - // add logo to top left - let imageView = UIImageView(image: UIImage(named: "sap_logo")) - let barButtonItem = UIBarButtonItem(customView: imageView) - navigationItem.leftBarButtonItem = barButtonItem + super.viewDidLoad() + setup() } - - override func viewDidLayoutSubviews() { - textView.scrollRectToVisible(CGRect(x: 0, y: 0, width: 1, height: 1), animated: false) - } - @IBAction func done(sender: AnyObject) { + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + partnershipTextView.scrollRectToVisible(CGRect(x: 0, y: 0, width: 1, height: 1), animated: false) + } + + // MARK: - Setup + + private func setup() { + setupLocalization() + setupNavigationBar() + setupVersion() + } + + private func setupLocalization() { + navigationItem.title = Translation.AboutView.Title.String + partnershipTextView.text = Translation.AboutView.PartnershipTextView.Text.String + licenseInformationButton.setTitle(Translation.LicenseView.Title.String, forState: .Normal) + termsButton.setTitle(Translation.AboutView.TermsButton.Title.String, forState: .Normal) + versionTitleLabel.text = Translation.AboutView.VersionTitleLabel.Text.String + } + + private func setupNavigationBar() { + navigationItem.leftBarButtonItem = UIBarButtonItem(customView: UIImageView(image: UIImage(named: "sap_logo"))) + } + + private func setupVersion() { + versionLabel.text = NSBundle.mainBundle().infoDictionary?["CFBundleVersion"] as? String ?? "-" + } + + // MARK: - Actions + + @IBAction func doneButtonTapped(sender: AnyObject) { presentingViewController!.dismissViewControllerAnimated(true, completion: nil) } - @IBAction func openEULA(sender: AnyObject) { - UIApplication.sharedApplication().openURL(URLs.EULA) + @IBAction func termsButtonTapped(sender: AnyObject) { + UIApplication.sharedApplication().openURL(URLs.Terms) } } \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Acknowledgements.markdown b/ios/SAPTracker/src/xcode/SAPTracker/Acknowledgements.markdown index dccc1675689..7450493bd52 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/Acknowledgements.markdown +++ b/ios/SAPTracker/src/xcode/SAPTracker/Acknowledgements.markdown @@ -1,51 +1,28 @@ # Acknowledgements + This application makes use of the following third party libraries: -## AFNetworkActivityLogger - -Copyright (c) 2013 AFNetworking (http://afnetworking.com/) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - ## AFNetworking Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com/) -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## SVProgressHUD + +Copyright (c) 2011-2016 Sam Vermette, Tobias Tiemerding and contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +A different license may apply to other resources included in this package, including Freepik Icons. Please consult their respective headers for the terms of their individual licenses. ## TSMarkdownParser @@ -53,21 +30,8 @@ The MIT License (MIT) Copyright (c) 2014 Tobias Sundstrand -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -Generated by CocoaPods - http://cocoapods.org +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/ios/SAPTracker/src/xcode/SAPTracker/AppDelegate.swift b/ios/SAPTracker/src/xcode/SAPTracker/AppDelegate.swift index 28a557af945..80ce0c947f6 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/AppDelegate.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/AppDelegate.swift @@ -11,79 +11,116 @@ import CoreData @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { - struct NotificationType { - static let openUrl = "openUrl" - } var window: UIWindow? - + + func application(application: UIApplication, performFetchWithCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) { + logInfo("\(#function)", info: "Background fetch started...") + var noData = true + var allSuccess = true + let regattas = CoreDataManager.sharedManager.fetchRegattas() + regattas?.forEach({ (regatta) in + if regatta.gpsFixes?.count > 0 { + noData = false + let gpsFixController = GPSFixController(regatta: regatta) + gpsFixController.sendAll({ (withSuccess) in + allSuccess = allSuccess && withSuccess + }) + } + }) + let fetchResult: UIBackgroundFetchResult = noData ? .NoData : allSuccess ? .NewData : .Failed + logInfo("\(#function)", info: "Background fetch completed with result: \(fetchResult.rawValue)") + completionHandler(fetchResult) + } + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { - - // set up connection logging for debug builds - #if DEBUG - AFNetworkActivityLogger.sharedLogger().startLogging() - AFNetworkActivityLogger.sharedLogger().level = AFHTTPRequestLoggerLevel.AFLoggerLevelDebug - #endif - - // initialize core data, migrate database if needed, or delete if migration needed but not possible - DataManager.sharedManager - - // start timer in case GPS fixes need to be sent - SendGPSFixController.sharedManager.timer() - - // set up styling - UINavigationBar.appearance().setBackgroundImage(UIImage(named: "navbar_bg"), forBarMetrics: UIBarMetrics.Default) - UINavigationBar.appearance().tintColor = UIColor.whiteColor() - UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor(), NSFontAttributeName: UIFont(name: "OpenSans-Bold", size: CGFloat(17.0))!] - UIPageControl.appearance().pageIndicatorTintColor = UIColor.lightGrayColor() - UIPageControl.appearance().currentPageIndicatorTintColor = UIColor.blackColor() - UIPageControl.appearance().backgroundColor = UIColor.whiteColor() - // needed for missing Swift method - Appearance.setAppearance() + setup() return true } func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool { - - let rootViewController = self.window!.rootViewController as! UINavigationController - rootViewController.popToRootViewControllerAnimated(false) - rootViewController.dismissViewControllerAnimated(false, completion: nil) + Preferences.newCheckInURL = urlStringForDeeplink(url) + return true + } + + func applicationWillResignActive(application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + CoreDataManager.sharedManager.saveContext() + } + + func applicationWillEnterForeground(application: UIApplication) { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + CoreDataManager.sharedManager.saveContext() + } + + // MARK: - Setup + + private func setup() { + setupAFNetworking() + setupBackgroundFetch() + setupCoreData() + setupNavigationBarApperance() + setupPageControlApperance() + setupSVProgressHUD() + } + + private func setupAFNetworking() { + AFNetworkActivityIndicatorManager.sharedManager().enabled = true + AFNetworkReachabilityManager.sharedManager().startMonitoring() + } + + private func setupBackgroundFetch() { + UIApplication.sharedApplication().setMinimumBackgroundFetchInterval(UIApplicationBackgroundFetchIntervalMinimum) + } + + private func setupCoreData() { + CoreDataManager.sharedManager // Initialize core data, migrate database if needed, or delete if migration needed but not possible + } + + private func setupNavigationBarApperance() { + UINavigationBar.appearance().tintColor = Colors.NavigationBarTintColor + UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName: Colors.NavigationBarTitleColor, NSFontAttributeName: Fonts.OpenSansBold17] + } + + private func setupPageControlApperance() { + UIPageControl.appearance().pageIndicatorTintColor = UIColor.lightGrayColor() + UIPageControl.appearance().currentPageIndicatorTintColor = UIColor.blackColor() + } + + private func setupSVProgressHUD() { + SVProgressHUD.setDefaultMaskType(.Gradient) + } + + // MARK: - Helper + + private func urlStringForDeeplink(url: NSURL) -> String { var urlString = url.absoluteString let appPrefix : String = "comsapsailingtracker://" + + // FIXME: - Two prefixes are not allowed + // Deeplink needs another structure (if possible) because of allowed characters in URL + // https:// -> http// + urlString = urlString.hasPrefix(appPrefix) ? urlString.substringFromIndex(appPrefix.endIndex) : urlString let httpPrefix : String = "http//" urlString = urlString.hasPrefix(httpPrefix) ? "http://" + urlString.substringFromIndex(httpPrefix.endIndex) : urlString let httpsPrefix : String = "https//" urlString = urlString.hasPrefix(httpsPrefix) ? "https://" + urlString.substringFromIndex(httpsPrefix.endIndex) : urlString - let notification = NSNotification(name: NotificationType.openUrl, object: self, userInfo:["url": urlString]) - NSNotificationQueue.defaultQueue().enqueueNotification(notification, postingStyle: NSPostingStyle.PostASAP) - return true + return urlString } - - func applicationWillResignActive(application: UIApplication) { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. - } - - func applicationDidEnterBackground(application: UIApplication) { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. - DataManager.sharedManager.saveContext() - } - - func applicationWillEnterForeground(application: UIApplication) { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. - } - - func applicationDidBecomeActive(application: UIApplication) { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. - } - - func applicationWillTerminate(application: UIApplication) { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. - DataManager.sharedManager.saveContext() - } - - + } - diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Appearance.h b/ios/SAPTracker/src/xcode/SAPTracker/Appearance.h deleted file mode 100644 index d9206e9f1ff..00000000000 --- a/ios/SAPTracker/src/xcode/SAPTracker/Appearance.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Appearance.h -// SAPTracker -// -// Created by computing on 01/12/14. -// Copyright (c) 2014 com.sap.sailing. All rights reserved. -// - -#import - -@interface Appearance : NSObject - -+ (void)setAppearance; - -@end diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Appearance.m b/ios/SAPTracker/src/xcode/SAPTracker/Appearance.m deleted file mode 100644 index e6c1ecd40ad..00000000000 --- a/ios/SAPTracker/src/xcode/SAPTracker/Appearance.m +++ /dev/null @@ -1,19 +0,0 @@ -// -// Appearance.m -// SAPTracker -// -// Created by computing on 01/12/14. -// Copyright (c) 2014 com.sap.sailing. All rights reserved. -// - -#import "Appearance.h" -#import - -@implementation Appearance - -+ (void)setAppearance { - [[UILabel appearanceWhenContainedIn:[UITableViewHeaderFooterView class], nil] setFont:[UIFont fontWithName:@"OpenSans-Bold" size:16]]; - [[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil]setTitleTextAttributes:@{NSFontAttributeName:[UIFont fontWithName:@"OpenSans" size:17]} forState:UIControlStateNormal]; -} - -@end diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Base.lproj/Localizable.strings b/ios/SAPTracker/src/xcode/SAPTracker/Base.lproj/Localizable.strings index aed83513de0..14e49d15af8 100644 Binary files a/ios/SAPTracker/src/xcode/SAPTracker/Base.lproj/Localizable.strings and b/ios/SAPTracker/src/xcode/SAPTracker/Base.lproj/Localizable.strings differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Base.lproj/Main.storyboard b/ios/SAPTracker/src/xcode/SAPTracker/Base.lproj/Main.storyboard deleted file mode 100644 index b93199fc460..00000000000 --- a/ios/SAPTracker/src/xcode/SAPTracker/Base.lproj/Main.storyboard +++ /dev/null @@ -1,1560 +0,0 @@ - - - - - - - - - - - OpenSans-Bold - OpenSans-Bold - OpenSans-Bold - OpenSans-Bold - OpenSans-Bold - OpenSans-Bold - OpenSans-Bold - OpenSans-Bold - OpenSans-Bold - - - OpenSans-Light - OpenSans-Light - OpenSans-Light - - - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - OpenSans - - - OpenSans-Semibold - OpenSans-Semibold - OpenSans-Semibold - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The SAP Sail InSight app supports live tracking of race boats by leveraging mobile phone technology, allowing the ability for friends and fans to follow racing whether onsite or online through live leader boards and 2D visualization. Following racing sailors can replay their races allowing the opportunity to review performance and optimize strategies all available at: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Cg - - - - - - - - - - - - - - - - - - - - - - - -Cg - - - - - - - - - - - - SAP supports US Sailing through the implementation of a range of innovative technology solutions, delivering analytics to help teams and sailors improve performance whilst also providing applications to help sailing operations run more efficiently. - - - - - - - - - - - - -Cg - - - - - - - - - - - - - - - - - - - - - - - -Cg - - - - - - - - - - - - As the national governing body for sailing, US Sailing provides leadership, integrity and growth for the sport including training and education programs for instructors and race officials alongside administration and oversight of competitive sailing across the country. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Base.lproj/eula-ios.html b/ios/SAPTracker/src/xcode/SAPTracker/Base.lproj/eula-ios.html deleted file mode 100644 index 47599f8eb96..00000000000 --- a/ios/SAPTracker/src/xcode/SAPTracker/Base.lproj/eula-ios.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - -

Please scroll down and read the following end user license agreement carefully. This is a legal agreement ("Agreement") between you and SAP SE which provides the terms of your use of the SAP Mobile Application ("Software"). By clicking "I Accept" or by installing and/or using the Software, you are agreeing to all of the terms and conditions stated in this Agreement. If You do not agree to these terms, do not click "agree", and do not use the Software.

-

1 Definitions

- -

"SAP" refers to SAP SE, for and on behalf of itself and its subsidiaries and affiliates as defined in Section 15 German Stock Corporation Act. "You" and "Your" refers to the individual that wishes to use the Software. "Apple" refers to Apple, Inc. and its majority owned affiliates.

- -

2 Supported Devices

- -

The Software supports certain Apple mobile devices, and data networks such as 3G, EDGE and WiFi, and enables users to access SAP Standard Software for use of specifically enabled business processes through such Apple mobile devices.

- -

3 License

- -

Subject to the terms, conditions and limitations stated in this Agreement and the Apple App Store Terms of Service, SAP grants You a personal, non-exclusive, non-transferable, non-sublicensable, revocable, limited license to run the Software on Your Apple mobile device solely for the purpose of the Software accessing SAP Backend Software. For the avoidance of doubt, this Agreement does not include a license for SAP Standard Software. You are not permitted to use the Software for any purpose other than as expressly permitted under this Agreement. SAP may audit Your use of the Software. You shall use the Software only in a manner consistent with this Agreement and the documentation (the "Documentation") which SAP may provide, in its sole discretion, in electronic and/or printed form with the Software and which can be found under http://service.sap.com.

- -

4 Intellectual Property

- -

SAP retains all ownership and intellectual property rights in the Software. You may not: a) remove or modify any marks or proprietary notices of SAP, b) provide or make the Software available to any third party, c) use the Software to provide third party training for SAP products, d) assign this Agreement or give or transfer the Software or an interest in them to another individual or entity, e) decompile, disassemble or reverse engineer (except to the extent permitted by applicable law) the Software, f) create derivative works of or based on the Software or g) use any SAP name, trademark or logo.

- -

5 User Content

- -

a) "User Content" means any communications, images, and all the material, data, and information that You upload or transmits through Software. -b) Company hereby grants SAP a perpetual and irrevocable, worldwide, fully paid-up and royalty free, non-exclusive, unlimited license, including the right to sublicense and assign to third parties, and right to store, use, copy, reproduce, fix, adapt, modify, improve, translate, reformat, create derivative works from, process, analyze, manufacture, introduce into circulation, commercialize, publish, distribute, license, sublicense, transfer, rent, lease, transmit, publicly display, publicly perform, or provide access to electronically, broadcast, communicate to the public by telecommunication, display, perform, enter into computer memory, and use and practice, in any way now known or in the future discovered, Your User Content as well as all modified and derivative works thereof. -c) By transmitting or submitting any User Content while using the Software, You affirm, represent and warrant that such transmission or submission is (i) accurate; (ii) not in violation of any laws, contractual restrictions or other third party rights, and that You have permission from any third party whose information or intellectual property is comprised in the User Content; and (iii) free of viruses, adware, spyware, worms or other malicious code. -d) You acknowledge and agree that any of Your personal information within such content will at all times be processed by SAP in accordance with its Privacy Policy (http://www.sap.com/corporate-en/our-company/legal/privacy.epx).

- -

6 Warranty

- -

As there is no charge for the license of the Software hereunder, You are not entitled to the elimination of any defects or to subsequent delivery of Software. SAP will compensate for loss or wasted anticipatory expenditure arising out of defects subject to the limitation of liability in section 7 herein.

- -

7 Liability

- -

7.1 SAP is liable for damages or wasted anticipatory expenditures, in tort or otherwise, only (a) under German product liability legislation, (b) for SAP’s gross negligence or intent, (c) for absence of an expressly assured or guaranteed quality, or (d) for personal injury. -7.2 Where SAP is liable for grossly negligent acts of its employees who are not directors or officers of SAP, SAP’s total liability for damages is limited to that liability and to not more than the quantum of loss that SAP ought, in the light of its knowledge of circumstances at the time this License Agreement was made, to have foreseen as typical in connection with provision and licensed use of Software. -7.3 Where SAP is liable under section 7.2, it is not liable for indirect loss, consequential damages, or loss of profit. -7.4 SAP and Licensee agree that the typical foreseeable quantum of loss cannot exceed €50,000 in any case. -7.5 Licensee undertakes to take appropriate steps to safeguard its data and programs, including without limitation making backup copies not less frequently than is recommended by SAP. Notwithstanding the other limitations of this section 7, SAP is not liable for the loss of data and its recreation, in so far as this would have been avoidable through observance of this obligation. -7.6 The benefit of exclusions and limitations in this section 7 also extends to claims of Customer against employees, contractors, and agents of SAP.

- -

8 Indemnification

- -

SAP will defend at its own expense any legal proceeding brought against You, to the extent that such proceeding is based on a claim that the use of the Software as permitted under this Agreement represents an infringement or misappropriation of a third party’s copyright, patent, or a trade secret, and will pay all damages and costs awarded by a court of final appeal attributable to such claim; provided, however, that You: a) provide notice of the claim promptly to SAP (but no later than one (1) month after You received notice of the claim), b) give SAP sole control of the defense and settlement of the claim, provided that You, at Your option and expense, may also be represented in the legal proceeding by independent counsel, c) provides to SAP, at SAP’s expense, all commercially reasonable information, assistance and authority to defend such claim and d) have not compromised or settled such proceeding without SAP’s prior written consent.SAP shall have no liability for any infringement or claim which results from the use of the Software provided hereunder in combination with any equipment, software or data not provided or approved by SAP. This section states the entire liability of SAP with respect to the indemnification of any intellectual property right infringement hereunder and there shall be no additional liability with respect to any alleged or proven infringement. Section 7 shall apply accordingly.

- -

9 Export

- -

The Software is subject to German, EU and US export control regulations. You confirm that: a) You will not use the Software for, and will not allow the Software to be used for, any purposes prohibited by German, EU and US law, including, without limitation, for the development, design, manufacture or production of nuclear, chemical or biological weapons of mass destruction, b) You are not located in a country that is subject to a U.S. Government embargo, or that has been designated by the U.S. Government as a "terrorist supporting" country, c) You are not a citizen, national or resident of, and are not under the control of, the government of: Cuba, Iran, Sudan, Iraq, North Korea, Syria, nor any other country to which the United States has prohibited export, d) You will not download or otherwise export or re-export the Software, directly or indirectly, neither to the above-mentioned countries nor to citizens, nationals or residents of those countries, e) You are not listed on the United States Department of Treasury lists of Specially Designated Nationals, Specially Designated Terrorists, and Specially Designated Narcotic Traffickers, nor listed on the United States Department of Commerce Table of Denial Orders or any other U.S. government list of prohibited or restricted parties and f) You will not download or otherwise export or re-export the Software, directly or indirectly, to persons on the above-mentioned lists.

- -

10 Data Protection

- -

SAP and You must comply with the provisions of the law of data protection. Where SAP is granted access (for example, for remote maintenance) to hardware and software that You use, it is not the intention that SAP process or use personal data for business purposes. Rather, transfer of personal data will only take place in exceptional circumstances, as an incidental effect of SAP’s performing its contractual duties. If in the course of contract maintenance SAP stores, processes, or uses personal data, it will comply with Your instructions in that respect. Additional remuneration is payable by You to the extent such instructions require goods, works, or services not included in the contract. SAP and You must implement the technical and organizational measures required by the German Federal Data Protection Act, section 9 and the schedule thereto, to protect personal data from misuse. SAP will deploy on work involving the processing of personal data only personnel bound to data secrecy in the meaning of the German Federal Data Protection Act, section 5. SAP will bind to the applicable provisions of the law of data protection any subcontractor with access to personal data. If the subcontractor is not domiciled in the European Union (EU), SAP will take steps to achieve a level of data protection that is appropriate in accordance with EU data protection requirements. You must ensure that all legal requirements on your part are met so that SAP can perform its contractual services without infringing the law. You acknowledge and agree that any of Your personal information will at all times be processed by SAP in accordance with its Privacy Policy (http://www.sap.com/corporate-en/our-company/legal/privacy.epx).

- -

11 Support

- -

SAP does not offer support for the Software other than – at its sole discretion - provision of updates, patches, bug fixes and new versions.

- -

12 Term and Termination

- -

You may terminate this Agreement by destroying all copies of the Software on Your Apple mobile device. SAP shall be entitled to terminate Your license to use the Software if You fail to comply with any of the terms of this Agreement. This Agreement terminates automatically upon termination or expiration of the SAP Standard Software agreement between You or Your employer and either the respective SAP entity or the authorized SAP reselling partner. In case of termination or expiration of this Agreement, You must destroy all copies of the Software on Your Apple mobile device.

- -

13 Law/Venue

- -

German law applies exclusively to all claims in contract, in tort or otherwise, and the UN sales laws convention is excluded. If You are a merchant within the meaning of the German Commercial Code (HGB), section 1, or a public-law juristic person or special fund, the sole place of jurisdiction for all differences arising out of or in connection with the Software Agreement shall be Karlsruhe.

- -

14 Third Party Product License Terms

- -

14.1 Google Maps Service ("GM Service"). In case the Software accesses the GM Service through a Google Maps API, Your use of the GM Service is subject to Google’s Terms of Use which are set forth on: http://www.google.com/intl/en_ALL/help/terms_maps.html. If You do not accept such Google Terms of Use, including, but not limited to all limitations and restrictions therein, You may not use the GM Service in the Software. You acknowledge and agree that use of the GM Service in or through the Software will constitute Your acceptance of Google´s Terms of Use. Company’s usage of GM Service within the Software can be terminated by SAP without stating any reason at any time. In that case SAP is not required to provide an equivalent service via another provider. Company is not entitled to seek any damages thereof. -14.2 Bing Maps Service ("BM Service"). In case the Software accesses the BM Service through a Bing Maps API, Company’s use of the BM Service is subject to Microsoft’s Terms of Use which are set forth on: http://www.microsoft.com/maps/assets/docs/terms.aspx#l1. If Company does not accept such Microsoft Terms of Use, including, but not limited to all limitations and restrictions therein, you or Company may not use the BM Service in the Software. Company acknowledges and agrees that use of the BM Service in or through the Software will constitute Company’s acceptance of Microsoft’s Terms of Use. Company’s usage of BM Service within the Software can be terminated by SAP without stating any reason at any time. In that case SAP is not required to provide an equivalent service via another provider. Company is not entitled to seek any damages thereof.

- -

15 Miscellaneous

- -

This Agreement is the complete Agreement for the Software licensed (including reference to information/documentation contained in a URL). This Agreement supersedes all prior or contemporaneous agreements or representations with regards to the subject matter of this Agreement. If any term of this Agreement is found to be invalid or unenforceable, the surviving provisions shall remain effective. SAP´s failure to enforce any right or provisions stipulated in this Agreement will not constitute a waiver of such provision, or any other provision of this Agreement. -You and SAP agree that: (a) this Agreement is between SAP and You, and that Apple is not a party to this Agreement; (b) that SAP is solely responsible for the Software and the content thereof; (c) that Apple, and Apple's subsidiaries, are third party beneficiaries of this Agreement, and d) Apple will have the right (and will be deemed to have accepted the right) to enforce this Agreement against You as a third party beneficiary hereof, but only if You accept the terms of this Agreement as outlined above.

- -

16 Contact

- -

If you have any questions or support-issues with regards to the Software please refer to our help portal: http://service.sap.com.

- - - diff --git a/ios/SAPTracker/src/xcode/SAPTracker/BaseData.swift b/ios/SAPTracker/src/xcode/SAPTracker/BaseData.swift new file mode 100644 index 00000000000..7637446c72e --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/BaseData.swift @@ -0,0 +1,33 @@ +// +// BaseData.swift +// SAPTracker +// +// Created by Raimund Wege on 05.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import UIKit + +class BaseData: NSObject { + + let dictionary: [String: AnyObject] + + override init() { + self.dictionary = [String: AnyObject]() + super.init() + } + + init(dictionary: [String: AnyObject]?) { + self.dictionary = dictionary ?? [String: AnyObject]() + super.init() + } + + func doubleValue(forKey key: String) -> Double { + return dictionary[key] as? Double ?? 0.0 + } + + func stringValue(forKey key: String) -> String { + return dictionary[key] as? String ?? "" + } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/BatteryManager.swift b/ios/SAPTracker/src/xcode/SAPTracker/BatteryManager.swift index dca99fdd3f3..308ea7fb239 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/BatteryManager.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/BatteryManager.swift @@ -1,46 +1,26 @@ // -// BatterySavingController.swift +// BatteryManager.swift // SAPTracker // -// Created by computing on 07/11/14. -// Copyright (c) 2014 com.sap.sailing. All rights reserved. +// Created by Raimund Wege on 04.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. // import Foundation -/* Needs to be sublass of NSObject for receiving NSNotifications */ class BatteryManager: NSObject { - - /* NSUserDefaultsKey */ - private let BatterySavingDefaultsKey = "BatterySaving" - /* Reference to device needed for reading battery level */ - private let device = UIDevice.currentDevice() + struct BatteryLevel { + static let Min: Float = 0.2 + } - /* Minimum battery level for sending data is 20% */ - private let minBatteryLevel: Float = 0.2 - - /* User preference for saving battery */ - var batterySavingPreference: Bool { - get { - let preferences = NSUserDefaults.standardUserDefaults() - return preferences.boolForKey(BatterySavingDefaultsKey) - } - set { - let preferences = NSUserDefaults.standardUserDefaults() - preferences.setBool(newValue, forKey: BatterySavingDefaultsKey) - preferences.synchronize() - } + struct SendingInterval { + static let Normal: NSTimeInterval = 3 + static let BatterySaving: NSTimeInterval = 30 } - - /* Is battery saving on? */ - var batterySaving: Bool { - get { - return batterySavingPreference || device.batteryLevel < minBatteryLevel && (device.batteryState == UIDeviceBatteryState.Unplugged || device.batteryState == UIDeviceBatteryState.Unknown) - } - } - - /* Singleton */ + + private let device: UIDevice! + class var sharedManager: BatteryManager { struct Singleton { static let sharedManager = BatteryManager() @@ -48,11 +28,32 @@ class BatteryManager: NSObject { return Singleton.sharedManager } - /* Register for battery events */ override init() { + device = UIDevice.currentDevice() super.init() - - // register for battery events - device.batteryMonitoringEnabled = true; + setup() } - } \ No newline at end of file + + // MARK: - Setup + + private func setup() { + setupDevice() + } + + private func setupDevice() { + device.batteryMonitoringEnabled = true + } + + // MARK: - Properties + + var batterySaving: Bool { get { return Preferences.batterySaving || forceBatterySaving() } } + + var sendingPeriod: NSTimeInterval { get { return batterySaving ? SendingInterval.BatterySaving : SendingInterval.Normal } } + + // MARK: - Helper + + private func forceBatterySaving() -> Bool { + return device.batteryLevel < BatteryLevel.Min && (device.batteryState == .Unplugged || device.batteryState == .Unknown) + } + + } diff --git a/ios/SAPTracker/src/xcode/SAPTracker/CheckIn.swift b/ios/SAPTracker/src/xcode/SAPTracker/CheckIn.swift deleted file mode 100644 index 6b932519427..00000000000 --- a/ios/SAPTracker/src/xcode/SAPTracker/CheckIn.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// CheckIn.swift -// SAPTracker -// -// Created by computing on 19/01/15. -// Copyright (c) 2015 com.sap.sailing. All rights reserved. -// - -import Foundation -import CoreData - -@objc(CheckIn) -public class CheckIn: NSManagedObject { - - @NSManaged public var serverUrl: String - @NSManaged public var eventId: String - @NSManaged public var leaderBoardName: String - @NSManaged public var competitorId: String - - @NSManaged public var imageUrl: String? - @NSManaged public var userImage: NSData? - @NSManaged public var lastSyncDate: NSDate? - - @NSManaged public var event: Event? - @NSManaged public var leaderBoard: LeaderBoard? - @NSManaged public var competitor: Competitor? - @NSManaged public var gpsFixes: NSSet? - -} \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker/CheckInController.swift b/ios/SAPTracker/src/xcode/SAPTracker/CheckInController.swift new file mode 100644 index 00000000000..cccba5b841d --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/CheckInController.swift @@ -0,0 +1,116 @@ +// +// CheckInController.swift +// SAPTracker +// +// Created by Raimund Wege on 25.05.16. +// Copyright (c) 2014 com.sap.sailing. All rights reserved. +// + +import Foundation +import UIKit +import AVFoundation + +@objc protocol CheckInControllerDelegate { + + func showCheckInAlert(sender: CheckInController, alertController: UIAlertController) + +} + +class CheckInController : NSObject { + + var delegate: CheckInControllerDelegate? + + private var requestManager = RequestManager() + + // MARK: - CheckIn + + func checkIn(regattaData: RegattaData, completion: (withSuccess: Bool) -> Void) { + SVProgressHUD.show() + requestManager = RequestManager(baseURLString: regattaData.serverURL) + requestManager.getRegattaData(regattaData, + success: + { (regattaData) in + SVProgressHUD.popActivity() + self.checkInSuccess(regattaData, completion: completion) + }, failure: { (error) in + SVProgressHUD.popActivity() + self.checkInFailure(error, completion: completion) + } + ) + } + + private func checkInSuccess(regattaData: RegattaData, completion: (withSuccess: Bool) -> Void) { + let alertController = UIAlertController(title: String(format: Translation.CheckInController.WelcomeAlert.Title.String, regattaData.competitorData.name), + message: String(format: Translation.CheckInController.WelcomeAlert.Message.String, regattaData.competitorData.sailID), + preferredStyle: .Alert + ) + let okAction = UIAlertAction(title: Translation.Common.OK.String, style: .Default) { (action) in + self.postCheckIn(regattaData, completion: completion) + } + let cancelAction = UIAlertAction(title: Translation.CheckInController.WelcomeAlert.CancelAction.Title.String, style: .Cancel) { (action) in + self.checkInDidFinish(withSuccess: false, completion: completion) + } + alertController.addAction(okAction) + alertController.addAction(cancelAction) + showCheckInAlert(alertController) + } + + private func checkInFailure(error: RequestManager.Error, completion: (withSuccess: Bool) -> Void) { + let alertController = UIAlertController(title: error.title, + message: error.message, + preferredStyle: .Alert + ) + let okAction = UIAlertAction(title: Translation.Common.OK.String, style: .Default) { (action) in + self.checkInDidFinish(withSuccess: false, completion: completion) + } + alertController.addAction(okAction) + showCheckInAlert(alertController) + } + + // MARK: - PostCheckIn + + private func postCheckIn(regattaData: RegattaData, completion: (withSuccess: Bool) -> Void) { + SVProgressHUD.show() + requestManager.postCheckIn(regattaData.leaderboardData.name, + competitorID: regattaData.competitorData.competitorID, + success: + { () -> Void in + SVProgressHUD.popActivity() + self.postCheckInSuccess(regattaData, completion: completion) + }, failure: { (error) -> Void in + SVProgressHUD.popActivity() + self.postCheckInFailure(error, completion: completion) + } + ) + } + + private func postCheckInSuccess(regattaData: RegattaData, completion: (withSuccess: Bool) -> Void) { + let regatta = CoreDataManager.sharedManager.fetchRegatta(regattaData) ?? CoreDataManager.sharedManager.newRegatta() + regatta.updateWithRegattaData(regattaData) + CoreDataManager.sharedManager.saveContext() + checkInDidFinish(withSuccess: true, completion: completion) + } + + private func postCheckInFailure(error: RequestManager.Error, completion: (withSuccess: Bool) -> Void) { + let alertController = UIAlertController(title: error.title, + message: error.message, + preferredStyle: .Alert + ) + let okAction = UIAlertAction(title: Translation.Common.OK.String, style: .Default) { (action) in + self.checkInDidFinish(withSuccess: false, completion: completion) + } + alertController.addAction(okAction) + showCheckInAlert(alertController) + } + + private func checkInDidFinish(withSuccess success: Bool, completion: (withSuccess: Bool) -> Void) { + completion(withSuccess: success) + } + + // MARK: - Controller + + private func showCheckInAlert(alertController: UIAlertController) { + self.delegate?.showCheckInAlert(self, alertController: alertController) + } + +} \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Competitor+CoreDataProperties.swift b/ios/SAPTracker/src/xcode/SAPTracker/Competitor+CoreDataProperties.swift new file mode 100644 index 00000000000..8d0d17f66ae --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Competitor+CoreDataProperties.swift @@ -0,0 +1,25 @@ +// +// Competitor+CoreDataProperties.swift +// SAPTracker +// +// Created by Raimund Wege on 04.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// +// Choose "Create NSManagedObject Subclass…" from the Core Data editor menu +// to delete and recreate this implementation file for your updated model. +// + +import Foundation +import CoreData + +extension Competitor { + + @NSManaged var boatClassName: String + @NSManaged var competitorID: String + @NSManaged var countryCode: String + @NSManaged var name: String + @NSManaged var nationality: String + @NSManaged var sailID: String + @NSManaged var regatta: Regatta + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Competitor.swift b/ios/SAPTracker/src/xcode/SAPTracker/Competitor.swift index 8fe2b409a15..80c34f621d0 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/Competitor.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/Competitor.swift @@ -2,31 +2,23 @@ // Competitor.swift // SAPTracker // -// Created by computing on 14/11/14. -// Copyright (c) 2014 com.sap.sailing. All rights reserved. +// Created by Raimund Wege on 04.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. // import Foundation import CoreData @objc(Competitor) -public class Competitor: NSManagedObject { +class Competitor: NSManagedObject { - @NSManaged public var boatClassName: String - @NSManaged public var competitorId: String - @NSManaged public var countryCode: String - @NSManaged public var name: String - @NSManaged public var nationality: String - @NSManaged public var sailId: String - @NSManaged public var checkIn: CheckIn? - - public func initWithDictionary(dictionary: Dictionary) { - competitorId = dictionary["id"] as! String - name = dictionary["name"] as! String - sailId = dictionary["sailID"] as! String - boatClassName = dictionary["boatClassName"] as! String - countryCode = dictionary["countryCode"] as! String - nationality = dictionary["nationality"] as! String + func updateWithCompetitorData(competitorData: CompetitorData) { + boatClassName = competitorData.boatClassName + competitorID = competitorData.competitorID + countryCode = competitorData.countryCode + name = competitorData.name + nationality = competitorData.nationality + sailID = competitorData.sailID } - + } diff --git a/ios/SAPTracker/src/xcode/SAPTracker/CompetitorData.swift b/ios/SAPTracker/src/xcode/SAPTracker/CompetitorData.swift new file mode 100644 index 00000000000..1c4b0917b65 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/CompetitorData.swift @@ -0,0 +1,29 @@ +// +// CompetitorData.swift +// SAPTracker +// +// Created by Raimund Wege on 05.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import UIKit + +class CompetitorData: BaseData { + + private struct Keys { + static let BoatClassName = "boatClassName" + static let CountryCode = "countryCode" + static let ID = "id" + static let Name = "name" + static let Nationality = "nationality" + static let SailID = "sailID" + } + + var boatClassName: String { get { return stringValue(forKey: Keys.BoatClassName) } } + var countryCode: String { get { return stringValue(forKey: Keys.CountryCode) } } + var competitorID: String { get { return stringValue(forKey: Keys.ID) } } + var name: String { get { return stringValue(forKey: Keys.Name) } } + var nationality: String { get { return stringValue(forKey: Keys.Nationality) } } + var sailID: String { get { return stringValue(forKey: Keys.SailID) } } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Constants.swift b/ios/SAPTracker/src/xcode/SAPTracker/Constants.swift index 7775506afc2..5d18971163e 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/Constants.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/Constants.swift @@ -8,7 +8,46 @@ import Foundation -struct URLs -{ - static let EULA = NSURL(string: "http://www.sapsailing.com/EULA_iOS_SailingBoatTracker.html")! -} \ No newline at end of file +struct Application { + static let Title = "SAP Sail InSight" +} + +struct URLs { + static let CodeConvention = NSURL(string: "https://github.com/raywenderlich/swift-style-guide/blob/master/README.markdown") ?? NSURL() + static let Terms = NSURL(string: "http://www.sapsailing.com/EULA_iOS_SailingBoatTracker.html") ?? NSURL() +} + +struct Colors { + static let Blue = UIColor(hex:0x009de0) + static let BlueHighlighted = UIColor(hex:0x007aad) + static let Gray = UIColor(hex:0xf3f3f3) + static let GrayHighlighted = UIColor(hex:0xf3f3f3) + static let Green = UIColor(hex:0x0e7733) + static let GreenHighlighted = UIColor(hex:0x08451e) + static let Red = UIColor(hex:0xcd201b) + static let RedHighlighted = UIColor(hex:0x991814) + static let NavigationBarTitleColor = UIColor.blackColor() + static let NavigationBarTintColor = UIColor(hex: 0x009de0) +} + +struct FontNames { + static let OpenSans = "OpenSans" + static let OpenSansBold = "OpenSans-Bold" +} + +struct Fonts { + static let OpenSansBold17 = UIFont(name: FontNames.OpenSansBold, size: CGFloat(17.0)) ?? UIFont.systemFontOfSize(17.0) + static let OpenSansBold13 = UIFont(name: FontNames.OpenSansBold, size: CGFloat(13.0)) ?? UIFont.systemFontOfSize(13.0) + static let OpenSans10 = UIFont(name: FontNames.OpenSans, size: CGFloat(10.0)) ?? UIFont.systemFontOfSize(10.0) +} + +struct Images { + static let Blue = UIImage(color: Colors.Blue) + static let BlueHighlighted = UIImage(color: Colors.BlueHighlighted) + static let Gray = UIImage(color: Colors.Gray) + static let GrayHighlighted = UIImage(color: Colors.GrayHighlighted) + static let Green = UIImage(color: Colors.Green) + static let GreenHighlighted = UIImage(color: Colors.GreenHighlighted) + static let Red = UIImage(color: Colors.Red) + static let RedHighlighted = UIImage(color: Colors.RedHighlighted) +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/CoreData.xcdatamodeld/.xccurrentversion b/ios/SAPTracker/src/xcode/SAPTracker/CoreData.xcdatamodeld/.xccurrentversion new file mode 100644 index 00000000000..3d5e5761c89 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/CoreData.xcdatamodeld/.xccurrentversion @@ -0,0 +1,8 @@ + + + + + _XCCurrentVersionName + CoreData 2.xcdatamodel + + diff --git a/ios/SAPTracker/src/xcode/SAPTracker/CoreData.xcdatamodeld/CoreData 2.xcdatamodel/contents b/ios/SAPTracker/src/xcode/SAPTracker/CoreData.xcdatamodeld/CoreData 2.xcdatamodel/contents new file mode 100644 index 00000000000..00b1529c859 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/CoreData.xcdatamodeld/CoreData 2.xcdatamodel/contents @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker/CoreDataManager.swift b/ios/SAPTracker/src/xcode/SAPTracker/CoreDataManager.swift new file mode 100644 index 00000000000..c16886e9dca --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/CoreDataManager.swift @@ -0,0 +1,180 @@ +// +// CoreDataManager.swift +// SAPTracker +// +// Created by computing on 21/10/14. +// Copyright (c) 2014 com.sap.sailing. All rights reserved. +// + +import Foundation +import CoreData + +public class CoreDataManager: NSObject { + + private enum Entities: String { + case Competitor + case Event + case GPSFix + case Leaderboard + case Regatta + } + + public class var sharedManager: CoreDataManager { + struct Singleton { + static let sharedManager = CoreDataManager() + } + return Singleton.sharedManager + } + + // MARK: - Fetch + + func fetchRegattas() -> [Regatta]? { + let fetchRequest = NSFetchRequest() + fetchRequest.entity = NSEntityDescription.entityForName(Entities.Regatta.rawValue, inManagedObjectContext: managedObjectContext) + var regattas: [AnyObject]? + do { + regattas = try managedObjectContext.executeFetchRequest(fetchRequest) + } catch { + logError("\(#function)", error: error) + } + return regattas as? [Regatta] + } + + func fetchRegatta(regattaData: RegattaData) -> Regatta? { + let fetchRequest = NSFetchRequest() + fetchRequest.entity = NSEntityDescription.entityForName(Entities.Regatta.rawValue, inManagedObjectContext: managedObjectContext) + fetchRequest.predicate = NSPredicate(format: "event.eventID = %@ AND leaderboard.name = %@ AND competitor.competitorID = %@", + regattaData.eventID, + regattaData.leaderboardName, + regattaData.competitorID) + do { + let regattas = try managedObjectContext.executeFetchRequest(fetchRequest) + if regattas.count == 0 { + return nil + } else { + return regattas[0] as? Regatta + } + } catch { + logError("\(#function)", error: error) + } + return nil + } + + func regattaFetchedResultsController() -> NSFetchedResultsController { + let fetchRequest = NSFetchRequest(entityName: Entities.Regatta.rawValue) + fetchRequest.predicate = NSPredicate(format: "event != nil AND leaderboard != nil AND competitor != nil") + fetchRequest.sortDescriptors = [NSSortDescriptor(key: "leaderboard.name", ascending: true)] + return NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext, sectionNameKeyPath: nil, cacheName: nil) + } + + // MARK: - Insert + + func newRegatta() -> Regatta { + let regatta = NSEntityDescription.insertNewObjectForEntityForName(Entities.Regatta.rawValue, inManagedObjectContext: managedObjectContext) as! Regatta + regatta.event = newEvent(regatta) + regatta.leaderboard = newLeaderboard(regatta) + regatta.competitor = newCompetitor(regatta) + return regatta + } + + private func newEvent(regatta: Regatta) -> Event { + let event = NSEntityDescription.insertNewObjectForEntityForName(Entities.Event.rawValue, inManagedObjectContext: managedObjectContext) as! Event + event.regatta = regatta + return event + } + + private func newLeaderboard(regatta: Regatta) -> Leaderboard { + let leaderboard = NSEntityDescription.insertNewObjectForEntityForName(Entities.Leaderboard.rawValue, inManagedObjectContext: managedObjectContext) as! Leaderboard + leaderboard.regatta = regatta + return leaderboard + } + + private func newCompetitor(regatta: Regatta) -> Competitor { + let competitor = NSEntityDescription.insertNewObjectForEntityForName(Entities.Competitor.rawValue, inManagedObjectContext: managedObjectContext) as! Competitor + competitor.regatta = regatta + return competitor + } + + func newGPSFix(regatta: Regatta) -> GPSFix { + let gpsFix = NSEntityDescription.insertNewObjectForEntityForName(Entities.GPSFix.rawValue, inManagedObjectContext: managedObjectContext) as! GPSFix + gpsFix.regatta = regatta + return gpsFix + } + + // MARK: - Delete + + func deleteObject(object: AnyObject?) { + guard let o = object as? NSManagedObject else { return } + managedObjectContext.deleteObject(o) + } + + func deleteObjects(objects: Array?) { + objects?.forEach { (o) in deleteObject(o) } + } + + // MARK: - Core Data stack + + lazy var applicationDocumentsDirectory: NSURL = { + let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask) + return urls[urls.count-1] + }() + + lazy var managedObjectModel: NSManagedObjectModel = { + let modelURL = NSBundle.mainBundle().URLForResource("CoreData", withExtension: "momd")! + return NSManagedObjectModel(contentsOfURL: modelURL)! + }() + + lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = { + let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel) + let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("CoreData.sqlite") + let options = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true] + do { + logInfo("\(#function)", info: "Connecting to database...") + try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options) + logInfo("\(#function)", info: "Database connection established") + } catch { + logInfo("\(#function)", info: "Connecting to database failed") + logError("\(#function)", error: error) + do { + logInfo("\(#function)", info: "Removing corrupt database...") + try NSFileManager.defaultManager().removeItemAtURL(url) + logInfo("\(#function)", info: "Corrupt database removed") + do { + logInfo("\(#function)", info: "Connecting to new database...") + try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options) + logInfo("\(#function)", info: "Database connection established") + } catch { + logInfo("\(#function)", info: "Connecting to new database failed") + logError("\(#function)", error: error) + abort() + } + } catch { + logInfo("\(#function)", info: "Removing corrupt database failed") + logError("\(#function)", error: error) + abort() + } + } + return coordinator + }() + + lazy var managedObjectContext: NSManagedObjectContext = { + let coordinator = self.persistentStoreCoordinator + var managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType) + managedObjectContext.persistentStoreCoordinator = coordinator + return managedObjectContext + }() + + // MARK: - Core Data Saving support + + func saveContext () { + if managedObjectContext.hasChanges { + do { + try managedObjectContext.save() + } catch { + logError("\(#function)", error: error) + abort() + } + } + } + +} \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker/CourseViewController.swift b/ios/SAPTracker/src/xcode/SAPTracker/CourseViewController.swift index ffbc9113b65..b418df01871 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/CourseViewController.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/CourseViewController.swift @@ -10,19 +10,64 @@ import Foundation class CourseViewController: UIViewController { + private let defaultCourseText = "- °" + + @IBOutlet weak var titleLabel: UILabel! @IBOutlet weak var courseLabel: UILabel! override func viewDidLoad() { super.viewDidLoad() - NSNotificationCenter.defaultCenter().addObserver(self, selector:"newLocation:", name:LocationManager.NotificationType.newLocation, object: nil) + setup() + subscribeForNotifications() } - + deinit { + unsubscribeFromNotifications() + } + + // MARK: - Setup + + private func setup() { + setupCourseLabel(-1.0) + setupLocalization() + } + + private func setupCourseLabel(course: Double) { + courseLabel.text = course < 0 ? defaultCourseText : String(format: "%.0f °", course) + } + + private func setupLocalization() { + titleLabel.text = Translation.CourseView.TitleLabel.Text.String + } + + // MARK: - Notifications + + private func subscribeForNotifications() { + NSNotificationCenter.defaultCenter().addObserver(self, + selector:#selector(locationManagerUpdated(_:)), + name:LocationManager.NotificationType.Updated, + object: nil) + NSNotificationCenter.defaultCenter().addObserver(self, + selector:#selector(locationManagerFailed(_:)), + name:LocationManager.NotificationType.Failed, + object: nil) + } + + private func unsubscribeFromNotifications() { NSNotificationCenter.defaultCenter().removeObserver(self) } - func newLocation(notification: NSNotification) { - courseLabel.text = String(format: "%.0f °", notification.userInfo!["course"] as! Double) + @objc private func locationManagerUpdated(notification: NSNotification) { + dispatch_async(dispatch_get_main_queue(), { + guard let locationData = notification.userInfo?[LocationManager.UserInfo.LocationData] as? LocationData else { return } + self.setupCourseLabel(locationData.location.course) + }) + } + + @objc private func locationManagerFailed(notification: NSNotification) { + dispatch_async(dispatch_get_main_queue(), { + self.setupCourseLabel(-1.0) + }) } } \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker/DataManager.swift b/ios/SAPTracker/src/xcode/SAPTracker/DataManager.swift deleted file mode 100644 index 0fc121fec17..00000000000 --- a/ios/SAPTracker/src/xcode/SAPTracker/DataManager.swift +++ /dev/null @@ -1,233 +0,0 @@ -// -// DataManager.swift -// SAPTracker -// -// Created by computing on 21/10/14. -// Copyright (c) 2014 com.sap.sailing. All rights reserved. -// - -import Foundation -import CoreData - -public class DataManager: NSObject { - - var selectedCheckIn: CheckIn? - - public class var sharedManager: DataManager { - struct Singleton { - static let sharedManager = DataManager() - } - return Singleton.sharedManager - } - - override init() { - super.init() - - print(managedObjectContext!) - - // store new locations to database - NSNotificationCenter.defaultCenter().addObserver(self, selector: "newLocation:", name: LocationManager.NotificationType.newLocation, object: nil) - - // save context when done tracking - NSNotificationCenter.defaultCenter().addObserver(self, selector: "trackingStopped:", name: LocationManager.NotificationType.trackingStopped, object: nil) - } - - deinit { - NSNotificationCenter.defaultCenter().removeObserver(self) - } - - // MARK: - notification callbacks - - /* New location detected, store to database if location is valid. */ - func newLocation(notification: NSNotification) { - if notification == NSNull() { - return - } - var dict = notification.userInfo!; - if dict["isValid"] as! Bool { - let gpsFix = NSEntityDescription.insertNewObjectForEntityForName("GPSFix", inManagedObjectContext: self.managedObjectContext!) as! GPSFix - gpsFix.initWithDictionary(dict) - if selectedCheckIn == nil { - abort(); - } - gpsFix.checkIn = selectedCheckIn! - saveContext() - } - } - - /* Tracking stopped, save data to disk. */ - func trackingStopped(notification: NSNotification) { - saveContext() - } - - // MARK: - public database access - func getCheckIn(eventId: String, leaderBoardName: String, competitorId: String)->CheckIn? { - let fetchRequest = NSFetchRequest() - fetchRequest.entity = NSEntityDescription.entityForName("CheckIn", inManagedObjectContext: self.managedObjectContext!) - fetchRequest.predicate = NSPredicate(format: "eventId = %@ AND leaderBoardName = %@ AND competitorId = %@", eventId, leaderBoardName, competitorId) - do { - let results = try self.managedObjectContext!.executeFetchRequest(fetchRequest) - if results.count == 0 { - return nil - } else { - return results[0] as? CheckIn - } - } catch { - print(error) - } - return nil - } - - func newCheckIn()->CheckIn { - return NSEntityDescription.insertNewObjectForEntityForName("CheckIn", inManagedObjectContext: self.managedObjectContext!) as! CheckIn - } - - func newEvent(checkIn: CheckIn) -> Event { - let event = NSEntityDescription.insertNewObjectForEntityForName("Event", inManagedObjectContext: self.managedObjectContext!) as! Event - event.checkIn = checkIn - return event - } - - func newLeaderBoard(checkIn: CheckIn) -> LeaderBoard { - let leaderBoard = NSEntityDescription.insertNewObjectForEntityForName("LeaderBoard", inManagedObjectContext: self.managedObjectContext!) as! LeaderBoard - leaderBoard.checkIn = checkIn - return leaderBoard - } - - func newCompetitor(checkIn: CheckIn) -> Competitor { - let competitor = NSEntityDescription.insertNewObjectForEntityForName("Competitor", inManagedObjectContext: self.managedObjectContext!) as! Competitor - competitor.checkIn = checkIn - return competitor - } - - /* Get latest locations. Limited by the max number of objects that can be sent. */ - func latestLocations() -> [GPSFix] { - let fetchRequest = NSFetchRequest() - fetchRequest.entity = NSEntityDescription.entityForName("GPSFix", inManagedObjectContext: self.managedObjectContext!) - fetchRequest.sortDescriptors = [NSSortDescriptor(key: "timestamp", ascending: false)] - fetchRequest.fetchLimit = APIManager.Constants.maxSendGPSFix - var results: [AnyObject]? = nil - do { - try results = self.managedObjectContext!.executeFetchRequest(fetchRequest) - } catch { - print(error) - } - return results as! [GPSFix] - } - - func countCachedFixes() -> Int { - let request = NSFetchRequest() - request.entity = NSEntityDescription.entityForName("GPSFix", inManagedObjectContext: self.managedObjectContext!) - request.includesSubentities = false - var error: NSError? = nil - let count = self.managedObjectContext!.countForFetchRequest(request, error:&error) - if(count == NSNotFound) { - //Handle error - } - return count - } - - /* Get all check ins. */ - func checkInFetchedResultsController()->NSFetchedResultsController { - let fetchRequest = NSFetchRequest(entityName: "CheckIn") - fetchRequest.sortDescriptors = [NSSortDescriptor(key: "leaderBoardName", ascending: true)] - return NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext!, sectionNameKeyPath: nil, cacheName: nil) - } - - public func deleteCheckIn(checkIn: CheckIn) { - self.managedObjectContext!.deleteObject(checkIn) - } - - // MARK: - Core Data stack - - lazy var applicationDocumentsDirectory: NSURL = { - // The directory the application uses to store the Core Data store file. This code uses a directory named "com.sap.sailing.ios.CoreData" in the application's documents Application Support directory. - let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask) - return urls[urls.count-1] - }() - - lazy var managedObjectModel: NSManagedObjectModel = { - // The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model. - let modelURL = NSBundle.mainBundle().URLForResource("CoreData", withExtension: "momd")! - return NSManagedObjectModel(contentsOfURL: modelURL)! - }() - - lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = { - // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail. - // Create the coordinator and store - var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel) - let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("CoreData.sqlite") - var error: NSError? = nil - - // http://stackoverflow.com/a/8890373 - // Check if we already have a persistent store - if (NSFileManager.defaultManager().fileExistsAtPath(url.path!)) { - do { - let existingPersistentStoreMetadata = try NSPersistentStoreCoordinator.metadataForPersistentStoreOfType(NSSQLiteStoreType, URL: url) - // if (existingPersistentStoreMetadata == nil) { - // // Something *really* bad has happened to the persistent store - // NSException.raise(NSInternalInconsistencyException, format: "Failed to read metadata for persistent store %@: %@", arguments:getVaList([url, error!])); - // } - - if (!self.managedObjectModel.isConfiguration(nil, compatibleWithStoreMetadata: existingPersistentStoreMetadata)) { - do { - try NSFileManager.defaultManager().removeItemAtURL(url) - } catch { - print("*** Could not delete persistent store, %@", error); - } // else the existing persistent store is compatible with the current model - nice! - } // else no database file yet - } catch { - print(error) - } - } - - let options = [NSMigratePersistentStoresAutomaticallyOption: 1, NSInferMappingModelAutomaticallyOption: 1] - var failureReason = "There was an error creating or loading the application's saved data." - do { - try coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options) - } catch { - print(error) - coordinator = nil - // Report any error we got. - let dict = NSMutableDictionary() - dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" - dict[NSLocalizedFailureReasonErrorKey] = failureReason -// dict[NSUnderlyingErrorKey] = error -// error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict as [NSObject : AnyObject]) -// // Replace this with code to handle the error appropriately. -// // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. -// NSLog("Unresolved error \(error), \(error!.userInfo)") -// //abort() -// NSFileManager.defaultManager().removeItemAtURL(url, error:nil); -// return nil - } - return coordinator - }() - - public lazy var managedObjectContext: NSManagedObjectContext? = { - // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail. - let coordinator = self.persistentStoreCoordinator - if coordinator == nil { - return nil - } - var managedObjectContext = NSManagedObjectContext() - managedObjectContext.persistentStoreCoordinator = coordinator - return managedObjectContext - }() - - // MARK: - Core Data Saving support - - func saveContext () { - if let moc = self.managedObjectContext { - if (moc.hasChanges) { - do { - try moc.save() - } catch { - print(error) - abort() - } - } - } - } - -} \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker/DeviceUDIDManager.swift b/ios/SAPTracker/src/xcode/SAPTracker/DeviceUDIDManager.swift deleted file mode 100644 index 747c8eb24ee..00000000000 --- a/ios/SAPTracker/src/xcode/SAPTracker/DeviceUDIDManager.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// DeviceUDIDManager.swift -// SAPTracker -// -// Created by computing on 22/10/14. -// Copyright (c) 2014 com.sap.sailing. All rights reserved. -// - -import Foundation - -struct DeviceUDIDManager { - - private static let preferences = NSUserDefaults.standardUserDefaults() - private static var staticUdid: String? - - static var UDID: String { - get { - if (staticUdid == nil) { - if preferences.objectForKey("udid") == nil { - staticUdid = NSUUID().UUIDString.lowercaseString - preferences.setObject(staticUdid, forKey: "udid") - preferences.synchronize() - } else { - staticUdid = preferences.objectForKey("udid") as? String - } - } - return staticUdid! - } - } - -} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Event+CoreDataProperties.swift b/ios/SAPTracker/src/xcode/SAPTracker/Event+CoreDataProperties.swift new file mode 100644 index 00000000000..b85b66ae6e7 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Event+CoreDataProperties.swift @@ -0,0 +1,23 @@ +// +// Event+CoreDataProperties.swift +// SAPTracker +// +// Created by Raimund Wege on 04.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// +// Choose "Create NSManagedObject Subclass…" from the Core Data editor menu +// to delete and recreate this implementation file for your updated model. +// + +import Foundation +import CoreData + +extension Event { + + @NSManaged var endDate: NSTimeInterval + @NSManaged var eventID: String + @NSManaged var name: String + @NSManaged var startDate: NSTimeInterval + @NSManaged var regatta: Regatta + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Event.swift b/ios/SAPTracker/src/xcode/SAPTracker/Event.swift index 91062e7a51d..2f6c94b489e 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/Event.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/Event.swift @@ -2,33 +2,21 @@ // Event.swift // SAPTracker // -// Created by computing on 14/11/14. -// Copyright (c) 2014 com.sap.sailing. All rights reserved. +// Created by Raimund Wege on 04.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. // import Foundation import CoreData @objc(Event) -public class Event: NSManagedObject { +class Event: NSManagedObject { - @NSManaged public var eventId: String - @NSManaged public var name: String - @NSManaged public var startDate: NSDate - @NSManaged public var endDate: NSDate - @NSManaged public var checkIn: CheckIn? - - public func initWithDictionary(dictionary: [String: AnyObject]) { - eventId = dictionary["id"] as! String - name = dictionary["name"] as! String - startDate = NSDate(timeIntervalSince1970: (dictionary["startDate"] as! Double)/1000) - endDate = NSDate(timeIntervalSince1970: (dictionary["endDate"] as! Double)/1000) - if (dictionary["imageURLs"] != nil) { - let imageUrls = dictionary["imageURLs"] as! Array - if (imageUrls.count > 0) { - checkIn!.imageUrl = imageUrls[0] - } - } + func updateWithEventData(eventData: EventData) { + endDate = eventData.endDate + eventID = eventData.eventID + name = eventData.name + startDate = eventData.startDate } - + } diff --git a/ios/SAPTracker/src/xcode/SAPTracker/EventData.swift b/ios/SAPTracker/src/xcode/SAPTracker/EventData.swift new file mode 100644 index 00000000000..655bf292f1c --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/EventData.swift @@ -0,0 +1,26 @@ +// +// EventData.swift +// SAPTracker +// +// Created by Raimund Wege on 05.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import UIKit + +class EventData: BaseData { + + private struct Keys { + static let EndDate = "endDate" + static let ID = "id" + static let ImageURLs = "imageURLs" + static let Name = "name" + static let StartDate = "startDate" + } + + var endDate: Double { get { return doubleValue(forKey: Keys.EndDate) / 1000 } } + var eventID: String { get { return stringValue(forKey: Keys.ID) } } + var name: String { get { return stringValue(forKey: Keys.Name) } } + var startDate: Double { get { return doubleValue(forKey: Keys.StartDate) / 1000 } } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Extensions.swift b/ios/SAPTracker/src/xcode/SAPTracker/Extensions.swift index ba6b5c8fcb8..470c243f21b 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/Extensions.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/Extensions.swift @@ -8,45 +8,62 @@ import Foundation -/* Set color to RGB hex value. See http://stackoverflow.com/a/24263296 */ -extension UIColor { +// MARK: - Logging + +func logInfo(name: String, info: String) { + #if DEBUG + NSLog("\(name): \(info)") + #endif +} + +func logError(name: String, error: ErrorType) { + #if DEBUG + NSLog("\(name): \(error)") + #endif +} + +// MARK: - UIColor + +extension UIColor { // Set color to RGB hex value. See http://stackoverflow.com/a/24263296 + convenience init(red: Int, green: Int, blue: Int) { assert(red >= 0 && red <= 255, "Invalid red component") assert(green >= 0 && green <= 255, "Invalid green component") assert(blue >= 0 && blue <= 255, "Invalid blue component") - self.init(red: CGFloat(red) / 255.0, green: CGFloat(green) / 255.0, blue: CGFloat(blue) / 255.0, alpha: 1.0) } convenience init(hex:Int) { self.init(red:(hex >> 16) & 0xff, green:(hex >> 8) & 0xff, blue:hex & 0xff) } + } -/* Needed for setting border color in Interface Builder. */ -extension CALayer { - var borderUIColor: UIColor { - get { - return UIColor(CGColor: self.borderColor!) - } - set { - self.borderColor = newValue.CGColor - } +// MARK: - UIImage + +extension UIImage { + + public convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) { + let rect = CGRect(origin: .zero, size: size) + UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0) + color.setFill() + UIRectFill(rect) + let image = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + guard let cgImage = image.CGImage else { return nil } + self.init(CGImage: cgImage) } + } -/* Needed for bottom status labels. */ -class PaddedLabel : UILabel { - override func drawTextInRect(rect: CGRect) { - let insets = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5) - return super.drawTextInRect(UIEdgeInsetsInsetRect(rect, insets)) +// MARK: - UITableViewCell + +extension UITableViewCell { + + func removeSeparatorInset() { + preservesSuperviewLayoutMargins = false + layoutMargins = UIEdgeInsetsZero + separatorInset = UIEdgeInsetsZero } + } - -/* Needed for programmatically setting button heights in iOS 7. */ -struct ButtonHeight { - static let bigButtonPortrait = CGFloat(75.0) - static let bigButtonLandscape = CGFloat(50.0) - static let smallButtonPortrait = CGFloat(50.0) - static let smallButtonLandscape = CGFloat(50.0) -} \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker/GPSAccuracyView.swift b/ios/SAPTracker/src/xcode/SAPTracker/GPSAccuracyView.swift index 779aa68ce2c..87cb35544d5 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/GPSAccuracyView.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/GPSAccuracyView.swift @@ -2,68 +2,111 @@ // GPSAccuracyView.swift // SAPTracker // -// Created by computing on 11/12/14. -// Copyright (c) 2014 com.sap.sailing. All rights reserved. +// Created by Raimund Wege on 05.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. // import UIKit class GPSAccuracyView : UIView { + struct Color { + static let Green = UIColor(hex: 0x408000) + static let Red = UIColor(hex: 0xFF0000) + static let Orange = UIColor(hex: 0xFF8000) + } + let barView = UIView() override init(frame: CGRect) { super.init(frame: frame) - setup() + initialize() } required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder)! + initialize() + } + + private func initialize() { setup() + subscribeForNotifications() } deinit { + unsubscribeFromNotifications() + } + + // MARK: - Setup + + private func setup() { + setupBarView() + setupBackroundColor() + } + + private func setupBarView() { + addSubview(barView) + barView.frame = bounds + } + + private func setupBackroundColor() { + backgroundColor = UIColor.grayColor() + } + + // MARK: - Notifications + + private func subscribeForNotifications() { + NSNotificationCenter.defaultCenter().addObserver(self, + selector:#selector(locationManagerUpdated(_:)), + name:LocationManager.NotificationType.Updated, + object: nil + ) + NSNotificationCenter.defaultCenter().addObserver(self, + selector:#selector(locationManagerFailed(_:)), + name:LocationManager.NotificationType.Failed, + object: nil + ) + } + + private func unsubscribeFromNotifications() { NSNotificationCenter.defaultCenter().removeObserver(self) } - private func setup() { - backgroundColor = UIColor.grayColor() - - addSubview(barView) - barView.frame = bounds - - // add listeners - NSNotificationCenter.defaultCenter().addObserver(self, selector:"newLocation:", name:LocationManager.NotificationType.newLocation, object: nil) - NSNotificationCenter.defaultCenter().addObserver(self, selector:"locationManagerFailed:", name:LocationManager.NotificationType.locationManagerFailed, object: nil) - + @objc private func locationManagerUpdated(notification: NSNotification) { + dispatch_async(dispatch_get_main_queue(), { + guard let locationData = notification.userInfo?[LocationManager.UserInfo.LocationData] as? LocationData else { return } + self.drawBar(locationData.location.horizontalAccuracy) + }) } - + + @objc private func locationManagerFailed(notification: NSNotification) { + dispatch_async(dispatch_get_main_queue(), { + self.drawBar(-1.0) + }) + } + + // MARK: - Draw + private func drawBar(horizontalAccuracy: Double) { var height = 1.0 - var color = TrackingViewController.Color.Red + var color = Color.Red if (horizontalAccuracy < 0) { - + // ... } else if (horizontalAccuracy > 48) { height = 0.33 } else if (horizontalAccuracy > 10) { height = 0.66 - color = TrackingViewController.Color.Orange + color = Color.Orange } else { height = 1.0 - color = TrackingViewController.Color.Green + color = Color.Green } - let frame = CGRect(x:0, y:CGFloat(1.0 - height) * bounds.height, width:bounds.width, height:CGFloat(height) * bounds.height) + let frame = CGRect(x:0, + y:CGFloat(1.0 - height) * bounds.height, + width:bounds.width, + height:CGFloat(height) * bounds.height) barView.frame = frame barView.backgroundColor = color } - func newLocation(notification: NSNotification) { - let horizontalAccuracy = notification.userInfo!["horizontalAccuracy"] as! Double - drawBar(horizontalAccuracy) - } - - func locationManagerFailed(notification: NSNotification) { - drawBar(-1.0) - } - } \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker/GPSFix+CoreDataProperties.swift b/ios/SAPTracker/src/xcode/SAPTracker/GPSFix+CoreDataProperties.swift new file mode 100644 index 00000000000..b3eba45af86 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/GPSFix+CoreDataProperties.swift @@ -0,0 +1,24 @@ +// +// GPSFix+CoreDataProperties.swift +// SAPTracker +// +// Created by Raimund Wege on 04.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// +// Choose "Create NSManagedObject Subclass…" from the Core Data editor menu +// to delete and recreate this implementation file for your updated model. +// + +import Foundation +import CoreData + +extension GPSFix { + + @NSManaged var course: Double + @NSManaged var latitude: Double + @NSManaged var longitude: Double + @NSManaged var speed: Double + @NSManaged var timestamp: Double + @NSManaged var regatta: Regatta + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/GPSFix.swift b/ios/SAPTracker/src/xcode/SAPTracker/GPSFix.swift index 3ea2019c39d..0a56e0172a0 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/GPSFix.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/GPSFix.swift @@ -2,39 +2,22 @@ // GPSFix.swift // SAPTracker // -// Created by computing on 14/11/14. -// Copyright (c) 2014 com.sap.sailing. All rights reserved. +// Created by Raimund Wege on 04.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. // import Foundation import CoreData @objc(GPSFix) -public class GPSFix: NSManagedObject { +class GPSFix: NSManagedObject { - @NSManaged var course: Double - @NSManaged var latitude: Double - @NSManaged var longitude: Double - @NSManaged var speed: Double - @NSManaged var timestamp: Double - @NSManaged var checkIn: CheckIn? - - func initWithDictionary(dictionary: Dictionary) { - timestamp = round(dictionary["timestamp"] as! Double * 1000) - latitude = dictionary["latitude"] as! Double - longitude = dictionary["longitude"] as! Double - speed = dictionary["speed"] as! Double - course = dictionary["course"] as! Double + func updateWithLocationData(locationData: LocationData) { + course = locationData.location.course + latitude = locationData.location.coordinate.latitude + longitude = locationData.location.coordinate.longitude + speed = locationData.location.speed + timestamp = round(locationData.location.timestamp.timeIntervalSince1970 * 1000) } - func dictionary() -> [String: AnyObject] { - var dictionary = [String: AnyObject]() - dictionary["course"] = course - dictionary["latitude"] = latitude - dictionary["longitude"] = longitude - dictionary["speed"] = speed - dictionary["timestamp"] = timestamp - return dictionary - } - } diff --git a/ios/SAPTracker/src/xcode/SAPTracker/GPSFixController.swift b/ios/SAPTracker/src/xcode/SAPTracker/GPSFixController.swift new file mode 100644 index 00000000000..754bdb05bfb --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/GPSFixController.swift @@ -0,0 +1,164 @@ +// +// GPSFixController.swift +// SAPTracker +// +// Created by Raimund Wege on 21.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import UIKit + +class GPSFixController: NSObject { + + struct NotificationType { + static let ModeChanged = "RegattaController.ModeChanged" + } + + struct UserInfo { + static let Mode = "Mode" + } + + struct GPSFixSending { + static let SliceSize = 1000 + } + + enum Mode: String { + case BatterySaving + case Error + case None + case Offline + case Online + var description: String { + switch self { + case .BatterySaving: return Translation.GPSFixController.Mode.BatterySaving.String + case .Error: return Translation.GPSFixController.Mode.Error.String + case .None: return Translation.GPSFixController.Mode.None.String + case .Offline: return Translation.GPSFixController.Mode.Offline.String + case .Online: return Translation.GPSFixController.Mode.Online.String + } + } + } + + let regatta: Regatta + + init(regatta: Regatta) { + self.regatta = regatta + } + + // MARK: - Send All + + func sendAll(completion: (withSuccess: Bool) -> Void) { + sendAll({ + completion(withSuccess: true) + }) { (error, gpsFixesLeft) in + completion(withSuccess: false) + } + } + + private func sendAll(success: () -> Void, failure: (error: RequestManager.Error, gpsFixesLeft: Set) -> Void) { + sendAll(regatta.gpsFixes as? Set ?? [], success: success, failure: failure) + } + + private func sendAll(gpsFixesLeft: Set, + success: () -> Void, + failure: (error: RequestManager.Error, gpsFixesLeft: Set) -> Void) + { + guard gpsFixesLeft.count > 0 else { success(); return } + sendSlice(gpsFixesLeft, success: { (gpsFixesLeft) in + self.sendAll(gpsFixesLeft, success: success, failure: failure) + }) { (error, gpsFixesLeft) in + failure(error: error, gpsFixesLeft: gpsFixesLeft) + } + } + + // MARK: - Send Slice + + func sendSlice(completion: (withSuccess: Bool) -> Void) { + sendSlice({ (gpsFixesLeft) in + completion(withSuccess: true) + }) { (error, gpsFixesLeft) in + completion(withSuccess: false) + } + } + + private func sendSlice(success: (gpsFixesLeft: Set) -> Void, failure: (error: RequestManager.Error, gpsFixesLeft: Set?) -> Void) { + sendSlice(regatta.gpsFixes as? Set ?? [], success: success, failure: failure) + } + + private func sendSlice(gpsFixes: Set, + success: (gpsFixesLeft: Set) -> Void, + failure: (error: RequestManager.Error, gpsFixesLeft: Set) -> Void) + { + guard gpsFixes.count > 0 else { success(gpsFixesLeft: []); return } + let slicedGPSFixes = sliceGPSFixes(gpsFixes) + let gpsFixesLeft = gpsFixes.subtract(slicedGPSFixes) + sendSlice(slicedGPSFixes, + gpsFixesLeft: gpsFixesLeft, + success: success, + failure: failure + ) + } + + private func sendSlice(gpsFixes: Array, + gpsFixesLeft: Set, + success: (gpsFixesLeft: Set) -> Void, + failure: (error: RequestManager.Error, gpsFixesLeft: Set) -> Void) + { + log("\(gpsFixes.count) GPS fixes will be sent and \(gpsFixesLeft.count) will be left") + requestManager.postGPSFixes(gpsFixes, + success: { () in self.sendSliceSuccess(gpsFixes, gpsFixesLeft: gpsFixesLeft, success: success) }, + failure: { (error) in self.sendSliceFailure(error, gpsFixesLeft: gpsFixesLeft, failure: failure) } + ) + } + + private func sendSliceSuccess(gpsFixes: Array, + gpsFixesLeft: Set, + success: (gpsFixesLeft: Set) -> Void) + { + dispatch_async(dispatch_get_main_queue(), { + self.log("Sending \(gpsFixes.count) GPS fixes was successful") + self.postModeChangedNotification(BatteryManager.sharedManager.batterySaving ? .BatterySaving : .Online) + CoreDataManager.sharedManager.deleteObjects(gpsFixes) + CoreDataManager.sharedManager.saveContext() + self.log("\(gpsFixes.count) GPS fixes deleted") + success(gpsFixesLeft: gpsFixesLeft) + }) + } + + private func sendSliceFailure(error: RequestManager.Error, + gpsFixesLeft: Set, + failure: (error: RequestManager.Error, gpsFixesLeft: Set) -> Void) + { + dispatch_async(dispatch_get_main_queue(), { + self.log("Sending GPS fixes failed. \(error.title): \(error.message)") + self.postModeChangedNotification(AFNetworkReachabilityManager.sharedManager().reachable ? .Error : .Offline) + failure(error: error, gpsFixesLeft: gpsFixesLeft) + }) + } + + // MARK: - Notifications + + private func postModeChangedNotification(mode: Mode) { + let userInfo = [UserInfo.Mode: mode.rawValue] + let notification = NSNotification(name: NotificationType.ModeChanged, object: self, userInfo: userInfo) + NSNotificationQueue.defaultQueue().enqueueNotification(notification, postingStyle: NSPostingStyle.PostASAP) + } + + // MARK: - Properties + + private lazy var requestManager: RequestManager = { + let requestManager = RequestManager(baseURLString: self.regatta.serverURL) + return requestManager + }() + + // MARK: - Helper + + private func log(info: String) { + logInfo("\(self.description)", info: info) + } + + private func sliceGPSFixes(gpsFixes: Set) -> Array { + return Array(gpsFixes.sort { (gpsFix1, gpsFix2) -> Bool in gpsFix1.timestamp < gpsFix2.timestamp }.prefix(GPSFixSending.SliceSize)) + } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/GradientView.swift b/ios/SAPTracker/src/xcode/SAPTracker/GradientView.swift new file mode 100644 index 00000000000..3f034cacfca --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/GradientView.swift @@ -0,0 +1,24 @@ +// +// GradientView.swift +// SAPTracker +// +// Created by Raimund Wege on 07.06.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import UIKit + +@IBDesignable class GradientView: UIView { + + @IBInspectable var firstColor: UIColor = UIColor.whiteColor() + @IBInspectable var secondColor: UIColor = UIColor.blackColor() + + override class func layerClass() -> AnyClass { + return CAGradientLayer.self + } + + override func layoutSubviews() { + (layer as! CAGradientLayer).colors = [firstColor.CGColor, secondColor.CGColor] + } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/HomeViewController.swift b/ios/SAPTracker/src/xcode/SAPTracker/HomeViewController.swift index 1fe17e1cf20..c84a6648808 100755 --- a/ios/SAPTracker/src/xcode/SAPTracker/HomeViewController.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/HomeViewController.swift @@ -2,297 +2,437 @@ // ViewController.swift // SAPTracker // -// Created by computing on 17/10/14. +// Created by Raimund Wege on 17/10/14. // Copyright (c) 2014 com.sap.sailing. All rights reserved. // import UIKit import CoreData -class HomeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate, QRCodeManagerDelegate { +class HomeViewController: UIViewController { - enum AlertView: Int { - case NoCameraAvailable - } - - struct Keys { - static let acceptedTerms = "acceptedTerms" + private struct Segue { + static let About = "About" + static let Regatta = "Regatta" + static let Scan = "Scan" + static let Settings = "Settings" } - @IBOutlet weak var bottomNote: PaddedLabel! - @IBOutlet weak var btnScan: UIButton! - @IBOutlet weak var btnNoCode: UIButton! + var selectedRegatta: Regatta? + + @IBOutlet var headerView: UIView! // Strong reference needed to avoid deallocation when not attached to table view + + @IBOutlet weak var headerTitleLabel: UILabel! @IBOutlet weak var tableView: UITableView! - @IBOutlet weak var tableViewHeight: NSLayoutConstraint! - @IBOutlet weak var activityIndicatorView: UIActivityIndicatorView! - @IBOutlet var vSplashScreen: UIView! - - var fetchedResultsController: NSFetchedResultsController? - private var qrCodeManager: QRCodeManager? + @IBOutlet weak var scanCodeButton: UIButton! + @IBOutlet weak var noCodeButton: UIButton! + @IBOutlet weak var infoCodeLabel: UILabel! + @IBOutlet weak var footerView: UIView! + @IBOutlet weak var footerTextView: UITextView! override func viewDidLoad() { super.viewDidLoad() - - loadSplashScreen() - - // set QR manager, needed in case app is being open by custom URL - qrCodeManager = QRCodeManager(delegate: self) - - // set up data source for list - fetchedResultsController = DataManager.sharedManager.checkInFetchedResultsController() - fetchedResultsController!.delegate = self - do { - try fetchedResultsController!.performFetch() - } catch { - print(error) - } - - // register for open custom URL events - NSNotificationCenter.defaultCenter().addObserver(self, selector: "openUrl:", name: AppDelegate.NotificationType.openUrl, object: nil) - - NSNotificationCenter.defaultCenter().addObserver(self, selector: "checkEULA:", name: UIApplicationWillEnterForegroundNotification, object: nil) - - checkEULA(NSNotification.init(name: "", object: nil)) - - navigationItem.title = NSLocalizedString("Header", comment: "") - bottomNote.text = NSLocalizedString("QR found", comment: "") - btnScan.setTitle(NSLocalizedString("Scan Code", comment: ""), forState: .Normal) - btnNoCode.setTitle(NSLocalizedString("No Code", comment: ""), forState: .Normal) - - // add logo to top left - let imageView = UIImageView(image: UIImage(named: "sap_logo")) - let barButtonItem = UIBarButtonItem(customView: imageView) - navigationItem.leftBarButtonItem = barButtonItem + setup() } - - func loadSplashScreen() { - - if let keyWindow = UIApplication.sharedApplication().keyWindow { - - vSplashScreen.translatesAutoresizingMaskIntoConstraints = false - keyWindow.addSubview(vSplashScreen) - - let lcTop = NSLayoutConstraint(item: vSplashScreen, - attribute: NSLayoutAttribute.Top, - relatedBy: NSLayoutRelation.Equal, - toItem: keyWindow, - attribute: NSLayoutAttribute.Top, - multiplier: 1.0, - constant: 0) - let lcBottom = NSLayoutConstraint(item: vSplashScreen, - attribute: NSLayoutAttribute.Bottom, - relatedBy: NSLayoutRelation.Equal, - toItem: keyWindow, - attribute: NSLayoutAttribute.Bottom, - multiplier: 1.0, - constant: 0) - let lcLeft = NSLayoutConstraint(item: vSplashScreen, - attribute: NSLayoutAttribute.Left, - relatedBy: NSLayoutRelation.Equal, - toItem: keyWindow, - attribute: NSLayoutAttribute.Left, - multiplier: 1.0, - constant: 0) - let lcRight = NSLayoutConstraint(item: vSplashScreen, - attribute: NSLayoutAttribute.Right, - relatedBy: NSLayoutRelation.Equal, - toItem: keyWindow, - attribute: NSLayoutAttribute.Right, - multiplier: 1.0, - constant: 0) - keyWindow.addConstraints([lcTop, lcBottom, lcLeft, lcRight]) - - weak var weakself = self - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(2 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in - weakself?.vSplashScreen.removeFromSuperview() - } - } - } - - deinit { + + override func viewDidAppear(animated: Bool) { + super.viewDidAppear(animated) + review() + subscribeForNewCheckInURLNotifications() + } + + override func viewWillDisappear(animated: Bool) { + super.viewWillDisappear(animated) + unsubscribeFromNewCheckInURLNotifications() + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + layout() + } + + // MARK: - Setup + + private func setup() { + setupButtons() + setupLocalization() + setupNavigationBar() + setupTableView() + setupTableViewDataSource() + setupTableViewHeader() + } + + private func setupButtons() { + scanCodeButton.setBackgroundImage(Images.BlueHighlighted, forState: .Highlighted) + noCodeButton.setBackgroundImage(Images.GrayHighlighted, forState: .Highlighted) + } + + private func setupLocalization() { + headerTitleLabel.text = Translation.HomeView.HeaderTitleLabel.Text.String + scanCodeButton.setTitle(Translation.ScanView.Title.String, forState: .Normal) + noCodeButton.setTitle(Translation.HomeView.NoCodeAlert.Title.String, forState: .Normal) + infoCodeLabel.text = Translation.HomeView.InfoCodeLabel.Text.String + footerTextView.text = Translation.HomeView.FooterTextView.Text.String + } + + private func setupNavigationBar() { + navigationItem.title = Application.Title + navigationItem.leftBarButtonItem = UIBarButtonItem(customView: UIImageView(image: UIImage(named: "sap_logo"))) + } + + private func setupTableView() { + tableView.rowHeight = UITableViewAutomaticDimension + tableView.estimatedRowHeight = 140 + } + + private func setupTableViewDataSource() { + do { + try fetchedResultsController.performFetch() + } catch { + logError("\(#function)", error: error) + } + } + + private func setupTableViewHeader() { + if fetchedResultsController.sections?[0].numberOfObjects ?? 0 == 0 { + tableView.tableHeaderView = nil + } else { + tableView.tableHeaderView = headerView + } + } + + // MARK: - Layout + + private func layout() { + self.layoutFooterView() + } + + private func layoutFooterView() { + let height = footerTextView.sizeThatFits(CGSizeMake(footerView.frame.width, CGFloat.max)).height + footerView.frame = CGRectMake(footerView.frame.origin.x, + footerView.frame.origin.y, + footerView.frame.width, + height + ) + } + + // MARK: - Review + + private func review() { + self.reviewTerms({ + logInfo("\(#function)", info: "Review terms done.") + self.reviewCodeConvention({ + logInfo("\(#function)", info: "Review code convention done.") + self.reviewGPSFixes({ + logInfo("\(#function)", info: "Review GPS fixes done.") + self.reviewNewCheckIn({ + logInfo("\(#function)", info: "Review new check-in done.") + self.reviewSelectedRegatta({ + logInfo("\(#function)", info: "Review selected regatta done.") + }) + }) + }) + }) + }) + } + + // MARK: 1. Review Terms + + private func reviewTerms(completion: () -> Void) { + guard Preferences.termsAccepted == false else { completion(); return } + let alertController = UIAlertController(title: Translation.HomeView.TermsAlert.Title.String, + message: Translation.HomeView.TermsAlert.Message.String, + preferredStyle: .Alert + ) + let showTermsAction = UIAlertAction(title: Translation.HomeView.TermsAlert.ShowTermsAction.Title.String, style: .Default) { action in + UIApplication.sharedApplication().openURL(URLs.Terms) + self.reviewTerms(completion) // Review terms until user accepted terms + } + let acceptTermsAction = UIAlertAction(title: Translation.HomeView.TermsAlert.AcceptTermsAction.Title.String, style: .Default) { action in + Preferences.termsAccepted = true + completion() // Terms accepted + } + alertController.addAction(showTermsAction) + alertController.addAction(acceptTermsAction) + presentViewController(alertController, animated: true, completion: nil) + } + + // MARK: 2. Review Code Convention + + private func reviewCodeConvention(completion: () -> Void) { + #if DEBUG + guard Preferences.codeConventionRead == false else { completion(); return } + let alertController = UIAlertController(title: "Code Convention", + message: "Please try to respect the code convention which is used for this project.", + preferredStyle: .Alert + ) + let showCodeConventionAction = UIAlertAction(title: "Code Convention", style: .Default) { action in + UIApplication.sharedApplication().openURL(URLs.CodeConvention) + self.reviewCodeConvention(completion) + } + let okAction = UIAlertAction(title: "OK", style: .Default) { action in + Preferences.codeConventionRead = true + completion() + } + alertController.addAction(showCodeConventionAction) + alertController.addAction(okAction) + presentViewController(alertController, animated: true, completion: nil) + #else + completion() + #endif + } + + // MARK: 3. Review GPS Fixes + + private func reviewGPSFixes(completion: () -> Void) { + SVProgressHUD.show() + fetchedResultsController.delegate = nil + var regattas = CoreDataManager.sharedManager.fetchRegattas() ?? [] + reviewGPSFixes(®attas) { + self.reviewGPSFixesCompleted(completion) + } + } + + private func reviewGPSFixes(inout regattas: [Regatta], completion: () -> Void) { + guard let regatta = regattas.popLast() else { completion(); return } + let gpsFixController = GPSFixController.init(regatta: regatta) + gpsFixController.sendAll({ (withSuccess) in + self.reviewGPSFixes(®attas, completion: completion) + }) + } + + private func reviewGPSFixesCompleted(completion: () -> Void) { + SVProgressHUD.popActivity() + fetchedResultsController.delegate = self + completion() + } + + // MARK: 4. Review New Check-In + + private func reviewNewCheckIn(completion: () -> Void) { + guard let urlString = Preferences.newCheckInURL else { completion(); return } + guard let regattaData = RegattaData(urlString: urlString) else { completion(); return } + checkInController.checkIn(regattaData, completion: { (withSuccess) in + Preferences.newCheckInURL = nil + self.selectedRegatta = CoreDataManager.sharedManager.fetchRegatta(regattaData) + completion() + }) + } + + // MARK: 5. Review Selected Regatta + + private func reviewSelectedRegatta(completion: () -> Void) { + guard shouldPerformRegattaSegue() else { completion(); return } + performSegueWithIdentifier(Segue.Regatta, sender: self) + completion() + } + + // MARK: - Notifications + + private func subscribeForNewCheckInURLNotifications() { + NSNotificationCenter.defaultCenter().addObserver(self, + selector: #selector(HomeViewController.newCheckInURLNotification(_:)), + name: Preferences.NotificationType.NewCheckInURLChanged, + object: nil) + } + + private func unsubscribeFromNewCheckInURLNotifications() { NSNotificationCenter.defaultCenter().removeObserver(self) } - - func checkEULA(n: NSNotification) { - // check that user accepted terms - if !NSUserDefaults.standardUserDefaults().boolForKey(Keys.acceptedTerms) { - - let alert = UIAlertController(title: NSLocalizedString("EULA_title", comment: ""), - message: NSLocalizedString("EULA_content", comment: ""), - preferredStyle: .Alert) - - let viewAction = UIAlertAction(title: NSLocalizedString("EULA_view", comment: ""), - style: .Cancel, - handler: { action in - UIApplication.sharedApplication().openURL(URLs.EULA) + + @objc private func newCheckInURLNotification(notification: NSNotification) { + dispatch_async(dispatch_get_main_queue(), { + self.reviewNewCheckIn({ + logInfo("\(#function)", info: "Review new check-in done.") + self.reviewSelectedRegatta({ + logInfo("\(#function)", info: "Review selected regatta done.") + }) }) - - let confirmAction = UIAlertAction(title: NSLocalizedString("EULA_confirm", comment: ""), - style: .Default, - handler: { action in - let preferences = NSUserDefaults.standardUserDefaults() - preferences.setBool(true, forKey:Keys.acceptedTerms) - preferences.synchronize() - }) - - alert.addAction(viewAction) - alert.addAction(confirmAction) - presentViewController(alert, animated: true, completion: nil) - } - } - - override func viewWillAppear(animated: Bool) { - super.viewWillAppear(animated) - DataManager.sharedManager.selectedCheckIn = nil; - } - - func openUrl(notification: NSNotification) { - let url = notification.userInfo!["url"] as! String - qrCodeManager!.parseUrl(url) - } - - func _DEBUG_OPEN_URL() { - let url = "http://ec2-54-171-89-140.eu-west-1.compute.amazonaws.com:8888/tracking/checkin?event_id=71c7b531-fb1b-441c-b2fa-f4e9ff672d60&leaderboard_name=Ubigatta&competitor_id=9df7b4f6-611b-4be0-b028-c7b1bdd434c2" - let url2 = "http://ec2-54-171-89-140.eu-west-1.compute.amazonaws.com:8888/tracking/checkin?event_id=71c7b531-fb1b-441c-b2fa-f4e9ff672d60&leaderboard_name=Ubigatta&competitor_id=a5a00800-daf8-0131-89e6-60a44ce903c3" - qrCodeManager!.parseUrl(url2) - } - - @IBAction func showActionSheet(sender: AnyObject) { - - let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet) - if let popoverController = actionSheet.popoverPresentationController, - let barButtonItem = sender as? UIBarButtonItem { - popoverController.barButtonItem = barButtonItem - } - - let aSettings = UIAlertAction(title: NSLocalizedString("Settings", comment: ""), style: .Default) { (action) -> Void in - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.6 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in - self.performSegueWithIdentifier("SettingsFromHome", sender: actionSheet) - } - } - actionSheet.addAction(aSettings) - - let aAbout = UIAlertAction(title: NSLocalizedString("About", comment: ""), style: .Default) { (action) -> Void in - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.6 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in - self.performSegueWithIdentifier("AboutFromHome", sender: actionSheet) - } - } - actionSheet.addAction(aAbout) - - let aCancel = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel, handler: nil) - actionSheet.addAction(aCancel) - - presentViewController(actionSheet, animated: true, completion: nil) + }) } - // MARK: - UITableViewDataSource + // MARK: - Actions - func resizeTable() { - let info = fetchedResultsController!.sections![0] - let rows = info.numberOfObjects - if rows < 3 { - tableView.removeConstraint(tableViewHeight) - tableViewHeight = NSLayoutConstraint(item: tableView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.Height, multiplier: 1.0, constant: CGFloat(22 + 44 * rows)) - tableView.addConstraint(tableViewHeight) - tableView.scrollEnabled = false + @IBAction func optionButtonTapped(sender: AnyObject) { + let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet) + if let popoverController = alertController.popoverPresentationController { + popoverController.barButtonItem = sender as? UIBarButtonItem + } + let settingsAction = UIAlertAction(title: Translation.SettingsView.Title.String, style: .Default) { (action) -> Void in + self.performSegueWithIdentifier(Segue.Settings, sender: alertController) + } + let aboutAction = UIAlertAction(title: Translation.Common.Info.String, style: .Default) { (action) -> Void in + self.performSegueWithIdentifier(Segue.About, sender: alertController) + } + let cancelAction = UIAlertAction(title: Translation.Common.Cancel.String, style: .Cancel, handler: nil) + alertController.addAction(settingsAction) + alertController.addAction(aboutAction) + alertController.addAction(cancelAction) + presentViewController(alertController, animated: true, completion: nil) + } + + @IBAction func scanButtonTapped(sender: AnyObject) { + if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera) { + performSegueWithIdentifier(Segue.Scan, sender: sender) } else { - tableView.removeConstraint(tableViewHeight) - tableViewHeight = NSLayoutConstraint(item: tableView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.Height, multiplier: 1.0, constant: CGFloat(22 + 44 * 3)) - tableView.addConstraint(tableViewHeight) - tableView.scrollEnabled = true + showNoCameraAlert() } } + @IBAction func noCodeButtonTapped(sender: AnyObject) { + showNoCodeAlert() + } + + // MARK: - Alerts + + private func showNoCameraAlert() { + let alertController = UIAlertController(title: Translation.Common.Error.String, + message: Translation.HomeView.NoCameraAlert.Message.String, + preferredStyle: .Alert + ) + let okAction = UIAlertAction(title: Translation.Common.OK.String, style: .Default, handler: nil) + alertController.addAction(okAction) + presentViewController(alertController, animated: true, completion: nil) + } + + private func showNoCodeAlert() { + let alertController = UIAlertController(title: Translation.HomeView.NoCodeAlert.Title.String, + message: Translation.HomeView.NoCodeAlert.Message.String, + preferredStyle: .Alert + ) + let okAction = UIAlertAction(title: Translation.Common.OK.String, style: .Default, handler: nil) + alertController.addAction(okAction) + presentViewController(alertController, animated: true, completion: nil) + } + + // MARK: - Segues + + override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool { + if (identifier == Segue.Regatta) { + return shouldPerformRegattaSegue() + } else { + return true + } + } + + private func shouldPerformRegattaSegue() -> Bool { + return selectedRegatta != nil + } + + override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { + if (segue.identifier == Segue.Regatta) { + guard let regattaVC = segue.destinationViewController as? RegattaViewController else { return } + regattaVC.regatta = selectedRegatta + selectedRegatta = nil + } else if (segue.identifier == Segue.Scan) { + guard let scanVC = segue.destinationViewController as? ScanViewController else { return } + scanVC.homeViewController = self + } + } + + // MARK: - Properties + + private lazy var checkInController: CheckInController = { + let checkInController = CheckInController() + checkInController.delegate = self + return checkInController + }() + + private lazy var fetchedResultsController: NSFetchedResultsController = { + let fetchedResultsController = CoreDataManager.sharedManager.regattaFetchedResultsController() + fetchedResultsController.delegate = self + return fetchedResultsController + }() + +} + +// MARK: - UITableViewDataSource + +extension HomeViewController: UITableViewDataSource { + func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - let info = fetchedResultsController!.sections![section] - resizeTable() - return info.numberOfObjects - } - - func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { - return NSLocalizedString("Your Regattas", comment: "") + return fetchedResultsController.sections?[section].numberOfObjects ?? 0 } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCellWithIdentifier("Regatta") as UITableViewCell! - configureCell(cell, atIndexPath: indexPath) + let cell = tableView.dequeueReusableCellWithIdentifier("Regatta") ?? UITableViewCell() + self.configureCell(cell, atIndexPath: indexPath) return cell } func configureCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) { - let checkIn = fetchedResultsController!.objectAtIndexPath(indexPath) as! CheckIn - cell.textLabel?.text = checkIn.leaderBoardName + guard let regattaCell = cell as? HomeViewRegattaCell else { return } + guard let regatta = fetchedResultsController.objectAtIndexPath(indexPath) as? Regatta else { return } + regattaCell.eventLabel.text = regatta.event.name + regattaCell.leaderboardLabel.text = regatta.leaderboard.name + regattaCell.competitorLabel.text = regatta.competitor.name } - // MARK: - NSFetchedResultsControllerDelegate +} + +// MARK: - UITableViewDelegate + +extension HomeViewController: UITableViewDelegate { + + func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? { + selectedRegatta = fetchedResultsController.objectAtIndexPath(indexPath) as? Regatta + return indexPath + } + + func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { + tableView.deselectRowAtIndexPath(indexPath, animated: true) + } + + func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { + cell.removeSeparatorInset() + } + +} + +// MARK: - NSFetchedResultsControllerDelegate + +extension HomeViewController: NSFetchedResultsControllerDelegate { func controllerWillChangeContent(controller: NSFetchedResultsController) { tableView.beginUpdates() } - func controller(controller: NSFetchedResultsController, didChangeObject object: AnyObject, atIndexPath indexPath: NSIndexPath?, - forChangeType type: NSFetchedResultsChangeType, - newIndexPath: NSIndexPath?) { - switch type { - case .Insert: - tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: UITableViewRowAnimation.Automatic) - case .Update: - let cell = tableView.cellForRowAtIndexPath(indexPath!) - if cell != nil { - configureCell(cell!, atIndexPath: indexPath!) - tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.Automatic) - } - case .Move: - tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.Automatic) - tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Automatic) - case .Delete: - tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.Automatic) - default: - return + func controller(controller: NSFetchedResultsController, + didChangeObject object: AnyObject, + atIndexPath indexPath: NSIndexPath?, + forChangeType type: NSFetchedResultsChangeType, + newIndexPath: NSIndexPath?) + { + switch type { + case .Insert: + tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: UITableViewRowAnimation.Automatic) + case .Update: + let cell = tableView.cellForRowAtIndexPath(indexPath!) + if cell != nil { + configureCell(cell!, atIndexPath: indexPath!) + tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.Automatic) } + case .Move: + tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.Automatic) + tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Automatic) + case .Delete: + tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.Automatic) + } } func controllerDidChangeContent(controller: NSFetchedResultsController) { tableView.endUpdates() + setupTableViewHeader() } - - // MARK: - UITableViewDelegate - - func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { - DataManager.sharedManager.selectedCheckIn = (fetchedResultsController!.objectAtIndexPath(indexPath) as! CheckIn) - tableView.deselectRowAtIndexPath(indexPath, animated: true) - performSegueWithIdentifier("Regatta", sender: tableView) - } - - // MARK: - Button actions - - @IBAction func scanButtonTap(sender: AnyObject) { - -// _DEBUG_OPEN_URL() -// return; - - if !UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera) { - let alertView = UIAlertView(title: NSLocalizedString("No camera available.", comment: ""), message: nil, delegate: nil, cancelButtonTitle: NSLocalizedString("Cancel", comment: "")) - alertView.tag = AlertView.NoCameraAvailable.rawValue; - alertView.show() - return - } - - if (!QRCodeManager.deviceCanReadQRCodes()) { - let alertView = UIAlertView(title: NSLocalizedString("Cannot read QR codes with this device.", comment: ""), message: nil, delegate: nil, cancelButtonTitle: NSLocalizedString("Cancel", comment: "")) - alertView.tag = AlertView.NoCameraAvailable.rawValue; - alertView.show() - return - } - performSegueWithIdentifier("Scan", sender: sender) - } - - @IBAction func noQrCodeButtonTap(sender: AnyObject) { - let alertView = UIAlertView(title: NSLocalizedString("In order to use this app you need to check-in via QR code or email link. Please contact the racing committee if you need either.", comment: ""), message: nil, delegate: nil, cancelButtonTitle: NSLocalizedString("Cancel", comment: "")) - alertView.tag = AlertView.NoCameraAvailable.rawValue; - alertView.show() - } - } +// MARK: - CheckInControllerDelegate + +extension HomeViewController: CheckInControllerDelegate { + + func showCheckInAlert(sender: CheckInController, alertController: UIAlertController) { + presentViewController(alertController, animated: true, completion: nil) + } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/HomeViewRegattaCell.swift b/ios/SAPTracker/src/xcode/SAPTracker/HomeViewRegattaCell.swift new file mode 100644 index 00000000000..7937105f804 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/HomeViewRegattaCell.swift @@ -0,0 +1,17 @@ +// +// HomeViewRegattaCell.swift +// SAPTracker +// +// Created by Raimund Wege on 26.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import UIKit + +class HomeViewRegattaCell: UITableViewCell { + + @IBOutlet weak var eventLabel: UILabel! + @IBOutlet weak var leaderboardLabel: UILabel! + @IBOutlet weak var competitorLabel: UILabel! + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/1024x768.png b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/1024x768.png deleted file mode 100644 index 4791fb7a795..00000000000 Binary files a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/1024x768.png and /dev/null differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/1242x2208.png b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/1242x2208.png deleted file mode 100644 index 79e7b048b33..00000000000 Binary files a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/1242x2208.png and /dev/null differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/1536x2048.png b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/1536x2048.png deleted file mode 100644 index dca2234c01f..00000000000 Binary files a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/1536x2048.png and /dev/null differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/2048x1536.png b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/2048x1536.png deleted file mode 100644 index 2ae477f3a28..00000000000 Binary files a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/2048x1536.png and /dev/null differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/2208x1242.png b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/2208x1242.png deleted file mode 100644 index d6cad0587ac..00000000000 Binary files a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/2208x1242.png and /dev/null differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/640x1136.png b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/640x1136.png deleted file mode 100644 index 8ddc958c6b5..00000000000 Binary files a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/640x1136.png and /dev/null differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/640x960.png b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/640x960.png deleted file mode 100644 index 5b29f9d7627..00000000000 Binary files a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/640x960.png and /dev/null differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/750x1334.png b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/750x1334.png deleted file mode 100644 index 435f4d2c43e..00000000000 Binary files a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/750x1334.png and /dev/null differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/768x1024.png b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/768x1024.png deleted file mode 100644 index e676f41e4a9..00000000000 Binary files a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/768x1024.png and /dev/null differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/Contents.json b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/Contents.json deleted file mode 100644 index 4499d2b100d..00000000000 --- a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/LaunchImage_old.launchimage/Contents.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "images" : [ - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "736h", - "filename" : "1242x2208.png", - "minimum-system-version" : "8.0", - "orientation" : "portrait", - "scale" : "3x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "736h", - "filename" : "2208x1242.png", - "minimum-system-version" : "8.0", - "orientation" : "landscape", - "scale" : "3x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "667h", - "filename" : "750x1334.png", - "minimum-system-version" : "8.0", - "orientation" : "portrait", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "iphone", - "filename" : "640x960.png", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "retina4", - "filename" : "640x1136.png", - "minimum-system-version" : "7.0", - "orientation" : "portrait", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "ipad", - "filename" : "768x1024.png", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "1x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "filename" : "1024x768.png", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "1x" - }, - { - "orientation" : "portrait", - "idiom" : "ipad", - "filename" : "1536x2048.png", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "filename" : "2048x1536.png", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/applogo.imageset/Contents.json b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/applogo.imageset/Contents.json index 92cdd2babf3..f7c897dc681 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/applogo.imageset/Contents.json +++ b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/applogo.imageset/Contents.json @@ -2,16 +2,17 @@ "images" : [ { "idiom" : "universal", + "filename" : "launch_screen_icon_xhdpi.png", "scale" : "1x" }, { "idiom" : "universal", - "filename" : "applogo@2x.png", + "filename" : "launch_screen_icon_xxhdpi.png", "scale" : "2x" }, { "idiom" : "universal", - "filename" : "applogo@3x.png", + "filename" : "launch_screen_icon_xxxhdpi.png", "scale" : "3x" } ], diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/applogo.imageset/applogo@2x.png b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/applogo.imageset/applogo@2x.png deleted file mode 100644 index 9a4fd2796a0..00000000000 Binary files a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/applogo.imageset/applogo@2x.png and /dev/null differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/applogo.imageset/applogo@3x.png b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/applogo.imageset/applogo@3x.png deleted file mode 100644 index a408e2c793e..00000000000 Binary files a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/applogo.imageset/applogo@3x.png and /dev/null differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/applogo.imageset/launch_screen_icon_xhdpi.png b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/applogo.imageset/launch_screen_icon_xhdpi.png new file mode 100644 index 00000000000..5c68fd94b98 Binary files /dev/null and b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/applogo.imageset/launch_screen_icon_xhdpi.png differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/applogo.imageset/launch_screen_icon_xxhdpi.png b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/applogo.imageset/launch_screen_icon_xxhdpi.png new file mode 100644 index 00000000000..2d5a0a8eb05 Binary files /dev/null and b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/applogo.imageset/launch_screen_icon_xxhdpi.png differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/applogo.imageset/launch_screen_icon_xxxhdpi.png b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/applogo.imageset/launch_screen_icon_xxxhdpi.png new file mode 100644 index 00000000000..f7caf8567bc Binary files /dev/null and b/ios/SAPTracker/src/xcode/SAPTracker/Images.xcassets/applogo.imageset/launch_screen_icon_xxxhdpi.png differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Info.plist b/ios/SAPTracker/src/xcode/SAPTracker/Info.plist index 78a2feb5690..c9144059cf0 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/Info.plist +++ b/ios/SAPTracker/src/xcode/SAPTracker/Info.plist @@ -28,9 +28,17 @@ comsapsailingtracker + + CFBundleTypeRole + Editor + CFBundleURLSchemes + + prefs + + CFBundleVersion - 37 + 2.0.0-rc2 LSRequiresIPhoneOS NSAppTransportSecurity @@ -49,6 +57,7 @@ UIBackgroundModes + fetch location UILaunchStoryboardName @@ -63,7 +72,7 @@ UIRequiresFullScreen UIStatusBarStyle - UIStatusBarStyleLightContent + UIStatusBarStyleDefault UISupportedInterfaceOrientations UIInterfaceOrientationPortrait diff --git a/ios/SAPTracker/src/xcode/SAPTracker/LaunchScreen.storyboard b/ios/SAPTracker/src/xcode/SAPTracker/LaunchScreen.storyboard index f6bb9acf486..877a58bd709 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/LaunchScreen.storyboard +++ b/ios/SAPTracker/src/xcode/SAPTracker/LaunchScreen.storyboard @@ -1,10 +1,15 @@ - + - + + + + OpenSans + + @@ -18,19 +23,41 @@ - - + + + + + + + + + + + - + + + + + + + - + - + - - - - + + + + + + @@ -40,6 +67,6 @@ - + diff --git a/ios/SAPTracker/src/xcode/SAPTracker/LeaderBoard.swift b/ios/SAPTracker/src/xcode/SAPTracker/LeaderBoard.swift deleted file mode 100644 index e27f3e1be96..00000000000 --- a/ios/SAPTracker/src/xcode/SAPTracker/LeaderBoard.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// LeaderBoard.swift -// SAPTracker -// -// Created by computing on 14/11/14. -// Copyright (c) 2014 com.sap.sailing. All rights reserved. -// - -import Foundation -import CoreData - -@objc(LeaderBoard) -public class LeaderBoard: NSManagedObject { - - @NSManaged public var name: String - @NSManaged public var checkIn: CheckIn? - - public func initWithDictionary(dictionary: Dictionary) { - name = dictionary["name"] as! String - } - -} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/LeaderBoardViewController.swift b/ios/SAPTracker/src/xcode/SAPTracker/LeaderBoardViewController.swift deleted file mode 100644 index 9dca5659a6b..00000000000 --- a/ios/SAPTracker/src/xcode/SAPTracker/LeaderBoardViewController.swift +++ /dev/null @@ -1,42 +0,0 @@ -// -// LeaderBoardViewController.swift -// SAPTracker -// -// Created by computing on 08/12/14. -// Copyright (c) 2014 com.sap.sailing. All rights reserved. -// - -import Foundation - -class LeaderBoardViewController: UIViewController, UIWebViewDelegate, UIAlertViewDelegate { - - @IBOutlet weak var webView: UIWebView! - @IBOutlet weak var activityIndicator: UIActivityIndicatorView! - - override func viewDidLoad() { - super.viewDidLoad() - let serverUrl = DataManager.sharedManager.selectedCheckIn!.serverUrl - let eventId = DataManager.sharedManager.selectedCheckIn!.eventId - let leaderBoardName = DataManager.sharedManager.selectedCheckIn!.leaderBoardName.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)! - let url = "\(serverUrl)/gwt/Leaderboard.html?name=\(leaderBoardName)&showRaceDetails=false&embedded=true&hideToolbar=true" - webView!.loadRequest(NSURLRequest(URL: NSURL(string: url)!)) - } - - @IBAction func done(sender: AnyObject) { - presentingViewController!.dismissViewControllerAnimated(true, completion: nil) - } - - func webViewDidFinishLoad(webView: UIWebView) { - activityIndicator.stopAnimating() - } - - func wwebView(webView: UIWebView, didFailLoadWithError error: NSError) { - activityIndicator.hidden = true - let alertView = UIAlertView(title: NSLocalizedString("Couldn't load about view", comment: ""), message: nil, delegate: nil, cancelButtonTitle: NSLocalizedString("Cancel", comment: "")) - alertView.show() - } - - func alertView(alertView: UIAlertView, clickedButtonAtIndex buttonIndex: Int) { - presentingViewController!.dismissViewControllerAnimated(true, completion: nil) - } -} \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Leaderboard+CoreDataProperties.swift b/ios/SAPTracker/src/xcode/SAPTracker/Leaderboard+CoreDataProperties.swift new file mode 100644 index 00000000000..a2705c7fdd5 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Leaderboard+CoreDataProperties.swift @@ -0,0 +1,20 @@ +// +// Leaderboard+CoreDataProperties.swift +// SAPTracker +// +// Created by Raimund Wege on 04.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// +// Choose "Create NSManagedObject Subclass…" from the Core Data editor menu +// to delete and recreate this implementation file for your updated model. +// + +import Foundation +import CoreData + +extension Leaderboard { + + @NSManaged var name: String + @NSManaged var regatta: Regatta + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Leaderboard.swift b/ios/SAPTracker/src/xcode/SAPTracker/Leaderboard.swift new file mode 100644 index 00000000000..d421cf63c56 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Leaderboard.swift @@ -0,0 +1,23 @@ +// +// Leaderboard.swift +// SAPTracker +// +// Created by Raimund Wege on 04.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import Foundation +import CoreData + +@objc(Leaderboard) +class Leaderboard: NSManagedObject { + + func updateWithLeaderboardData(leaderboardData: LeaderboardData) { + name = leaderboardData.name + } + + func nameWithQueryAllowedCharacters() -> String? { + return name.stringByAddingPercentEncodingWithAllowedCharacters(.URLQueryAllowedCharacterSet()) + } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/LeaderboardData.swift b/ios/SAPTracker/src/xcode/SAPTracker/LeaderboardData.swift new file mode 100644 index 00000000000..0477dc524d5 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/LeaderboardData.swift @@ -0,0 +1,19 @@ +// +// LeaderboardData.swift +// SAPTracker +// +// Created by Raimund Wege on 05.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import UIKit + +class LeaderboardData: BaseData { + + private struct Keys { + static let Name = "name" + } + + var name: String { get { return stringValue(forKey: Keys.Name) } } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/LeaderboardViewController.swift b/ios/SAPTracker/src/xcode/SAPTracker/LeaderboardViewController.swift new file mode 100644 index 00000000000..782eed22281 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/LeaderboardViewController.swift @@ -0,0 +1,65 @@ +// +// LeaderboardViewController.swift +// SAPTracker +// +// Created by Raimund Wege on 04.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import Foundation + +class LeaderboardViewController: UIViewController { + + var regatta: Regatta! + + @IBOutlet weak var webView: UIWebView! + @IBOutlet weak var activityIndicator: UIActivityIndicatorView! + + override func viewDidLoad() { + super.viewDidLoad() + setup() + } + + // MARK: - Setup + + private func setup() { + setupLocalization() + setupWebView() + } + + private func setupLocalization() { + navigationItem.title = Translation.LeaderboardView.Title.String + } + + private func setupWebView() { + guard let url = regatta.leaderboardURL() else { return } + webView.loadRequest(NSURLRequest(URL: url)) + } + + // MARK: - Actions + + @IBAction func doneButtonTapped(sender: AnyObject) { + presentingViewController!.dismissViewControllerAnimated(true, completion: nil) + } + +} + +// MARK: - UIWebViewDelegate + +extension LeaderboardViewController: UIWebViewDelegate { + + func webViewDidFinishLoad(webView: UIWebView) { + activityIndicator.stopAnimating() + } + + func webView(webView: UIWebView, didFailLoadWithError error: NSError?) { + activityIndicator.stopAnimating() + let alertController = UIAlertController(title: error?.localizedDescription, message: nil, preferredStyle: .Alert) + let okAction = UIAlertAction(title: Translation.Common.OK.String, style: .Default) { (action) in + self.presentingViewController!.dismissViewControllerAnimated(true, completion: nil) + } + alertController.addAction(okAction) + presentViewController(alertController, animated: true, completion: nil) + } + +} diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperation.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFHTTPRequestOperation.h old mode 100644 new mode 100755 similarity index 87% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperation.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFHTTPRequestOperation.h index dfa82f66916..cf6def4e3e4 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperation.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFHTTPRequestOperation.h @@ -1,6 +1,5 @@ // AFHTTPRequestOperation.h -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -23,6 +22,8 @@ #import #import "AFURLConnectionOperation.h" +NS_ASSUME_NONNULL_BEGIN + /** `AFHTTPRequestOperation` is a subclass of `AFURLConnectionOperation` for requests using the HTTP or HTTPS protocols. It encapsulates the concept of acceptable status codes and content types, which determine the success or failure of a request. */ @@ -35,19 +36,19 @@ /** The last HTTP response received by the operation's connection. */ -@property (readonly, nonatomic, strong) NSHTTPURLResponse *response; +@property (readonly, nonatomic, strong, nullable) NSHTTPURLResponse *response; /** Responses sent from the server in data tasks created with `dataTaskWithRequest:success:failure:` and run using the `GET` / `POST` / et al. convenience methods are automatically validated and serialized by the response serializer. By default, this property is set to an AFHTTPResponse serializer, which uses the raw data as its response object. The serializer validates the status code to be in the `2XX` range, denoting success. If the response serializer generates an error in `-responseObjectForResponse:data:error:`, the `failure` callback of the session task or request operation will be executed; otherwise, the `success` callback will be executed. - @warning `responseSerializer` must not be `nil`. Setting a response serializer will clear out any cached value + @warning `responseSerializer` must not be `nil`. Setting a response serializer will clear out any cached value */ @property (nonatomic, strong) AFHTTPResponseSerializer * responseSerializer; /** An object constructed by the `responseSerializer` from the response and response data. Returns `nil` unless the operation `isFinished`, has a `response`, and has `responseData` with non-zero content length. If an error occurs during serialization, `nil` will be returned, and the `error` property will be populated with the serialization error. */ -@property (readonly, nonatomic, strong) id responseObject; +@property (readonly, nonatomic, strong, nullable) id responseObject; ///----------------------------------------------------------- /// @name Setting Completion Block Success / Failure Callbacks @@ -57,11 +58,13 @@ Sets the `completionBlock` property with a block that executes either the specified success or failure block, depending on the state of the request on completion. If `error` returns a value, which can be caused by an unacceptable status code or content type, then `failure` is executed. Otherwise, `success` is executed. This method should be overridden in subclasses in order to specify the response object passed into the success block. - + @param success The block to be executed on the completion of a successful request. This block has no return value and takes two arguments: the receiver operation and the object constructed from the response data of the request. @param failure The block to be executed on the completion of an unsuccessful request. This block has no return value and takes two arguments: the receiver operation and the error that occurred during the request. */ -- (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; +- (void)setCompletionBlockWithSuccess:(nullable void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(nullable void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; @end + +NS_ASSUME_NONNULL_END diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperation.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFHTTPRequestOperation.m old mode 100644 new mode 100755 similarity index 98% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperation.m rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFHTTPRequestOperation.m index 1de5812ca14..b8deda839a4 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperation.m +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFHTTPRequestOperation.m @@ -1,6 +1,5 @@ // AFHTTPRequestOperation.m -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -57,6 +56,7 @@ static dispatch_group_t http_request_operation_completion_group() { @end @implementation AFHTTPRequestOperation +@dynamic response; @dynamic lock; - (instancetype)initWithRequest:(NSURLRequest *)urlRequest { diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperationManager.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFHTTPRequestOperationManager.h old mode 100644 new mode 100755 similarity index 80% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperationManager.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFHTTPRequestOperationManager.h index 9f390294e22..81708116541 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperationManager.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFHTTPRequestOperationManager.h @@ -1,6 +1,5 @@ // AFHTTPRequestOperationManager.h -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -36,23 +35,33 @@ #import "AFSecurityPolicy.h" #import "AFNetworkReachabilityManager.h" +#ifndef NS_DESIGNATED_INITIALIZER +#if __has_attribute(objc_designated_initializer) +#define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) +#else +#define NS_DESIGNATED_INITIALIZER +#endif +#endif + +NS_ASSUME_NONNULL_BEGIN + /** `AFHTTPRequestOperationManager` encapsulates the common patterns of communicating with a web application over HTTP, including request creation, response serialization, network reachability monitoring, and security, as well as request operation management. ## Subclassing Notes - + Developers targeting iOS 7 or Mac OS X 10.9 or later that deal extensively with a web service are encouraged to subclass `AFHTTPSessionManager`, providing a class method that returns a shared singleton object on which authentication and other configuration can be shared across the application. - + For developers targeting iOS 6 or Mac OS X 10.8 or earlier, `AFHTTPRequestOperationManager` may be used to similar effect. - + ## Methods to Override To change the behavior of all request operation construction for an `AFHTTPRequestOperationManager` subclass, override `HTTPRequestOperationWithRequest:success:failure`. ## Serialization - - Requests created by an HTTP client will contain default headers and encode parameters according to the `requestSerializer` property, which is an object conforming to ``. - + + Requests created by an HTTP client will contain default headers and encode parameters according to the `requestSerializer` property, which is an object conforming to ``. + Responses received from the server are automatically validated and serialized by the `responseSerializers` property, which is an object conforming to `` ## URL Construction Using Relative Paths @@ -87,11 +96,11 @@ /** The URL used to monitor reachability, and construct requests from relative paths in methods like `requestWithMethod:URLString:parameters:`, and the `GET` / `POST` / et al. convenience methods. */ -@property (readonly, nonatomic, strong) NSURL *baseURL; +@property (readonly, nonatomic, strong, nullable) NSURL *baseURL; /** Requests created with `requestWithMethod:URLString:parameters:` & `multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:` are constructed with a set of default headers using a parameter serialization specified by this property. By default, this is set to an instance of `AFHTTPRequestSerializer`, which serializes query string parameters for `GET`, `HEAD`, and `DELETE` requests, or otherwise URL-form-encodes HTTP message bodies. - + @warning `requestSerializer` must not be `nil`. */ @property (nonatomic, strong) AFHTTPRequestSerializer * requestSerializer; @@ -124,7 +133,7 @@ @see AFURLConnectionOperation -credential */ -@property (nonatomic, strong) NSURLCredential *credential; +@property (nonatomic, strong, nullable) NSURLCredential *credential; ///------------------------------- /// @name Managing Security Policy @@ -151,12 +160,20 @@ /** The dispatch queue for the `completionBlock` of request operations. If `NULL` (default), the main queue is used. */ -@property (nonatomic, strong) dispatch_queue_t completionQueue; +#if OS_OBJECT_USE_OBJC +@property (nonatomic, strong, nullable) dispatch_queue_t completionQueue; +#else +@property (nonatomic, assign, nullable) dispatch_queue_t completionQueue; +#endif /** The dispatch group for the `completionBlock` of request operations. If `NULL` (default), a private dispatch group is used. */ -@property (nonatomic, strong) dispatch_group_t completionGroup; +#if OS_OBJECT_USE_OBJC +@property (nonatomic, strong, nullable) dispatch_group_t completionGroup; +#else +@property (nonatomic, assign, nullable) dispatch_group_t completionGroup; +#endif ///--------------------------------------------- /// @name Creating and Initializing HTTP Clients @@ -169,14 +186,14 @@ /** Initializes an `AFHTTPRequestOperationManager` object with the specified base URL. - + This is the designated initializer. - + @param url The base URL for the HTTP client. @return The newly-initialized HTTP client */ -- (instancetype)initWithBaseURL:(NSURL *)url; +- (instancetype)initWithBaseURL:(nullable NSURL *)url NS_DESIGNATED_INITIALIZER; ///--------------------------------------- /// @name Managing HTTP Request Operations @@ -190,8 +207,8 @@ @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes two arguments:, the created request operation and the `NSError` object describing the network or parsing error that occurred. */ - (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)request - success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; + success:(nullable void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(nullable void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; ///--------------------------- /// @name Making HTTP Requests @@ -207,10 +224,10 @@ @see -HTTPRequestOperationWithRequest:success:failure: */ -- (AFHTTPRequestOperation *)GET:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; +- (nullable AFHTTPRequestOperation *)GET:(NSString *)URLString + parameters:(nullable id)parameters + success:(nullable void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(nullable void (^)(AFHTTPRequestOperation * __nullable operation, NSError *error))failure; /** Creates and runs an `AFHTTPRequestOperation` with a `HEAD` request. @@ -222,10 +239,10 @@ @see -HTTPRequestOperationWithRequest:success:failure: */ -- (AFHTTPRequestOperation *)HEAD:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(AFHTTPRequestOperation *operation))success - failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; +- (nullable AFHTTPRequestOperation *)HEAD:(NSString *)URLString + parameters:(nullable id)parameters + success:(nullable void (^)(AFHTTPRequestOperation *operation))success + failure:(nullable void (^)(AFHTTPRequestOperation * __nullable operation, NSError *error))failure; /** Creates and runs an `AFHTTPRequestOperation` with a `POST` request. @@ -237,10 +254,10 @@ @see -HTTPRequestOperationWithRequest:success:failure: */ -- (AFHTTPRequestOperation *)POST:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; +- (nullable AFHTTPRequestOperation *)POST:(NSString *)URLString + parameters:(nullable id)parameters + success:(nullable void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(nullable void (^)(AFHTTPRequestOperation * __nullable operation, NSError *error))failure; /** Creates and runs an `AFHTTPRequestOperation` with a multipart `POST` request. @@ -253,11 +270,11 @@ @see -HTTPRequestOperationWithRequest:success:failure: */ -- (AFHTTPRequestOperation *)POST:(NSString *)URLString - parameters:(id)parameters - constructingBodyWithBlock:(void (^)(id formData))block - success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; +- (nullable AFHTTPRequestOperation *)POST:(NSString *)URLString + parameters:(nullable id)parameters + constructingBodyWithBlock:(nullable void (^)(id formData))block + success:(nullable void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(nullable void (^)(AFHTTPRequestOperation * __nullable operation, NSError *error))failure; /** Creates and runs an `AFHTTPRequestOperation` with a `PUT` request. @@ -269,10 +286,10 @@ @see -HTTPRequestOperationWithRequest:success:failure: */ -- (AFHTTPRequestOperation *)PUT:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; +- (nullable AFHTTPRequestOperation *)PUT:(NSString *)URLString + parameters:(nullable id)parameters + success:(nullable void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(nullable void (^)(AFHTTPRequestOperation * __nullable operation, NSError *error))failure; /** Creates and runs an `AFHTTPRequestOperation` with a `PATCH` request. @@ -284,10 +301,10 @@ @see -HTTPRequestOperationWithRequest:success:failure: */ -- (AFHTTPRequestOperation *)PATCH:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; +- (nullable AFHTTPRequestOperation *)PATCH:(NSString *)URLString + parameters:(nullable id)parameters + success:(nullable void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(nullable void (^)(AFHTTPRequestOperation * __nullable operation, NSError *error))failure; /** Creates and runs an `AFHTTPRequestOperation` with a `DELETE` request. @@ -299,10 +316,11 @@ @see -HTTPRequestOperationWithRequest:success:failure: */ -- (AFHTTPRequestOperation *)DELETE:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success - failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; +- (nullable AFHTTPRequestOperation *)DELETE:(NSString *)URLString + parameters:(nullable id)parameters + success:(nullable void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(nullable void (^)(AFHTTPRequestOperation * __nullable operation, NSError *error))failure; @end +NS_ASSUME_NONNULL_END diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperationManager.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFHTTPRequestOperationManager.m old mode 100644 new mode 100755 similarity index 76% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperationManager.m rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFHTTPRequestOperationManager.m index 4ae72754804..ee682b794ed --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFHTTPRequestOperationManager.m +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFHTTPRequestOperationManager.m @@ -1,6 +1,5 @@ // AFHTTPRequestOperationManager.m -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -43,7 +42,7 @@ } - (instancetype)init { - return [self initWithBaseURL:nil]; + return [self initWithBaseURL:nil]; } - (instancetype)initWithBaseURL:(NSURL *)url { @@ -92,6 +91,30 @@ #pragma mark - +- (AFHTTPRequestOperation *)HTTPRequestOperationWithHTTPMethod:(NSString *)method + URLString:(NSString *)URLString + parameters:(id)parameters + success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success + failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure +{ + NSError *serializationError = nil; + NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError]; + if (serializationError) { + if (failure) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgnu" + dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ + failure(nil, serializationError); + }); +#pragma clang diagnostic pop + } + + return nil; + } + + return [self HTTPRequestOperationWithRequest:request success:success failure:failure]; +} + - (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)request success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure @@ -116,8 +139,7 @@ success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { - NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"GET" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil]; - AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure]; + AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithHTTPMethod:@"GET" URLString:URLString parameters:parameters success:success failure:failure]; [self.operationQueue addOperation:operation]; @@ -129,8 +151,7 @@ success:(void (^)(AFHTTPRequestOperation *operation))success failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { - NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"HEAD" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil]; - AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *requestOperation, __unused id responseObject) { + AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithHTTPMethod:@"HEAD" URLString:URLString parameters:parameters success:^(AFHTTPRequestOperation *requestOperation, __unused id responseObject) { if (success) { success(requestOperation); } @@ -146,8 +167,7 @@ success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { - NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil]; - AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure]; + AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithHTTPMethod:@"POST" URLString:URLString parameters:parameters success:success failure:failure]; [self.operationQueue addOperation:operation]; @@ -160,7 +180,21 @@ success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { - NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:nil]; + NSError *serializationError = nil; + NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:&serializationError]; + if (serializationError) { + if (failure) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgnu" + dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ + failure(nil, serializationError); + }); +#pragma clang diagnostic pop + } + + return nil; + } + AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure]; [self.operationQueue addOperation:operation]; @@ -173,8 +207,7 @@ success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { - NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"PUT" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil]; - AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure]; + AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithHTTPMethod:@"PUT" URLString:URLString parameters:parameters success:success failure:failure]; [self.operationQueue addOperation:operation]; @@ -186,8 +219,7 @@ success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { - NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"PATCH" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil]; - AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure]; + AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithHTTPMethod:@"PATCH" URLString:URLString parameters:parameters success:success failure:failure]; [self.operationQueue addOperation:operation]; @@ -199,8 +231,7 @@ success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { - NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"DELETE" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:nil]; - AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure]; + AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithHTTPMethod:@"DELETE" URLString:URLString parameters:parameters success:success failure:failure]; [self.operationQueue addOperation:operation]; @@ -229,6 +260,10 @@ self.requestSerializer = [decoder decodeObjectOfClass:[AFHTTPRequestSerializer class] forKey:NSStringFromSelector(@selector(requestSerializer))]; self.responseSerializer = [decoder decodeObjectOfClass:[AFHTTPResponseSerializer class] forKey:NSStringFromSelector(@selector(responseSerializer))]; + AFSecurityPolicy *decodedPolicy = [decoder decodeObjectOfClass:[AFSecurityPolicy class] forKey:NSStringFromSelector(@selector(securityPolicy))]; + if (decodedPolicy) { + self.securityPolicy = decodedPolicy; + } return self; } @@ -237,6 +272,7 @@ [coder encodeObject:self.baseURL forKey:NSStringFromSelector(@selector(baseURL))]; [coder encodeObject:self.requestSerializer forKey:NSStringFromSelector(@selector(requestSerializer))]; [coder encodeObject:self.responseSerializer forKey:NSStringFromSelector(@selector(responseSerializer))]; + [coder encodeObject:self.securityPolicy forKey:NSStringFromSelector(@selector(securityPolicy))]; } #pragma mark - NSCopying @@ -246,7 +282,8 @@ HTTPClient.requestSerializer = [self.requestSerializer copyWithZone:zone]; HTTPClient.responseSerializer = [self.responseSerializer copyWithZone:zone]; - + HTTPClient.securityPolicy = [self.securityPolicy copyWithZone:zone]; + return HTTPClient; } diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFHTTPSessionManager.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFHTTPSessionManager.h old mode 100644 new mode 100755 similarity index 78% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFHTTPSessionManager.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFHTTPSessionManager.h index 8fed5a68919..04b087626fa --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFHTTPSessionManager.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFHTTPSessionManager.h @@ -1,6 +1,5 @@ // AFHTTPSessionManager.h -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -21,7 +20,9 @@ // THE SOFTWARE. #import +#if !TARGET_OS_WATCH #import +#endif #import #if __IPHONE_OS_VERSION_MIN_REQUIRED @@ -32,6 +33,14 @@ #import "AFURLSessionManager.h" +#ifndef NS_DESIGNATED_INITIALIZER +#if __has_attribute(objc_designated_initializer) +#define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) +#else +#define NS_DESIGNATED_INITIALIZER +#endif +#endif + /** `AFHTTPSessionManager` is a subclass of `AFURLSessionManager` with convenience methods for making HTTP requests. When a `baseURL` is provided, requests made with the `GET` / `POST` / et al. convenience methods can be made with relative paths. @@ -70,14 +79,16 @@ @warning Managers for background sessions must be owned for the duration of their use. This can be accomplished by creating an application-wide or shared singleton instance. */ -#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090) +#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090) || TARGET_OS_WATCH + +NS_ASSUME_NONNULL_BEGIN @interface AFHTTPSessionManager : AFURLSessionManager /** - The URL used to monitor reachability, and construct requests from relative paths in methods like `requestWithMethod:URLString:parameters:`, and the `GET` / `POST` / et al. convenience methods. + The URL used to construct requests from relative paths in methods like `requestWithMethod:URLString:parameters:`, and the `GET` / `POST` / et al. convenience methods. */ -@property (readonly, nonatomic, strong) NSURL *baseURL; +@property (readonly, nonatomic, strong, nullable) NSURL *baseURL; /** Requests created with `requestWithMethod:URLString:parameters:` & `multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:` are constructed with a set of default headers using a parameter serialization specified by this property. By default, this is set to an instance of `AFHTTPRequestSerializer`, which serializes query string parameters for `GET`, `HEAD`, and `DELETE` requests, or otherwise URL-form-encodes HTTP message bodies. @@ -109,7 +120,7 @@ @return The newly-initialized HTTP client */ -- (instancetype)initWithBaseURL:(NSURL *)url; +- (instancetype)initWithBaseURL:(nullable NSURL *)url; /** Initializes an `AFHTTPSessionManager` object with the specified base URL. @@ -121,8 +132,8 @@ @return The newly-initialized HTTP client */ -- (instancetype)initWithBaseURL:(NSURL *)url - sessionConfiguration:(NSURLSessionConfiguration *)configuration; +- (instancetype)initWithBaseURL:(nullable NSURL *)url + sessionConfiguration:(nullable NSURLSessionConfiguration *)configuration NS_DESIGNATED_INITIALIZER; ///--------------------------- /// @name Making HTTP Requests @@ -138,10 +149,10 @@ @see -dataTaskWithRequest:completionHandler: */ -- (NSURLSessionDataTask *)GET:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; +- (nullable NSURLSessionDataTask *)GET:(NSString *)URLString + parameters:(nullable id)parameters + success:(nullable void (^)(NSURLSessionDataTask *task, id responseObject))success + failure:(nullable void (^)(NSURLSessionDataTask * __nullable task, NSError *error))failure; /** Creates and runs an `NSURLSessionDataTask` with a `HEAD` request. @@ -153,10 +164,10 @@ @see -dataTaskWithRequest:completionHandler: */ -- (NSURLSessionDataTask *)HEAD:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(NSURLSessionDataTask *task))success - failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; +- (nullable NSURLSessionDataTask *)HEAD:(NSString *)URLString + parameters:(nullable id)parameters + success:(nullable void (^)(NSURLSessionDataTask *task))success + failure:(nullable void (^)(NSURLSessionDataTask * __nullable task, NSError *error))failure; /** Creates and runs an `NSURLSessionDataTask` with a `POST` request. @@ -168,10 +179,10 @@ @see -dataTaskWithRequest:completionHandler: */ -- (NSURLSessionDataTask *)POST:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; +- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString + parameters:(nullable id)parameters + success:(nullable void (^)(NSURLSessionDataTask *task, id responseObject))success + failure:(nullable void (^)(NSURLSessionDataTask * __nullable task, NSError *error))failure; /** Creates and runs an `NSURLSessionDataTask` with a multipart `POST` request. @@ -184,11 +195,11 @@ @see -dataTaskWithRequest:completionHandler: */ -- (NSURLSessionDataTask *)POST:(NSString *)URLString - parameters:(id)parameters - constructingBodyWithBlock:(void (^)(id formData))block - success:(void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; +- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString + parameters:(nullable id)parameters + constructingBodyWithBlock:(nullable void (^)(id formData))block + success:(nullable void (^)(NSURLSessionDataTask *task, id responseObject))success + failure:(nullable void (^)(NSURLSessionDataTask * __nullable task, NSError *error))failure; /** Creates and runs an `NSURLSessionDataTask` with a `PUT` request. @@ -200,10 +211,10 @@ @see -dataTaskWithRequest:completionHandler: */ -- (NSURLSessionDataTask *)PUT:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; +- (nullable NSURLSessionDataTask *)PUT:(NSString *)URLString + parameters:(nullable id)parameters + success:(nullable void (^)(NSURLSessionDataTask *task, id responseObject))success + failure:(nullable void (^)(NSURLSessionDataTask * __nullable task, NSError *error))failure; /** Creates and runs an `NSURLSessionDataTask` with a `PATCH` request. @@ -215,10 +226,10 @@ @see -dataTaskWithRequest:completionHandler: */ -- (NSURLSessionDataTask *)PATCH:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; +- (nullable NSURLSessionDataTask *)PATCH:(NSString *)URLString + parameters:(nullable id)parameters + success:(nullable void (^)(NSURLSessionDataTask *task, id responseObject))success + failure:(nullable void (^)(NSURLSessionDataTask * __nullable task, NSError *error))failure; /** Creates and runs an `NSURLSessionDataTask` with a `DELETE` request. @@ -230,11 +241,13 @@ @see -dataTaskWithRequest:completionHandler: */ -- (NSURLSessionDataTask *)DELETE:(NSString *)URLString - parameters:(id)parameters - success:(void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; +- (nullable NSURLSessionDataTask *)DELETE:(NSString *)URLString + parameters:(nullable id)parameters + success:(nullable void (^)(NSURLSessionDataTask *task, id responseObject))success + failure:(nullable void (^)(NSURLSessionDataTask * __nullable task, NSError *error))failure; @end +NS_ASSUME_NONNULL_END + #endif diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFHTTPSessionManager.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFHTTPSessionManager.m old mode 100644 new mode 100755 similarity index 94% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFHTTPSessionManager.m rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFHTTPSessionManager.m index 6413297d720..ed46b26d3cf --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFHTTPSessionManager.m +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFHTTPSessionManager.m @@ -1,6 +1,5 @@ // AFHTTPSessionManager.m -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -22,7 +21,7 @@ #import "AFHTTPSessionManager.h" -#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090) +#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090) || TARGET_WATCH_OS #import "AFURLRequestSerialization.h" #import "AFURLResponseSerialization.h" @@ -38,8 +37,10 @@ #import #endif -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#if TARGET_OS_IOS #import +#elif TARGET_OS_WATCH +#import #endif @interface AFHTTPSessionManager () @@ -47,6 +48,7 @@ @end @implementation AFHTTPSessionManager +@dynamic responseSerializer; + (instancetype)manager { return [[[self class] alloc] initWithBaseURL:nil]; @@ -288,6 +290,10 @@ self.requestSerializer = [decoder decodeObjectOfClass:[AFHTTPRequestSerializer class] forKey:NSStringFromSelector(@selector(requestSerializer))]; self.responseSerializer = [decoder decodeObjectOfClass:[AFHTTPResponseSerializer class] forKey:NSStringFromSelector(@selector(responseSerializer))]; + AFSecurityPolicy *decodedPolicy = [decoder decodeObjectOfClass:[AFSecurityPolicy class] forKey:NSStringFromSelector(@selector(securityPolicy))]; + if (decodedPolicy) { + self.securityPolicy = decodedPolicy; + } return self; } @@ -303,6 +309,7 @@ } [coder encodeObject:self.requestSerializer forKey:NSStringFromSelector(@selector(requestSerializer))]; [coder encodeObject:self.responseSerializer forKey:NSStringFromSelector(@selector(responseSerializer))]; + [coder encodeObject:self.securityPolicy forKey:NSStringFromSelector(@selector(securityPolicy))]; } #pragma mark - NSCopying @@ -312,7 +319,7 @@ HTTPClient.requestSerializer = [self.requestSerializer copyWithZone:zone]; HTTPClient.responseSerializer = [self.responseSerializer copyWithZone:zone]; - + HTTPClient.securityPolicy = [self.securityPolicy copyWithZone:zone]; return HTTPClient; } diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFNetworkReachabilityManager.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFNetworkReachabilityManager.h old mode 100644 new mode 100755 similarity index 90% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFNetworkReachabilityManager.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFNetworkReachabilityManager.h index 5e610d887f4..e2eb945df04 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFNetworkReachabilityManager.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFNetworkReachabilityManager.h @@ -1,6 +1,5 @@ // AFNetworkReachabilityManager.h -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -8,10 +7,10 @@ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,8 +20,18 @@ // THE SOFTWARE. #import + +#if !TARGET_OS_WATCH #import +#ifndef NS_DESIGNATED_INITIALIZER +#if __has_attribute(objc_designated_initializer) +#define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) +#else +#define NS_DESIGNATED_INITIALIZER +#endif +#endif + typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { AFNetworkReachabilityStatusUnknown = -1, AFNetworkReachabilityStatusNotReachable = 0, @@ -30,13 +39,15 @@ typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { AFNetworkReachabilityStatusReachableViaWiFi = 2, }; +NS_ASSUME_NONNULL_BEGIN + /** `AFNetworkReachabilityManager` monitors the reachability of domains, and addresses for both WWAN and WiFi network interfaces. - + Reachability can be used to determine background information about why a network operation failed, or to trigger a network operation retrying when a connection is established. It should not be used to prevent a user from initiating a network request, as it's possible that an initial request may be required to establish reachability. See Apple's Reachability Sample Code (https://developer.apple.com/library/ios/samplecode/reachability/) - + @warning Instances of `AFNetworkReachabilityManager` must be started with `-startMonitoring` before reachability status can be determined. */ @interface AFNetworkReachabilityManager : NSObject @@ -72,9 +83,9 @@ typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { /** Creates and returns a network reachability manager for the specified domain. - + @param domain The domain used to evaluate network reachability. - + @return An initialized network reachability manager, actively monitoring the specified domain. */ + (instancetype)managerForDomain:(NSString *)domain; @@ -90,12 +101,12 @@ typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { /** Initializes an instance of a network reachability manager from the specified reachability object. - + @param reachability The reachability object to monitor. - + @return An initialized network reachability manager, actively monitoring the specified reachability. */ -- (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability; +- (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability NS_DESIGNATED_INITIALIZER; ///-------------------------------------------------- /// @name Starting & Stopping Reachability Monitoring @@ -129,7 +140,7 @@ typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { @param block A block object to be executed when the network availability of the `baseURL` host changes.. This block has no return value and takes a single argument which represents the various reachability states from the device to the `baseURL`. */ -- (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block; +- (void)setReachabilityStatusChangeBlock:(nullable void (^)(AFNetworkReachabilityStatus status))block; @end @@ -180,8 +191,8 @@ typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { @warning In order for network reachability to be monitored, include the `SystemConfiguration` framework in the active target's "Link Binary With Library" build phase, and add `#import ` to the header prefix of the project (`Prefix.pch`). */ -extern NSString * const AFNetworkingReachabilityDidChangeNotification; -extern NSString * const AFNetworkingReachabilityNotificationStatusItem; +FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityDidChangeNotification; +FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityNotificationStatusItem; ///-------------------- /// @name Functions @@ -190,4 +201,7 @@ extern NSString * const AFNetworkingReachabilityNotificationStatusItem; /** Returns a localized string representation of an `AFNetworkReachabilityStatus` value. */ -extern NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status); +FOUNDATION_EXPORT NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status); + +NS_ASSUME_NONNULL_END +#endif diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFNetworkReachabilityManager.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFNetworkReachabilityManager.m old mode 100644 new mode 100755 similarity index 75% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFNetworkReachabilityManager.m rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFNetworkReachabilityManager.m index 1da148282d4..fe67781e3c0 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFNetworkReachabilityManager.m +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFNetworkReachabilityManager.m @@ -1,6 +1,5 @@ // AFNetworkReachabilityManager.m -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -8,10 +7,10 @@ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +20,7 @@ // THE SOFTWARE. #import "AFNetworkReachabilityManager.h" +#if !TARGET_OS_WATCH #import #import @@ -33,12 +33,6 @@ NSString * const AFNetworkingReachabilityNotificationStatusItem = @"AFNetworking typedef void (^AFNetworkReachabilityStatusBlock)(AFNetworkReachabilityStatus status); -typedef NS_ENUM(NSUInteger, AFNetworkReachabilityAssociation) { - AFNetworkReachabilityForAddress = 1, - AFNetworkReachabilityForAddressPair = 2, - AFNetworkReachabilityForName = 3, -}; - NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status) { switch (status) { case AFNetworkReachabilityStatusNotReachable: @@ -76,19 +70,28 @@ static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags(SCNetwork return status; } -static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) { +/** + * Queue a status change notification for the main thread. + * + * This is done to ensure that the notifications are received in the same order + * as they are sent. If notifications are sent directly, it is possible that + * a queued notification (for an earlier status condition) is processed after + * the later update, resulting in the listener being left in the wrong state. + */ +static void AFPostReachabilityStatusChange(SCNetworkReachabilityFlags flags, AFNetworkReachabilityStatusBlock block) { AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags); - AFNetworkReachabilityStatusBlock block = (__bridge AFNetworkReachabilityStatusBlock)info; - if (block) { - block(status); - } - - dispatch_async(dispatch_get_main_queue(), ^{ + if (block) { + block(status); + } NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; - [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:@{ AFNetworkingReachabilityNotificationStatusItem: @(status) }]; + NSDictionary *userInfo = @{ AFNetworkingReachabilityNotificationStatusItem: @(status) }; + [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:userInfo]; }); - +} + +static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) { + AFPostReachabilityStatusChange(flags, (__bridge AFNetworkReachabilityStatusBlock)info); } static const void * AFNetworkReachabilityRetainCallback(const void *info) { @@ -102,8 +105,7 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) { } @interface AFNetworkReachabilityManager () -@property (readwrite, nonatomic, assign) SCNetworkReachabilityRef networkReachability; -@property (readwrite, nonatomic, assign) AFNetworkReachabilityAssociation networkReachabilityAssociation; +@property (readwrite, nonatomic, strong) id networkReachability; @property (readwrite, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus; @property (readwrite, nonatomic, copy) AFNetworkReachabilityStatusBlock networkReachabilityStatusBlock; @end @@ -125,23 +127,24 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) { return _sharedManager; } +#ifndef __clang_analyzer__ + (instancetype)managerForDomain:(NSString *)domain { SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [domain UTF8String]); AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability]; - manager.networkReachabilityAssociation = AFNetworkReachabilityForName; return manager; } +#endif +#ifndef __clang_analyzer__ + (instancetype)managerForAddress:(const void *)address { SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)address); - AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability]; - manager.networkReachabilityAssociation = AFNetworkReachabilityForAddress; return manager; } +#endif - (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability { self = [super init]; @@ -149,19 +152,19 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) { return nil; } - self.networkReachability = reachability; + self.networkReachability = CFBridgingRelease(reachability); self.networkReachabilityStatus = AFNetworkReachabilityStatusUnknown; return self; } +- (instancetype)init NS_UNAVAILABLE +{ + return nil; +} + - (void)dealloc { [self stopMonitoring]; - - if (_networkReachability) { - CFRelease(_networkReachability); - _networkReachability = NULL; - } } #pragma mark - @@ -198,32 +201,17 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) { }; + id networkReachability = self.networkReachability; SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL}; - SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context); - SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); + SCNetworkReachabilitySetCallback((__bridge SCNetworkReachabilityRef)networkReachability, AFNetworkReachabilityCallback, &context); + SCNetworkReachabilityScheduleWithRunLoop((__bridge SCNetworkReachabilityRef)networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); - switch (self.networkReachabilityAssociation) { - case AFNetworkReachabilityForName: - break; - case AFNetworkReachabilityForAddress: - case AFNetworkReachabilityForAddressPair: - default: { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{ - SCNetworkReachabilityFlags flags; - SCNetworkReachabilityGetFlags(self.networkReachability, &flags); - AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags); - dispatch_async(dispatch_get_main_queue(), ^{ - callback(status); - - NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; - [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:@{ AFNetworkingReachabilityNotificationStatusItem: @(status) }]; - - - }); - }); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{ + SCNetworkReachabilityFlags flags; + if (SCNetworkReachabilityGetFlags((__bridge SCNetworkReachabilityRef)networkReachability, &flags)) { + AFPostReachabilityStatusChange(flags, callback); } - break; - } + }); } - (void)stopMonitoring { @@ -231,7 +219,7 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) { return; } - SCNetworkReachabilityUnscheduleFromRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); + SCNetworkReachabilityUnscheduleFromRunLoop((__bridge SCNetworkReachabilityRef)self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); } #pragma mark - @@ -257,3 +245,4 @@ static void AFNetworkReachabilityReleaseCallback(const void *info) { } @end +#endif diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFNetworking.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFNetworking.h old mode 100644 new mode 100755 similarity index 95% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFNetworking.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFNetworking.h index 68273da58e0..6d442bb148e --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFNetworking.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFNetworking.h @@ -29,14 +29,16 @@ #import "AFURLRequestSerialization.h" #import "AFURLResponseSerialization.h" #import "AFSecurityPolicy.h" +#if !TARGET_OS_WATCH #import "AFNetworkReachabilityManager.h" - #import "AFURLConnectionOperation.h" #import "AFHTTPRequestOperation.h" #import "AFHTTPRequestOperationManager.h" +#endif #if ( ( defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090) || \ - ( defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 ) ) + ( defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 ) || \ + TARGET_OS_WATCH ) #import "AFURLSessionManager.h" #import "AFHTTPSessionManager.h" #endif diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFSecurityPolicy.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFSecurityPolicy.h old mode 100644 new mode 100755 similarity index 84% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFSecurityPolicy.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFSecurityPolicy.h index a880d75191f..d968f49d090 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFSecurityPolicy.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFSecurityPolicy.h @@ -1,6 +1,5 @@ -// AFSecurity.h -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// AFSecurityPolicy.h +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -31,10 +30,13 @@ typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { /** `AFSecurityPolicy` evaluates server trust against pinned X.509 certificates and public keys over secure connections. - + Adding pinned SSL certificates to your app helps prevent man-in-the-middle attacks and other vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged to route all communication over an HTTPS connection with SSL pinning configured and enabled. */ -@interface AFSecurityPolicy : NSObject + +NS_ASSUME_NONNULL_BEGIN + +@interface AFSecurityPolicy : NSObject /** The criteria by which server trust should be evaluated against the pinned SSL certificates. Defaults to `AFSSLPinningModeNone`. @@ -42,14 +44,9 @@ typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { @property (readonly, nonatomic, assign) AFSSLPinningMode SSLPinningMode; /** - Whether to evaluate an entire SSL certificate chain, or just the leaf certificate. Defaults to `YES`. + The certificates used to evaluate server trust according to the SSL pinning mode. By default, this property is set to any (`.cer`) certificates included in the app bundle. Note that if you create an array with duplicate certificates, the duplicate certificates will be removed. Note that if pinning is enabled, `evaluateServerTrust:forDomain:` will return true if any pinned certificate matches. */ -@property (nonatomic, assign) BOOL validatesCertificateChain; - -/** - The certificates used to evaluate server trust according to the SSL pinning mode. By default, this property is set to any (`.cer`) certificates included in the app bundle. - */ -@property (nonatomic, strong) NSArray *pinnedCertificates; +@property (nonatomic, strong, nullable) NSArray *pinnedCertificates; /** Whether or not to trust servers with an invalid or expired SSL certificates. Defaults to `NO`. @@ -57,7 +54,7 @@ typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { @property (nonatomic, assign) BOOL allowInvalidCertificates; /** - Whether or not to validate the domain name in the certificate's CN field. Defaults to `YES` for `AFSSLPinningModePublicKey` or `AFSSLPinningModeCertificate`, otherwise `NO`. + Whether or not to validate the domain name in the certificate's CN field. Defaults to `YES`. */ @property (nonatomic, assign) BOOL validatesDomainName; @@ -66,8 +63,8 @@ typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { ///----------------------------------------- /** - Returns the shared default security policy, which does not allow invalid certificates, does not validate domain name, and does not validate against pinned certificates or public keys. - + Returns the shared default security policy, which does not allow invalid certificates, validates domain name, and does not validate against pinned certificates or public keys. + @return The default security policy. */ + (instancetype)defaultPolicy; @@ -80,7 +77,7 @@ typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { Creates and returns a security policy with the specified pinning mode. @param pinningMode The SSL pinning mode. - + @return A new security policy. */ + (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode; @@ -97,26 +94,28 @@ typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { @param serverTrust The X.509 certificate trust of the server. @return Whether or not to trust the server. - + @warning This method has been deprecated in favor of `-evaluateServerTrust:forDomain:`. */ - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust DEPRECATED_ATTRIBUTE; /** - Whether or not the specified server trust should be accepted, based on the security policy. - + Whether or not the specified server trust should be accepted, based on the security policy. + This method should be used when responding to an authentication challenge from a server. - + @param serverTrust The X.509 certificate trust of the server. @param domain The domain of serverTrust. If `nil`, the domain will not be validated. - + @return Whether or not to trust the server. */ - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust - forDomain:(NSString *)domain; + forDomain:(nullable NSString *)domain; @end +NS_ASSUME_NONNULL_END + ///---------------- /// @name Constants ///---------------- diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFSecurityPolicy.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFSecurityPolicy.m old mode 100644 new mode 100755 similarity index 69% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFSecurityPolicy.m rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFSecurityPolicy.m index 1f97f914f37..2624775605d --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFSecurityPolicy.m +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFSecurityPolicy.m @@ -1,6 +1,5 @@ -// AFSecurity.m -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// AFSecurityPolicy.m +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -22,31 +21,13 @@ #import "AFSecurityPolicy.h" -// Equivalent of macro in , without causing compiler warning: -// "'DebugAssert' is deprecated: first deprecated in OS X 10.8" -#ifndef AF_Require - #define AF_Require(assertion, exceptionLabel) \ - do { \ - if (__builtin_expect(!(assertion), 0)) { \ - goto exceptionLabel; \ - } \ - } while (0) -#endif +#import -#ifndef AF_Require_noErr - #define AF_Require_noErr(errorCode, exceptionLabel) \ - do { \ - if (__builtin_expect(0 != (errorCode), 0)) { \ - goto exceptionLabel; \ - } \ - } while (0) -#endif - -#if !defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#if !TARGET_OS_IOS && !TARGET_OS_WATCH static NSData * AFSecKeyGetData(SecKeyRef key) { CFDataRef data = NULL; - AF_Require_noErr(SecItemExport(key, kSecFormatUnknown, kSecItemPemArmour, NULL, &data), _out); + __Require_noErr_Quiet(SecItemExport(key, kSecFormatUnknown, kSecItemPemArmour, NULL, &data), _out); return (__bridge_transfer NSData *)data; @@ -60,7 +41,7 @@ _out: #endif static BOOL AFSecKeyIsEqualToKey(SecKeyRef key1, SecKeyRef key2) { -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#if TARGET_OS_IOS || TARGET_OS_WATCH return [(__bridge id)key1 isEqual:(__bridge id)key2]; #else return [AFSecKeyGetData(key1) isEqual:AFSecKeyGetData(key2)]; @@ -77,14 +58,14 @@ static id AFPublicKeyForCertificate(NSData *certificate) { SecTrustResultType result; allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificate); - AF_Require(allowedCertificate != NULL, _out); + __Require_Quiet(allowedCertificate != NULL, _out); allowedCertificates[0] = allowedCertificate; tempCertificates = CFArrayCreate(NULL, (const void **)allowedCertificates, 1, NULL); policy = SecPolicyCreateBasicX509(); - AF_Require_noErr(SecTrustCreateWithCertificates(tempCertificates, policy, &allowedTrust), _out); - AF_Require_noErr(SecTrustEvaluate(allowedTrust, &result), _out); + __Require_noErr_Quiet(SecTrustCreateWithCertificates(tempCertificates, policy, &allowedTrust), _out); + __Require_noErr_Quiet(SecTrustEvaluate(allowedTrust, &result), _out); allowedPublicKey = (__bridge_transfer id)SecTrustCopyPublicKey(allowedTrust); @@ -111,7 +92,7 @@ _out: static BOOL AFServerTrustIsValid(SecTrustRef serverTrust) { BOOL isValid = NO; SecTrustResultType result; - AF_Require_noErr(SecTrustEvaluate(serverTrust, &result), _out); + __Require_noErr_Quiet(SecTrustEvaluate(serverTrust, &result), _out); isValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed); @@ -142,10 +123,10 @@ static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) { CFArrayRef certificates = CFArrayCreate(NULL, (const void **)someCertificates, 1, NULL); SecTrustRef trust; - AF_Require_noErr(SecTrustCreateWithCertificates(certificates, policy, &trust), _out); - + __Require_noErr_Quiet(SecTrustCreateWithCertificates(certificates, policy, &trust), _out); + SecTrustResultType result; - AF_Require_noErr(SecTrustEvaluate(trust, &result), _out); + __Require_noErr_Quiet(SecTrustEvaluate(trust, &result), _out); [trustChain addObject:(__bridge_transfer id)SecTrustCopyPublicKey(trust)]; @@ -215,29 +196,13 @@ static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) { return nil; } - self.validatesCertificateChain = YES; + self.validatesDomainName = YES; return self; } -#pragma mark - - -- (void)setSSLPinningMode:(AFSSLPinningMode)SSLPinningMode { - _SSLPinningMode = SSLPinningMode; - - switch (self.SSLPinningMode) { - case AFSSLPinningModePublicKey: - case AFSSLPinningModeCertificate: - self.validatesDomainName = YES; - break; - default: - self.validatesDomainName = NO; - break; - } -} - - (void)setPinnedCertificates:(NSArray *)pinnedCertificates { - _pinnedCertificates = pinnedCertificates; + _pinnedCertificates = [[NSOrderedSet orderedSetWithArray:pinnedCertificates] array]; if (self.pinnedCertificates) { NSMutableArray *mutablePinnedPublicKeys = [NSMutableArray arrayWithCapacity:[self.pinnedCertificates count]]; @@ -263,6 +228,19 @@ static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) { - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain { + if (domain && self.allowInvalidCertificates && self.validatesDomainName && (self.SSLPinningMode == AFSSLPinningModeNone || [self.pinnedCertificates count] == 0)) { + // https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/OverridingSSLChainValidationCorrectly.html + // According to the docs, you should only trust your provided certs for evaluation. + // Pinned certificates are added to the trust. Without pinned certificates, + // there is nothing to evaluate against. + // + // From Apple Docs: + // "Do not implicitly trust self-signed certificates as anchors (kSecTrustOptionImplicitAnchors). + // Instead, add your own (self-signed) CA certificate to the list of trusted anchors." + NSLog(@"In order to validate a domain name for self signed certificates, you MUST use pinning."); + return NO; + } + NSMutableArray *policies = [NSMutableArray array]; if (self.validatesDomainName) { [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)]; @@ -272,14 +250,17 @@ static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) { SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies); - if (!AFServerTrustIsValid(serverTrust) && !self.allowInvalidCertificates) { + if (self.SSLPinningMode == AFSSLPinningModeNone) { + return self.allowInvalidCertificates || AFServerTrustIsValid(serverTrust); + } else if (!AFServerTrustIsValid(serverTrust) && !self.allowInvalidCertificates) { return NO; } NSArray *serverCertificates = AFCertificateTrustChainForServerTrust(serverTrust); switch (self.SSLPinningMode) { case AFSSLPinningModeNone: - return YES; + default: + return NO; case AFSSLPinningModeCertificate: { NSMutableArray *pinnedCertificates = [NSMutableArray array]; for (NSData *certificateData in self.pinnedCertificates) { @@ -291,25 +272,17 @@ static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) { return NO; } - if (!self.validatesCertificateChain) { - return YES; - } - NSUInteger trustedCertificateCount = 0; for (NSData *trustChainCertificate in serverCertificates) { if ([self.pinnedCertificates containsObject:trustChainCertificate]) { trustedCertificateCount++; } } - - return trustedCertificateCount == [serverCertificates count]; + return trustedCertificateCount > 0; } case AFSSLPinningModePublicKey: { NSUInteger trustedPublicKeyCount = 0; NSArray *publicKeys = AFPublicKeyTrustChainForServerTrust(serverTrust); - if (!self.validatesCertificateChain && [publicKeys count] > 0) { - publicKeys = @[[publicKeys firstObject]]; - } for (id trustChainPublicKey in publicKeys) { for (id pinnedPublicKey in self.pinnedPublicKeys) { @@ -318,8 +291,7 @@ static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) { } } } - - return trustedPublicKeyCount > 0 && ((self.validatesCertificateChain && trustedPublicKeyCount == [serverCertificates count]) || (!self.validatesCertificateChain && trustedPublicKeyCount >= 1)); + return trustedPublicKeyCount > 0; } } @@ -332,4 +304,44 @@ static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) { return [NSSet setWithObject:@"pinnedCertificates"]; } +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)decoder { + + self = [self init]; + if (!self) { + return nil; + } + + self.SSLPinningMode = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(SSLPinningMode))] unsignedIntegerValue]; + self.allowInvalidCertificates = [decoder decodeBoolForKey:NSStringFromSelector(@selector(allowInvalidCertificates))]; + self.validatesDomainName = [decoder decodeBoolForKey:NSStringFromSelector(@selector(validatesDomainName))]; + self.pinnedCertificates = [decoder decodeObjectOfClass:[NSArray class] forKey:NSStringFromSelector(@selector(pinnedCertificates))]; + + return self; +} + +- (void)encodeWithCoder:(NSCoder *)coder { + [coder encodeObject:[NSNumber numberWithUnsignedInteger:self.SSLPinningMode] forKey:NSStringFromSelector(@selector(SSLPinningMode))]; + [coder encodeBool:self.allowInvalidCertificates forKey:NSStringFromSelector(@selector(allowInvalidCertificates))]; + [coder encodeBool:self.validatesDomainName forKey:NSStringFromSelector(@selector(validatesDomainName))]; + [coder encodeObject:self.pinnedCertificates forKey:NSStringFromSelector(@selector(pinnedCertificates))]; +} + +#pragma mark - NSCopying + +- (instancetype)copyWithZone:(NSZone *)zone { + AFSecurityPolicy *securityPolicy = [[[self class] allocWithZone:zone] init]; + securityPolicy.SSLPinningMode = self.SSLPinningMode; + securityPolicy.allowInvalidCertificates = self.allowInvalidCertificates; + securityPolicy.validatesDomainName = self.validatesDomainName; + securityPolicy.pinnedCertificates = [self.pinnedCertificates copyWithZone:zone]; + + return securityPolicy; +} + @end diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLConnectionOperation.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLConnectionOperation.h old mode 100644 new mode 100755 similarity index 84% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLConnectionOperation.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLConnectionOperation.h index 85435564c3e..c21119e2ba3 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLConnectionOperation.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLConnectionOperation.h @@ -1,6 +1,5 @@ // AFURLConnectionOperation.h -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -27,6 +26,14 @@ #import "AFURLResponseSerialization.h" #import "AFSecurityPolicy.h" +#ifndef NS_DESIGNATED_INITIALIZER +#if __has_attribute(objc_designated_initializer) +#define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) +#else +#define NS_DESIGNATED_INITIALIZER +#endif +#endif + /** `AFURLConnectionOperation` is a subclass of `NSOperation` that implements `NSURLConnection` delegate methods. @@ -47,7 +54,7 @@ - `connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:` - `connection:willCacheResponse:` - `connectionShouldUseCredentialStorage:` - - `connection:needNewBodyStream:` + - `connection:needNewBodyStream:` - `connection:willSendRequestForAuthenticationChallenge:` If any of these methods are overridden in a subclass, they _must_ call the `super` implementation first. @@ -57,18 +64,14 @@ The built-in `completionBlock` provided by `NSOperation` allows for custom behavior to be executed after the request finishes. It is a common pattern for class constructors in subclasses to take callback block parameters, and execute them conditionally in the body of its `completionBlock`. Make sure to handle cancelled operations appropriately when setting a `completionBlock` (i.e. returning early before parsing response data). See the implementation of any of the `AFHTTPRequestOperation` subclasses for an example of this. Subclasses are strongly discouraged from overriding `setCompletionBlock:`, as `AFURLConnectionOperation`'s implementation includes a workaround to mitigate retain cycles, and what Apple rather ominously refers to as ["The Deallocation Problem"](http://developer.apple.com/library/ios/#technotes/tn2109/). - + ## SSL Pinning - + Relying on the CA trust model to validate SSL certificates exposes your app to security vulnerabilities, such as man-in-the-middle attacks. For applications that connect to known servers, SSL certificate pinning provides an increased level of security, by checking server certificate validity against those specified in the app bundle. - + SSL with certificate pinning is strongly recommended for any application that transmits sensitive information to an external webservice. Connections will be validated on all matching certificates with a `.cer` extension in the bundle root. - - ## App Extensions - - When using AFNetworking in an App Extension, `#define AF_APP_EXTENSIONS` to avoid using unavailable APIs. ## NSCoding & NSCopying Conformance @@ -86,6 +89,8 @@ - Operation copies do not include `completionBlock`, as it often strongly captures a reference to `self`, which would otherwise have the unintuitive side-effect of pointing to the _original_ operation when copied. */ +NS_ASSUME_NONNULL_BEGIN + @interface AFURLConnectionOperation : NSOperation ///------------------------------- @@ -109,12 +114,12 @@ /** The last response received by the operation's connection. */ -@property (readonly, nonatomic, strong) NSURLResponse *response; +@property (readonly, nonatomic, strong, nullable) NSURLResponse *response; /** The error, if any, that occurred in the lifecycle of the request. */ -@property (readonly, nonatomic, strong) NSError *error; +@property (readonly, nonatomic, strong, nullable) NSError *error; ///---------------------------- /// @name Getting Response Data @@ -123,12 +128,12 @@ /** The data received during the request. */ -@property (readonly, nonatomic, strong) NSData *responseData; +@property (readonly, nonatomic, strong, nullable) NSData *responseData; /** The string representation of the response data. */ -@property (readonly, nonatomic, copy) NSString *responseString; +@property (readonly, nonatomic, copy, nullable) NSString *responseString; /** The string encoding of the response. @@ -153,7 +158,7 @@ This will be overridden by any shared credentials that exist for the username or password of the request URL, if present. */ -@property (nonatomic, strong) NSURLCredential *credential; +@property (nonatomic, strong, nullable) NSURLCredential *credential; ///------------------------------- /// @name Managing Security Policy @@ -180,7 +185,7 @@ By default, data is accumulated into a buffer that is stored into `responseData` upon completion of the request, with the intermediary `outputStream` property set to `nil`. When `outputStream` is set, the data will not be accumulated into an internal buffer, and as a result, the `responseData` property of the completed request will be `nil`. The output stream will be scheduled in the network thread runloop upon being set. */ -@property (nonatomic, strong) NSOutputStream *outputStream; +@property (nonatomic, strong, nullable) NSOutputStream *outputStream; ///--------------------------------- /// @name Managing Callback Queues @@ -189,12 +194,20 @@ /** The dispatch queue for `completionBlock`. If `NULL` (default), the main queue is used. */ -@property (nonatomic, strong) dispatch_queue_t completionQueue; +#if OS_OBJECT_USE_OBJC +@property (nonatomic, strong, nullable) dispatch_queue_t completionQueue; +#else +@property (nonatomic, assign, nullable) dispatch_queue_t completionQueue; +#endif /** The dispatch group for `completionBlock`. If `NULL` (default), a private dispatch group is used. */ -@property (nonatomic, strong) dispatch_group_t completionGroup; +#if OS_OBJECT_USE_OBJC +@property (nonatomic, strong, nullable) dispatch_group_t completionGroup; +#else +@property (nonatomic, assign, nullable) dispatch_group_t completionGroup; +#endif ///--------------------------------------------- /// @name Managing Request Operation Information @@ -204,6 +217,7 @@ The user info dictionary for the receiver. */ @property (nonatomic, strong) NSDictionary *userInfo; +// FIXME: It doesn't seem that this userInfo is used anywhere in the implementation. ///------------------------------------------------------ /// @name Initializing an AFURLConnectionOperation Object @@ -211,12 +225,12 @@ /** Initializes and returns a newly allocated operation object with a url connection configured with the specified url request. - + This is the designated initializer. - + @param urlRequest The request object to be used by the operation connection. */ -- (instancetype)initWithRequest:(NSURLRequest *)urlRequest; +- (instancetype)initWithRequest:(NSURLRequest *)urlRequest NS_DESIGNATED_INITIALIZER; ///---------------------------------- /// @name Pausing / Resuming Requests @@ -252,8 +266,8 @@ @param handler A handler to be called shortly before the application’s remaining background time reaches 0. The handler is wrapped in a block that cancels the operation, and cleans up and marks the end of execution, unlike the `handler` parameter in `UIApplication -beginBackgroundTaskWithExpirationHandler:`, which expects this to be done in the handler itself. The handler is called synchronously on the main thread, thus blocking the application’s suspension momentarily while the application is notified. */ -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && !defined(AF_APP_EXTENSIONS) -- (void)setShouldExecuteAsBackgroundTaskWithExpirationHandler:(void (^)(void))handler; +#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +- (void)setShouldExecuteAsBackgroundTaskWithExpirationHandler:(nullable void (^)(void))handler NS_EXTENSION_UNAVAILABLE_IOS("Not available in app extensions."); #endif ///--------------------------------- @@ -265,14 +279,14 @@ @param block A block object to be called when an undetermined number of bytes have been uploaded to the server. This block has no return value and takes three arguments: the number of bytes written since the last time the upload progress block was called, the total bytes written, and the total bytes expected to be written during the request, as initially determined by the length of the HTTP body. This block may be called multiple times, and will execute on the main thread. */ -- (void)setUploadProgressBlock:(void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))block; +- (void)setUploadProgressBlock:(nullable void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))block; /** Sets a callback to be called when an undetermined number of bytes have been downloaded from the server. @param block A block object to be called when an undetermined number of bytes have been downloaded from the server. This block has no return value and takes three arguments: the number of bytes read since the last time the download progress block was called, the total bytes read, and the total bytes expected to be read during the request, as initially determined by the expected content size of the `NSHTTPURLResponse` object. This block may be called multiple times, and will execute on the main thread. */ -- (void)setDownloadProgressBlock:(void (^)(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead))block; +- (void)setDownloadProgressBlock:(nullable void (^)(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead))block; ///------------------------------------------------- /// @name Setting NSURLConnection Delegate Callbacks @@ -280,19 +294,19 @@ /** Sets a block to be executed when the connection will authenticate a challenge in order to download its request, as handled by the `NSURLConnectionDelegate` method `connection:willSendRequestForAuthenticationChallenge:`. - + @param block A block object to be executed when the connection will authenticate a challenge in order to download its request. The block has no return type and takes two arguments: the URL connection object, and the challenge that must be authenticated. This block must invoke one of the challenge-responder methods (NSURLAuthenticationChallengeSender protocol). - + If `allowsInvalidSSLCertificate` is set to YES, `connection:willSendRequestForAuthenticationChallenge:` will attempt to have the challenge sender use credentials with invalid SSL certificates. */ -- (void)setWillSendRequestForAuthenticationChallengeBlock:(void (^)(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge))block; +- (void)setWillSendRequestForAuthenticationChallengeBlock:(nullable void (^)(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge))block; /** Sets a block to be executed when the server redirects the request from one URL to another URL, or when the request URL changed by the `NSURLProtocol` subclass handling the request in order to standardize its format, as handled by the `NSURLConnectionDataDelegate` method `connection:willSendRequest:redirectResponse:`. @param block A block object to be executed when the request URL was changed. The block returns an `NSURLRequest` object, the URL request to redirect, and takes three arguments: the URL connection object, the the proposed redirected request, and the URL response that caused the redirect. */ -- (void)setRedirectResponseBlock:(NSURLRequest * (^)(NSURLConnection *connection, NSURLRequest *request, NSURLResponse *redirectResponse))block; +- (void)setRedirectResponseBlock:(nullable NSURLRequest * (^)(NSURLConnection *connection, NSURLRequest *request, NSURLResponse *redirectResponse))block; /** @@ -300,16 +314,16 @@ @param block A block object to be executed to determine what response a connection will cache, if any. The block returns an `NSCachedURLResponse` object, the cached response to store in memory or `nil` to prevent the response from being cached, and takes two arguments: the URL connection object, and the cached response provided for the request. */ -- (void)setCacheResponseBlock:(NSCachedURLResponse * (^)(NSURLConnection *connection, NSCachedURLResponse *cachedResponse))block; +- (void)setCacheResponseBlock:(nullable NSCachedURLResponse * (^)(NSURLConnection *connection, NSCachedURLResponse *cachedResponse))block; /// /** */ -+ (NSArray *)batchOfRequestOperations:(NSArray *)operations - progressBlock:(void (^)(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations))progressBlock - completionBlock:(void (^)(NSArray *operations))completionBlock; ++ (NSArray *)batchOfRequestOperations:(nullable NSArray *)operations + progressBlock:(nullable void (^)(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations))progressBlock + completionBlock:(nullable void (^)(NSArray *operations))completionBlock; @end @@ -320,9 +334,11 @@ /** Posted when an operation begins executing. */ -extern NSString * const AFNetworkingOperationDidStartNotification; +FOUNDATION_EXPORT NSString * const AFNetworkingOperationDidStartNotification; /** Posted when an operation finishes. */ -extern NSString * const AFNetworkingOperationDidFinishNotification; +FOUNDATION_EXPORT NSString * const AFNetworkingOperationDidFinishNotification; + +NS_ASSUME_NONNULL_END diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLConnectionOperation.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLConnectionOperation.m old mode 100644 new mode 100755 similarity index 93% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLConnectionOperation.m rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLConnectionOperation.m index cfe609a2de2..2126ca6f067 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLConnectionOperation.m +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLConnectionOperation.m @@ -1,6 +1,5 @@ // AFURLConnectionOperation.m -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -38,12 +37,6 @@ typedef NS_ENUM(NSInteger, AFOperationState) { AFOperationFinishedState = 3, }; -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && !defined(AF_APP_EXTENSIONS) -typedef UIBackgroundTaskIdentifier AFBackgroundTaskIdentifier; -#else -typedef id AFBackgroundTaskIdentifier; -#endif - static dispatch_group_t url_request_operation_completion_group() { static dispatch_group_t af_url_request_operation_completion_group; static dispatch_once_t onceToken; @@ -73,6 +66,7 @@ typedef void (^AFURLConnectionOperationProgressBlock)(NSUInteger bytes, long lon typedef void (^AFURLConnectionOperationAuthenticationChallengeBlock)(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge); typedef NSCachedURLResponse * (^AFURLConnectionOperationCacheResponseBlock)(NSURLConnection *connection, NSCachedURLResponse *cachedResponse); typedef NSURLRequest * (^AFURLConnectionOperationRedirectResponseBlock)(NSURLConnection *connection, NSURLRequest *request, NSURLResponse *redirectResponse); +typedef void (^AFURLConnectionOperationBackgroundTaskCleanupBlock)(); static inline NSString * AFKeyPathFromOperationState(AFOperationState state) { switch (state) { @@ -145,7 +139,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat @property (readwrite, nonatomic, copy) NSString *responseString; @property (readwrite, nonatomic, assign) NSStringEncoding responseStringEncoding; @property (readwrite, nonatomic, assign) long long totalBytesRead; -@property (readwrite, nonatomic, assign) AFBackgroundTaskIdentifier backgroundTaskIdentifier; +@property (readwrite, nonatomic, copy) AFURLConnectionOperationBackgroundTaskCleanupBlock backgroundTaskCleanup; @property (readwrite, nonatomic, copy) AFURLConnectionOperationProgressBlock uploadProgress; @property (readwrite, nonatomic, copy) AFURLConnectionOperationProgressBlock downloadProgress; @property (readwrite, nonatomic, copy) AFURLConnectionOperationAuthenticationChallengeBlock authenticationChallenge; @@ -177,7 +171,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat _networkRequestThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil]; [_networkRequestThread start]; }); - + return _networkRequestThread; } @@ -193,11 +187,11 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat self.lock = [[NSRecursiveLock alloc] init]; self.lock.name = kAFNetworkingLockName; - + self.runLoopModes = [NSSet setWithObject:NSRunLoopCommonModes]; - + self.request = urlRequest; - + self.shouldUseCredentialStorage = YES; self.securityPolicy = [AFSecurityPolicy defaultPolicy]; @@ -205,18 +199,20 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat return self; } +- (instancetype)init NS_UNAVAILABLE +{ + return nil; +} + - (void)dealloc { if (_outputStream) { [_outputStream close]; _outputStream = nil; } -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && !defined(AF_APP_EXTENSIONS) - if (_backgroundTaskIdentifier) { - [[UIApplication sharedApplication] endBackgroundTask:_backgroundTaskIdentifier]; - _backgroundTaskIdentifier = UIBackgroundTaskInvalid; + if (_backgroundTaskCleanup) { + _backgroundTaskCleanup(); } -#endif } #pragma mark - @@ -289,24 +285,31 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat [self.lock unlock]; } -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && !defined(AF_APP_EXTENSIONS) +#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) - (void)setShouldExecuteAsBackgroundTaskWithExpirationHandler:(void (^)(void))handler { [self.lock lock]; - if (!self.backgroundTaskIdentifier) { + if (!self.backgroundTaskCleanup) { UIApplication *application = [UIApplication sharedApplication]; + UIBackgroundTaskIdentifier __block backgroundTaskIdentifier = UIBackgroundTaskInvalid; __weak __typeof(self)weakSelf = self; - self.backgroundTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:^{ + + self.backgroundTaskCleanup = ^(){ + if (backgroundTaskIdentifier != UIBackgroundTaskInvalid) { + [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskIdentifier]; + backgroundTaskIdentifier = UIBackgroundTaskInvalid; + } + }; + + backgroundTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:^{ __strong __typeof(weakSelf)strongSelf = weakSelf; - + if (handler) { handler(); } - + if (strongSelf) { [strongSelf cancel]; - - [application endBackgroundTask:strongSelf.backgroundTaskIdentifier]; - strongSelf.backgroundTaskIdentifier = UIBackgroundTaskInvalid; + strongSelf.backgroundTaskCleanup(); } }]; } @@ -320,11 +323,11 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat if (!AFStateTransitionIsValid(self.state, state, [self isCancelled])) { return; } - + [self.lock lock]; NSString *oldStateKey = AFKeyPathFromOperationState(self.state); NSString *newStateKey = AFKeyPathFromOperationState(state); - + [self willChangeValueForKey:newStateKey]; [self willChangeValueForKey:oldStateKey]; _state = state; @@ -337,17 +340,17 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat if ([self isPaused] || [self isFinished] || [self isCancelled]) { return; } - + [self.lock lock]; if ([self isExecuting]) { [self performSelector:@selector(operationDidPause) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]]; - + dispatch_async(dispatch_get_main_queue(), ^{ NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter postNotificationName:AFNetworkingOperationDidFinishNotification object:self]; }); } - + self.state = AFOperationPausedState; [self.lock unlock]; } @@ -366,10 +369,10 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat if (![self isPaused]) { return; } - + [self.lock lock]; self.state = AFOperationReadyState; - + [self start]; [self.lock unlock]; } @@ -447,7 +450,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat [self performSelector:@selector(cancelConnection) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]]; } else if ([self isReady]) { self.state = AFOperationExecutingState; - + [self performSelector:@selector(operationDidStart) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]]; } [self.lock unlock]; @@ -457,18 +460,18 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat [self.lock lock]; if (![self isCancelled]) { self.connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO]; - + NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; for (NSString *runLoopMode in self.runLoopModes) { [self.connection scheduleInRunLoop:runLoop forMode:runLoopMode]; [self.outputStream scheduleInRunLoop:runLoop forMode:runLoopMode]; } - + [self.outputStream open]; [self.connection start]; } [self.lock unlock]; - + dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidStartNotification object:self]; }); @@ -499,7 +502,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat - (void)cancelConnection { NSDictionary *userInfo = nil; if ([self.request URL]) { - userInfo = [NSDictionary dictionaryWithObject:[self.request URL] forKey:NSURLErrorFailingURLErrorKey]; + userInfo = @{NSURLErrorFailingURLErrorKey : [self.request URL]}; } NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled userInfo:userInfo]; @@ -508,7 +511,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat [self.connection cancel]; [self performSelector:@selector(connection:didFailWithError:) withObject:self.connection withObject:error]; } else { - // Accomodate race condition where `self.connection` has not yet been set before cancellation + // Accommodate race condition where `self.connection` has not yet been set before cancellation self.error = error; [self finish]; } @@ -661,16 +664,16 @@ didReceiveResponse:(NSURLResponse *)response if (numberOfBytesWritten == -1) { break; } - + totalNumberOfBytesWritten += numberOfBytesWritten; } break; - } - - if (self.outputStream.streamError) { + } else { [self.connection cancel]; - [self performSelector:@selector(connection:didFailWithError:) withObject:self.connection withObject:self.outputStream.streamError]; + if (self.outputStream.streamError) { + [self performSelector:@selector(connection:didFailWithError:) withObject:self.connection withObject:self.outputStream.streamError]; + } return; } } @@ -721,7 +724,7 @@ didReceiveResponse:(NSURLResponse *)response if ([self isCancelled]) { return nil; } - + return cachedResponse; } } @@ -734,13 +737,13 @@ didReceiveResponse:(NSURLResponse *)response - (id)initWithCoder:(NSCoder *)decoder { NSURLRequest *request = [decoder decodeObjectOfClass:[NSURLRequest class] forKey:NSStringFromSelector(@selector(request))]; - + self = [self initWithRequest:request]; if (!self) { return nil; } - self.state = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(state))] integerValue]; + self.state = (AFOperationState)[[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(state))] integerValue]; self.response = [decoder decodeObjectOfClass:[NSHTTPURLResponse class] forKey:NSStringFromSelector(@selector(response))]; self.error = [decoder decodeObjectOfClass:[NSError class] forKey:NSStringFromSelector(@selector(error))]; self.responseData = [decoder decodeObjectOfClass:[NSData class] forKey:NSStringFromSelector(@selector(responseData))]; @@ -751,9 +754,9 @@ didReceiveResponse:(NSURLResponse *)response - (void)encodeWithCoder:(NSCoder *)coder { [self pause]; - + [coder encodeObject:self.request forKey:NSStringFromSelector(@selector(request))]; - + switch (self.state) { case AFOperationExecutingState: case AFOperationPausedState: @@ -763,7 +766,7 @@ didReceiveResponse:(NSURLResponse *)response [coder encodeInteger:self.state forKey:NSStringFromSelector(@selector(state))]; break; } - + [coder encodeObject:self.response forKey:NSStringFromSelector(@selector(response))]; [coder encodeObject:self.error forKey:NSStringFromSelector(@selector(error))]; [coder encodeObject:self.responseData forKey:NSStringFromSelector(@selector(responseData))]; @@ -774,7 +777,7 @@ didReceiveResponse:(NSURLResponse *)response - (id)copyWithZone:(NSZone *)zone { AFURLConnectionOperation *operation = [(AFURLConnectionOperation *)[[self class] allocWithZone:zone] initWithRequest:self.request]; - + operation.uploadProgress = self.uploadProgress; operation.downloadProgress = self.downloadProgress; operation.authenticationChallenge = self.authenticationChallenge; @@ -782,7 +785,7 @@ didReceiveResponse:(NSURLResponse *)response operation.redirectResponse = self.redirectResponse; operation.completionQueue = self.completionQueue; operation.completionGroup = self.completionGroup; - + return operation; } diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLRequestSerialization.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLRequestSerialization.h old mode 100644 new mode 100755 similarity index 89% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLRequestSerialization.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLRequestSerialization.h index aed4549815f..15ced1dd0cd --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLRequestSerialization.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLRequestSerialization.h @@ -1,6 +1,5 @@ -// AFSerialization.h -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// AFURLRequestSerialization.h +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -8,10 +7,10 @@ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,10 +20,14 @@ // THE SOFTWARE. #import -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#if TARGET_OS_IOS #import +#elif TARGET_OS_WATCH +#import #endif +NS_ASSUME_NONNULL_BEGIN + /** The `AFURLRequestSerialization` protocol is adopted by an object that encodes parameters for a specified HTTP requests. Request serializers may encode parameters as query strings, HTTP bodies, setting the appropriate HTTP header fields as necessary. @@ -41,10 +44,13 @@ @return A serialized request. */ -- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request - withParameters:(id)parameters - error:(NSError * __autoreleasing *)error; - +- (nullable NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request + withParameters:(nullable id)parameters + error:(NSError * __nullable __autoreleasing *)error +#ifdef NS_SWIFT_NOTHROW +NS_SWIFT_NOTHROW +#endif +; @end #pragma mark - @@ -72,42 +78,42 @@ typedef NS_ENUM(NSUInteger, AFHTTPRequestQueryStringSerializationStyle) { /** Whether created requests can use the device’s cellular radio (if present). `YES` by default. - + @see NSMutableURLRequest -setAllowsCellularAccess: */ @property (nonatomic, assign) BOOL allowsCellularAccess; /** The cache policy of created requests. `NSURLRequestUseProtocolCachePolicy` by default. - + @see NSMutableURLRequest -setCachePolicy: */ @property (nonatomic, assign) NSURLRequestCachePolicy cachePolicy; /** Whether created requests should use the default cookie handling. `YES` by default. - + @see NSMutableURLRequest -setHTTPShouldHandleCookies: */ @property (nonatomic, assign) BOOL HTTPShouldHandleCookies; /** Whether created requests can continue transmitting data before receiving a response from an earlier transmission. `NO` by default - + @see NSMutableURLRequest -setHTTPShouldUsePipelining: */ @property (nonatomic, assign) BOOL HTTPShouldUsePipelining; /** The network service type for created requests. `NSURLNetworkServiceTypeDefault` by default. - + @see NSMutableURLRequest -setNetworkServiceType: */ @property (nonatomic, assign) NSURLRequestNetworkServiceType networkServiceType; /** The timeout interval, in seconds, for created requests. The default timeout interval is 60 seconds. - + @see NSMutableURLRequest -setTimeoutInterval: */ @property (nonatomic, assign) NSTimeInterval timeoutInterval; @@ -117,7 +123,12 @@ typedef NS_ENUM(NSUInteger, AFHTTPRequestQueryStringSerializationStyle) { ///--------------------------------------- /** - Default HTTP header field values to be applied to serialized requests. + Default HTTP header field values to be applied to serialized requests. By default, these include the following: + + - `Accept-Language` with the contents of `NSLocale +preferredLanguages` + - `User-Agent` with the contents of various bundle identifiers and OS designations + + @discussion To add or remove default request headers, use `setValue:forHTTPHeaderField:`. */ @property (readonly, nonatomic, strong) NSDictionary *HTTPRequestHeaders; @@ -132,17 +143,17 @@ typedef NS_ENUM(NSUInteger, AFHTTPRequestQueryStringSerializationStyle) { @param field The HTTP header to set a default value for @param value The value set as default for the specified header, or `nil` */ -- (void)setValue:(NSString *)value +- (void)setValue:(nullable NSString *)value forHTTPHeaderField:(NSString *)field; /** Returns the value for the HTTP headers set in the request serializer. @param field The HTTP header to retrieve the default value for - + @return The value set as default for the specified header, or `nil` */ -- (NSString *)valueForHTTPHeaderField:(NSString *)field; +- (nullable NSString *)valueForHTTPHeaderField:(NSString *)field; /** Sets the "Authorization" HTTP header set in request objects made by the HTTP client to a basic authentication value with Base64-encoded username and password. This overwrites any existing value for this header. @@ -187,7 +198,7 @@ forHTTPHeaderField:(NSString *)field; @param block A block that defines a process of encoding parameters into a query string. This block returns the query string and takes three arguments: the request, the parameters to encode, and the error that occurred when attempting to encode parameters for the given request. */ -- (void)setQueryStringSerializationWithBlock:(NSString * (^)(NSURLRequest *request, NSDictionary *parameters, NSError * __autoreleasing *error))block; +- (void)setQueryStringSerializationWithBlock:(nullable NSString * (^)(NSURLRequest *request, id parameters, NSError * __autoreleasing *error))block; ///------------------------------- /// @name Creating Request Objects @@ -208,14 +219,14 @@ forHTTPHeaderField:(NSString *)field; @param method The HTTP method for the request, such as `GET`, `POST`, `PUT`, or `DELETE`. This parameter must not be `nil`. @param URLString The URL string used to create the request URL. @param parameters The parameters to be either set as a query string for `GET` requests, or the request HTTP body. - @param error The error that occured while constructing the request. + @param error The error that occurred while constructing the request. @return An `NSMutableURLRequest` object. */ - (NSMutableURLRequest *)requestWithMethod:(NSString *)method URLString:(NSString *)URLString - parameters:(id)parameters - error:(NSError * __autoreleasing *)error; + parameters:(nullable id)parameters + error:(NSError * __nullable __autoreleasing *)error; /** @deprecated This method has been deprecated. Use -multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:error: instead. @@ -234,30 +245,30 @@ forHTTPHeaderField:(NSString *)field; @param URLString The URL string used to create the request URL. @param parameters The parameters to be encoded and set in the request HTTP body. @param block A block that takes a single argument and appends data to the HTTP body. The block argument is an object adopting the `AFMultipartFormData` protocol. - @param error The error that occured while constructing the request. + @param error The error that occurred while constructing the request. @return An `NSMutableURLRequest` object */ - (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method URLString:(NSString *)URLString - parameters:(NSDictionary *)parameters - constructingBodyWithBlock:(void (^)(id formData))block - error:(NSError * __autoreleasing *)error; + parameters:(nullable NSDictionary *)parameters + constructingBodyWithBlock:(nullable void (^)(id formData))block + error:(NSError * __nullable __autoreleasing *)error; /** Creates an `NSMutableURLRequest` by removing the `HTTPBodyStream` from a request, and asynchronously writing its contents into the specified file, invoking the completion handler when finished. - - @param request The multipart form request. + + @param request The multipart form request. The `HTTPBodyStream` property of `request` must not be `nil`. @param fileURL The file URL to write multipart form contents to. @param handler A handler block to execute. - + @discussion There is a bug in `NSURLSessionTask` that causes requests to not send a `Content-Length` header when streaming contents from an HTTP body, which is notably problematic when interacting with the Amazon S3 webservice. As a workaround, this method takes a request constructed with `multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:error:`, or any other request with an `HTTPBodyStream`, writes the contents to the specified file and returns a copy of the original request with the `HTTPBodyStream` property set to `nil`. From here, the file can either be passed to `AFURLSessionManager -uploadTaskWithRequest:fromFile:progress:completionHandler:`, or have its contents read into an `NSData` that's assigned to the `HTTPBody` property of the request. @see https://github.com/AFNetworking/AFNetworking/issues/1398 */ - (NSMutableURLRequest *)requestWithMultipartFormRequest:(NSURLRequest *)request writingStreamContentsToFile:(NSURL *)fileURL - completionHandler:(void (^)(NSError *error))handler; + completionHandler:(nullable void (^)(NSError * __nullable error))handler; @end @@ -281,7 +292,7 @@ forHTTPHeaderField:(NSString *)field; */ - (BOOL)appendPartWithFileURL:(NSURL *)fileURL name:(NSString *)name - error:(NSError * __autoreleasing *)error; + error:(NSError * __nullable __autoreleasing *)error; /** Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the encoded file data and the multipart form boundary. @@ -298,7 +309,7 @@ forHTTPHeaderField:(NSString *)field; name:(NSString *)name fileName:(NSString *)fileName mimeType:(NSString *)mimeType - error:(NSError * __autoreleasing *)error; + error:(NSError * __nullable __autoreleasing *)error; /** Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the data from the input stream and the multipart form boundary. @@ -309,7 +320,7 @@ forHTTPHeaderField:(NSString *)field; @param length The length of the specified input stream in bytes. @param mimeType The MIME type of the specified data. (For example, the MIME type for a JPEG image is image/jpeg.) For a list of valid MIME types, see http://www.iana.org/assignments/media-types/. This parameter must not be `nil`. */ -- (void)appendPartWithInputStream:(NSInputStream *)inputStream +- (void)appendPartWithInputStream:(nullable NSInputStream *)inputStream name:(NSString *)name fileName:(NSString *)fileName length:(int64_t)length @@ -345,7 +356,7 @@ forHTTPHeaderField:(NSString *)field; @param headers The HTTP headers to be appended to the form data. @param body The data to be encoded and appended to the form data. This parameter must not be `nil`. */ -- (void)appendPartWithHeaders:(NSDictionary *)headers +- (void)appendPartWithHeaders:(nullable NSDictionary *)headers body:(NSData *)body; /** @@ -404,7 +415,7 @@ forHTTPHeaderField:(NSString *)field; @param format The property list format. @param writeOptions The property list write options. - + @warning The `writeOptions` property is currently unused. */ + (instancetype)serializerWithFormat:(NSPropertyListFormat)format @@ -430,7 +441,7 @@ forHTTPHeaderField:(NSString *)field; `AFURLRequestSerializationErrorDomain` AFURLRequestSerializer errors. Error codes for `AFURLRequestSerializationErrorDomain` correspond to codes in `NSURLErrorDomain`. */ -extern NSString * const AFURLRequestSerializationErrorDomain; +FOUNDATION_EXPORT NSString * const AFURLRequestSerializationErrorDomain; /** ## User info dictionary keys @@ -444,7 +455,7 @@ extern NSString * const AFURLRequestSerializationErrorDomain; `AFNetworkingOperationFailingURLRequestErrorKey` The corresponding value is an `NSURLRequest` containing the request of the operation associated with an error. This key is only present in the `AFURLRequestSerializationErrorDomain`. */ -extern NSString * const AFNetworkingOperationFailingURLRequestErrorKey; +FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLRequestErrorKey; /** ## Throttling Bandwidth for HTTP Request Input Streams @@ -459,5 +470,7 @@ extern NSString * const AFNetworkingOperationFailingURLRequestErrorKey; `kAFUploadStream3GSuggestedDelay` Duration of delay each time a packet is read. Equal to 0.2 seconds. */ -extern NSUInteger const kAFUploadStream3GSuggestedPacketSize; -extern NSTimeInterval const kAFUploadStream3GSuggestedDelay; +FOUNDATION_EXPORT NSUInteger const kAFUploadStream3GSuggestedPacketSize; +FOUNDATION_EXPORT NSTimeInterval const kAFUploadStream3GSuggestedDelay; + +NS_ASSUME_NONNULL_END diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLRequestSerialization.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLRequestSerialization.m old mode 100644 new mode 100755 similarity index 85% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLRequestSerialization.m rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLRequestSerialization.m index a56e8542e10..7e224541082 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLRequestSerialization.m +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLRequestSerialization.m @@ -1,6 +1,5 @@ -// AFSerialization.h -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// AFURLRequestSerialization.m +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -8,10 +7,10 @@ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -31,7 +30,7 @@ NSString * const AFURLRequestSerializationErrorDomain = @"com.alamofire.error.serialization.request"; NSString * const AFNetworkingOperationFailingURLRequestErrorKey = @"com.alamofire.serialization.request.error.response"; -typedef NSString * (^AFQueryStringSerializationBlock)(NSURLRequest *request, NSDictionary *parameters, NSError *__autoreleasing *error); +typedef NSString * (^AFQueryStringSerializationBlock)(NSURLRequest *request, id parameters, NSError *__autoreleasing *error); static NSString * AFBase64EncodedStringFromString(NSString *string) { NSData *data = [NSData dataWithBytes:[string UTF8String] length:[string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]]; @@ -62,16 +61,51 @@ static NSString * AFBase64EncodedStringFromString(NSString *string) { return [[NSString alloc] initWithData:mutableData encoding:NSASCIIStringEncoding]; } -static NSString * const kAFCharactersToBeEscapedInQueryString = @":/?&=;+!@#$()',*"; +/** + Returns a percent-escaped string following RFC 3986 for a query string key or value. + RFC 3986 states that the following characters are "reserved" characters. + - General Delimiters: ":", "#", "[", "]", "@", "?", "/" + - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "=" -static NSString * AFPercentEscapedQueryStringKeyFromStringWithEncoding(NSString *string, NSStringEncoding encoding) { - static NSString * const kAFCharactersToLeaveUnescapedInQueryStringPairKey = @"[]."; + In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow + query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/" + should be percent-escaped in the query string. + - parameter string: The string to be percent-escaped. + - returns: The percent-escaped string. + */ +static NSString * AFPercentEscapedStringFromString(NSString *string) { + static NSString * const kAFCharactersGeneralDelimitersToEncode = @":#[]@"; // does not include "?" or "/" due to RFC 3986 - Section 3.4 + static NSString * const kAFCharactersSubDelimitersToEncode = @"!$&'()*+,;="; - return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, (__bridge CFStringRef)kAFCharactersToLeaveUnescapedInQueryStringPairKey, (__bridge CFStringRef)kAFCharactersToBeEscapedInQueryString, CFStringConvertNSStringEncodingToEncoding(encoding)); -} + NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy]; + [allowedCharacterSet removeCharactersInString:[kAFCharactersGeneralDelimitersToEncode stringByAppendingString:kAFCharactersSubDelimitersToEncode]]; -static NSString * AFPercentEscapedQueryStringValueFromStringWithEncoding(NSString *string, NSStringEncoding encoding) { - return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, (__bridge CFStringRef)kAFCharactersToBeEscapedInQueryString, CFStringConvertNSStringEncodingToEncoding(encoding)); + // FIXME: https://github.com/AFNetworking/AFNetworking/pull/3028 + // return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; + + static NSUInteger const batchSize = 50; + + NSUInteger index = 0; + NSMutableString *escaped = @"".mutableCopy; + + while (index < string.length) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wgnu" + NSUInteger length = MIN(string.length - index, batchSize); +#pragma GCC diagnostic pop + NSRange range = NSMakeRange(index, length); + + // To avoid breaking up character sequences such as 👴🏻👮🏽 + range = [string rangeOfComposedCharacterSequencesForRange:range]; + + NSString *substring = [string substringWithRange:range]; + NSString *encoded = [substring stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; + [escaped appendString:encoded]; + + index += range.length; + } + + return escaped; } #pragma mark - @@ -82,7 +116,7 @@ static NSString * AFPercentEscapedQueryStringValueFromStringWithEncoding(NSStrin - (id)initWithField:(id)field value:(id)value; -- (NSString *)URLEncodedStringValueWithEncoding:(NSStringEncoding)stringEncoding; +- (NSString *)URLEncodedStringValue; @end @implementation AFQueryStringPair @@ -99,11 +133,11 @@ static NSString * AFPercentEscapedQueryStringValueFromStringWithEncoding(NSStrin return self; } -- (NSString *)URLEncodedStringValueWithEncoding:(NSStringEncoding)stringEncoding { +- (NSString *)URLEncodedStringValue { if (!self.value || [self.value isEqual:[NSNull null]]) { - return AFPercentEscapedQueryStringKeyFromStringWithEncoding([self.field description], stringEncoding); + return AFPercentEscapedStringFromString([self.field description]); } else { - return [NSString stringWithFormat:@"%@=%@", AFPercentEscapedQueryStringKeyFromStringWithEncoding([self.field description], stringEncoding), AFPercentEscapedQueryStringValueFromStringWithEncoding([self.value description], stringEncoding)]; + return [NSString stringWithFormat:@"%@=%@", AFPercentEscapedStringFromString([self.field description]), AFPercentEscapedStringFromString([self.value description])]; } } @@ -111,13 +145,13 @@ static NSString * AFPercentEscapedQueryStringValueFromStringWithEncoding(NSStrin #pragma mark - -extern NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary); -extern NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value); +FOUNDATION_EXPORT NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary); +FOUNDATION_EXPORT NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value); -static NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *parameters, NSStringEncoding stringEncoding) { +static NSString * AFQueryStringFromParameters(NSDictionary *parameters) { NSMutableArray *mutablePairs = [NSMutableArray array]; for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) { - [mutablePairs addObject:[pair URLEncodedStringValueWithEncoding:stringEncoding]]; + [mutablePairs addObject:[pair URLEncodedStringValue]]; } return [mutablePairs componentsJoinedByString:@"&"]; @@ -136,7 +170,7 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) { NSDictionary *dictionary = value; // Sort dictionary keys to ensure consistent ordering in query string, which is important when deserializing potentially ambiguous sequences, such as an array of dictionaries for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[ sortDescriptor ]]) { - id nestedValue = [dictionary objectForKey:nestedKey]; + id nestedValue = dictionary[nestedKey]; if (nestedValue) { [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)]; } @@ -154,7 +188,7 @@ NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) { } else { [mutableQueryStringComponents addObject:[[AFQueryStringPair alloc] initWithField:key value:value]]; } - + return mutableQueryStringComponents; } @@ -216,11 +250,14 @@ static void *AFHTTPRequestSerializerObserverContext = &AFHTTPRequestSerializerOb NSString *userAgent = nil; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wgnu" -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#if TARGET_OS_IOS // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43 - userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleExecutableKey] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleIdentifierKey], [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]]; + userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]]; +#elif TARGET_OS_WATCH + // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43 + userAgent = [NSString stringWithFormat:@"%@/%@ (%@; watchOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[WKInterfaceDevice currentDevice] model], [[WKInterfaceDevice currentDevice] systemVersion], [[WKInterfaceDevice currentDevice] screenScale]]; #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) - userAgent = [NSString stringWithFormat:@"%@/%@ (Mac OS X %@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleExecutableKey] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleIdentifierKey], [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]]; + userAgent = [NSString stringWithFormat:@"%@/%@ (Mac OS X %@)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]]; #endif #pragma clang diagnostic pop if (userAgent) { @@ -256,6 +293,47 @@ static void *AFHTTPRequestSerializerObserverContext = &AFHTTPRequestSerializerOb #pragma mark - +// Workarounds for crashing behavior using Key-Value Observing with XCTest +// See https://github.com/AFNetworking/AFNetworking/issues/2523 + +- (void)setAllowsCellularAccess:(BOOL)allowsCellularAccess { + [self willChangeValueForKey:NSStringFromSelector(@selector(allowsCellularAccess))]; + _allowsCellularAccess = allowsCellularAccess; + [self didChangeValueForKey:NSStringFromSelector(@selector(allowsCellularAccess))]; +} + +- (void)setCachePolicy:(NSURLRequestCachePolicy)cachePolicy { + [self willChangeValueForKey:NSStringFromSelector(@selector(cachePolicy))]; + _cachePolicy = cachePolicy; + [self didChangeValueForKey:NSStringFromSelector(@selector(cachePolicy))]; +} + +- (void)setHTTPShouldHandleCookies:(BOOL)HTTPShouldHandleCookies { + [self willChangeValueForKey:NSStringFromSelector(@selector(HTTPShouldHandleCookies))]; + _HTTPShouldHandleCookies = HTTPShouldHandleCookies; + [self didChangeValueForKey:NSStringFromSelector(@selector(HTTPShouldHandleCookies))]; +} + +- (void)setHTTPShouldUsePipelining:(BOOL)HTTPShouldUsePipelining { + [self willChangeValueForKey:NSStringFromSelector(@selector(HTTPShouldUsePipelining))]; + _HTTPShouldUsePipelining = HTTPShouldUsePipelining; + [self didChangeValueForKey:NSStringFromSelector(@selector(HTTPShouldUsePipelining))]; +} + +- (void)setNetworkServiceType:(NSURLRequestNetworkServiceType)networkServiceType { + [self willChangeValueForKey:NSStringFromSelector(@selector(networkServiceType))]; + _networkServiceType = networkServiceType; + [self didChangeValueForKey:NSStringFromSelector(@selector(networkServiceType))]; +} + +- (void)setTimeoutInterval:(NSTimeInterval)timeoutInterval { + [self willChangeValueForKey:NSStringFromSelector(@selector(timeoutInterval))]; + _timeoutInterval = timeoutInterval; + [self didChangeValueForKey:NSStringFromSelector(@selector(timeoutInterval))]; +} + +#pragma mark - + - (NSDictionary *)HTTPRequestHeaders { return [NSDictionary dictionaryWithDictionary:self.mutableHTTPRequestHeaders]; } @@ -292,7 +370,7 @@ forHTTPHeaderField:(NSString *)field self.queryStringSerialization = nil; } -- (void)setQueryStringSerializationWithBlock:(NSString *(^)(NSURLRequest *, NSDictionary *, NSError *__autoreleasing *))block { +- (void)setQueryStringSerializationWithBlock:(NSString *(^)(NSURLRequest *, id, NSError *__autoreleasing *))block { self.queryStringSerialization = block; } @@ -380,10 +458,7 @@ forHTTPHeaderField:(NSString *)field writingStreamContentsToFile:(NSURL *)fileURL completionHandler:(void (^)(NSError *error))handler { - if (!request.HTTPBodyStream) { - return [request mutableCopy]; - } - + NSParameterAssert(request.HTTPBodyStream); NSParameterAssert([fileURL isFileURL]); NSInputStream *inputStream = request.HTTPBodyStream; @@ -449,8 +524,8 @@ forHTTPHeaderField:(NSString *)field } }]; + NSString *query = nil; if (parameters) { - NSString *query = nil; if (self.queryStringSerialization) { NSError *serializationError; query = self.queryStringSerialization(request, parameters, &serializationError); @@ -465,19 +540,25 @@ forHTTPHeaderField:(NSString *)field } else { switch (self.queryStringSerializationStyle) { case AFHTTPRequestQueryStringDefaultStyle: - query = AFQueryStringFromParametersWithEncoding(parameters, self.stringEncoding); + query = AFQueryStringFromParameters(parameters); break; } } + } - if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) { + if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) { + if (query) { mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? @"&%@" : @"?%@", query]]; - } else { - if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) { - [mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; - } - [mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]]; } + } else { + // #2864: an empty string is a valid x-www-form-urlencoded payload + if (!query) { + query = @""; + } + if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) { + [mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; + } + [mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]]; } return mutableRequest; @@ -485,6 +566,14 @@ forHTTPHeaderField:(NSString *)field #pragma mark - NSKeyValueObserving ++ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key { + if ([AFHTTPRequestSerializerObservedKeyPaths() containsObject:key]) { + return NO; + } + + return [super automaticallyNotifiesObserversForKey:key]; +} + - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(__unused id)object change:(NSDictionary *)change @@ -512,7 +601,7 @@ forHTTPHeaderField:(NSString *)field } self.mutableHTTPRequestHeaders = [[decoder decodeObjectOfClass:[NSDictionary class] forKey:NSStringFromSelector(@selector(mutableHTTPRequestHeaders))] mutableCopy]; - self.queryStringSerializationStyle = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(queryStringSerializationStyle))] unsignedIntegerValue]; + self.queryStringSerializationStyle = (AFHTTPRequestQueryStringSerializationStyle)[[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(queryStringSerializationStyle))] unsignedIntegerValue]; return self; } @@ -529,7 +618,7 @@ forHTTPHeaderField:(NSString *)field serializer.mutableHTTPRequestHeaders = [self.mutableHTTPRequestHeaders mutableCopyWithZone:zone]; serializer.queryStringSerializationStyle = self.queryStringSerializationStyle; serializer.queryStringSerialization = self.queryStringSerialization; - + return serializer; } @@ -674,17 +763,17 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; if (!fileAttributes) { return NO; } - + NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary]; [mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"]; [mutableHeaders setValue:mimeType forKey:@"Content-Type"]; - + AFHTTPBodyPart *bodyPart = [[AFHTTPBodyPart alloc] init]; bodyPart.stringEncoding = self.stringEncoding; bodyPart.headers = mutableHeaders; bodyPart.boundary = self.boundary; bodyPart.body = fileURL; - bodyPart.bodyContentLength = [[fileAttributes objectForKey:NSFileSize] unsignedLongLongValue]; + bodyPart.bodyContentLength = [fileAttributes[NSFileSize] unsignedLongLongValue]; [self.bodyStream appendHTTPBodyPart:bodyPart]; return YES; @@ -827,7 +916,7 @@ NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2; bodyPart.hasFinalBoundary = NO; } - [[self.HTTPBodyParts objectAtIndex:0] setHasInitialBoundary:YES]; + [[self.HTTPBodyParts firstObject] setHasInitialBoundary:YES]; [[self.HTTPBodyParts lastObject] setHasFinalBoundary:YES]; } } @@ -1167,13 +1256,13 @@ typedef enum { - (id)copyWithZone:(NSZone *)zone { AFHTTPBodyPart *bodyPart = [[[self class] allocWithZone:zone] init]; - + bodyPart.stringEncoding = self.stringEncoding; bodyPart.headers = self.headers; bodyPart.bodyContentLength = self.bodyContentLength; bodyPart.body = self.body; bodyPart.boundary = self.boundary; - + return bodyPart; } @@ -1214,7 +1303,7 @@ typedef enum { [mutableRequest setValue:value forHTTPHeaderField:field]; } }]; - + if (parameters) { if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) { [mutableRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; @@ -1313,7 +1402,7 @@ typedef enum { return nil; } - self.format = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(format))] unsignedIntegerValue]; + self.format = (NSPropertyListFormat)[[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(format))] unsignedIntegerValue]; self.writeOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(writeOptions))] unsignedIntegerValue]; return self; diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLResponseSerialization.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLResponseSerialization.h old mode 100644 new mode 100755 similarity index 89% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLResponseSerialization.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLResponseSerialization.h index 030e8faed76..1578b781711 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLResponseSerialization.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLResponseSerialization.h @@ -1,6 +1,5 @@ -// AFSerialization.h -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// AFURLResponseSerialization.h +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -8,10 +7,10 @@ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -23,6 +22,8 @@ #import #import +NS_ASSUME_NONNULL_BEGIN + /** The `AFURLResponseSerialization` protocol is adopted by an object that decodes data into a more useful object representation, according to details in the server response. Response serializers may additionally perform validation on the incoming response and data. @@ -39,9 +40,13 @@ @return The object decoded from the specified response data. */ -- (id)responseObjectForResponse:(NSURLResponse *)response - data:(NSData *)data - error:(NSError *__autoreleasing *)error; +- (nullable id)responseObjectForResponse:(nullable NSURLResponse *)response + data:(nullable NSData *)data + error:(NSError * __nullable __autoreleasing *)error +#ifdef NS_SWIFT_NOTHROW +NS_SWIFT_NOTHROW +#endif +; @end @@ -54,10 +59,10 @@ */ @interface AFHTTPResponseSerializer : NSObject -- (instancetype) init; +- (instancetype)init; /** - The string encoding used to serialize parameters. + The string encoding used to serialize data received from the server, when no string encoding is specified by the response. `NSUTF8StringEncoding` by default. */ @property (nonatomic, assign) NSStringEncoding stringEncoding; @@ -75,12 +80,12 @@ See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html */ -@property (nonatomic, copy) NSIndexSet *acceptableStatusCodes; +@property (nonatomic, copy, nullable) NSIndexSet *acceptableStatusCodes; /** The acceptable MIME types for responses. When non-`nil`, responses with a `Content-Type` with MIME types that do not intersect with the set will result in an error during validation. */ -@property (nonatomic, copy) NSSet *acceptableContentTypes; +@property (nonatomic, copy, nullable) NSSet *acceptableContentTypes; /** Validates the specified response and data. @@ -93,9 +98,9 @@ @return `YES` if the response is valid, otherwise `NO`. */ -- (BOOL)validateResponse:(NSHTTPURLResponse *)response - data:(NSData *)data - error:(NSError *__autoreleasing *)error; +- (BOOL)validateResponse:(nullable NSHTTPURLResponse *)response + data:(nullable NSData *)data + error:(NSError * __nullable __autoreleasing *)error; @end @@ -113,7 +118,7 @@ */ @interface AFJSONResponseSerializer : AFHTTPResponseSerializer -- (instancetype) init; +- (instancetype)init; /** Options for reading the response JSON data and creating the Foundation objects. For possible values, see the `NSJSONSerialization` documentation section "NSJSONReadingOptions". `0` by default. @@ -162,7 +167,7 @@ */ @interface AFXMLDocumentResponseSerializer : AFHTTPResponseSerializer -- (instancetype) init; +- (instancetype)init; /** Input and output options specifically intended for `NSXMLDocument` objects. For possible values, see the `NSJSONSerialization` documentation section "NSJSONReadingOptions". `0` by default. @@ -191,7 +196,7 @@ */ @interface AFPropertyListResponseSerializer : AFHTTPResponseSerializer -- (instancetype) init; +- (instancetype)init; /** The property list format. Possible values are described in "NSPropertyListFormat". @@ -285,7 +290,7 @@ `AFURLResponseSerializationErrorDomain` AFURLResponseSerializer errors. Error codes for `AFURLResponseSerializationErrorDomain` correspond to codes in `NSURLErrorDomain`. */ -extern NSString * const AFURLResponseSerializationErrorDomain; +FOUNDATION_EXPORT NSString * const AFURLResponseSerializationErrorDomain; /** ## User info dictionary keys @@ -299,12 +304,12 @@ extern NSString * const AFURLResponseSerializationErrorDomain; `AFNetworkingOperationFailingURLResponseErrorKey` The corresponding value is an `NSURLResponse` containing the response of the operation associated with an error. This key is only present in the `AFURLResponseSerializationErrorDomain`. - + `AFNetworkingOperationFailingURLResponseDataErrorKey` The corresponding value is an `NSData` containing the original data of the operation associated with an error. This key is only present in the `AFURLResponseSerializationErrorDomain`. */ -extern NSString * const AFNetworkingOperationFailingURLResponseErrorKey; - -extern NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey; +FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLResponseErrorKey; +FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey; +NS_ASSUME_NONNULL_END diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLResponseSerialization.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLResponseSerialization.m old mode 100644 new mode 100755 similarity index 94% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLResponseSerialization.m rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLResponseSerialization.m index 083d30c2663..cfa8287a26c --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLResponseSerialization.m +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLResponseSerialization.m @@ -1,6 +1,5 @@ -// AFSerialization.h -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// AFURLResponseSerialization.m +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -8,10 +7,10 @@ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -22,8 +21,10 @@ #import "AFURLResponseSerialization.h" -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#if TARGET_OS_IOS #import +#elif TARGET_OS_WATCH +#import #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) #import #endif @@ -68,11 +69,11 @@ static id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingO } else if ([JSONObject isKindOfClass:[NSDictionary class]]) { NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithDictionary:JSONObject]; for (id key in [(NSDictionary *)JSONObject allKeys]) { - id value = [(NSDictionary *)JSONObject objectForKey:key]; + id value = (NSDictionary *)JSONObject[key]; if (!value || [value isEqual:[NSNull null]]) { [mutableDictionary removeObjectForKey:key]; } else if ([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]]) { - [mutableDictionary setObject:AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions) forKey:key]; + mutableDictionary[key] = AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions); } } @@ -276,11 +277,11 @@ static id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingO if (self.removesKeysWithNullValues && responseObject) { responseObject = AFJSONObjectByRemovingKeysWithNullValues(responseObject, self.readingOptions); } - + if (error) { *error = AFErrorWithUnderlyingError(serializationError, *error); } - + return responseObject; } @@ -500,7 +501,7 @@ static id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingO return nil; } - self.format = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(format))] unsignedIntegerValue]; + self.format = (NSPropertyListFormat)[[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(format))] unsignedIntegerValue]; self.readOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(readOptions))] unsignedIntegerValue]; return self; @@ -530,9 +531,35 @@ static id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingO #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) #import -static UIImage * AFImageWithDataAtScale(NSData *data, CGFloat scale) { - UIImage *image = [[UIImage alloc] initWithData:data]; +@interface UIImage (AFNetworkingSafeImageLoading) ++ (UIImage *)af_safeImageWithData:(NSData *)data; +@end +static NSLock* imageLock = nil; + +@implementation UIImage (AFNetworkingSafeImageLoading) + ++ (UIImage *)af_safeImageWithData:(NSData *)data { + UIImage* image = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + imageLock = [[NSLock alloc] init]; + }); + + [imageLock lock]; + image = [UIImage imageWithData:data]; + [imageLock unlock]; + return image; +} + +@end + +static UIImage * AFImageWithDataAtScale(NSData *data, CGFloat scale) { + UIImage *image = [UIImage af_safeImageWithData:data]; + if (image.images) { + return image; + } + return [[UIImage alloc] initWithCGImage:[image CGImage] scale:scale orientation:image.imageOrientation]; } @@ -549,10 +576,11 @@ static UIImage * AFInflatedImageFromResponseWithDataAtScale(NSHTTPURLResponse *r } else if ([response.MIMEType isEqualToString:@"image/jpeg"]) { imageRef = CGImageCreateWithJPEGDataProvider(dataProvider, NULL, true, kCGRenderingIntentDefault); - // CGImageCreateWithJPEGDataProvider does not properly handle CMKY, so if so, fall back to AFImageWithDataAtScale if (imageRef) { CGColorSpaceRef imageColorSpace = CGImageGetColorSpace(imageRef); CGColorSpaceModel imageColorSpaceModel = CGColorSpaceGetModel(imageColorSpace); + + // CGImageCreateWithJPEGDataProvider does not properly handle CMKY, so fall back to AFImageWithDataAtScale if (imageColorSpaceModel == kCGColorSpaceModelCMYK) { CGImageRelease(imageRef); imageRef = NULL; @@ -584,7 +612,8 @@ static UIImage * AFInflatedImageFromResponseWithDataAtScale(NSHTTPURLResponse *r return image; } - size_t bytesPerRow = 0; // CGImageGetBytesPerRow() calculates incorrectly in iOS 5.0, so defer to CGBitmapContextCreate + // CGImageGetBytesPerRow() calculates incorrectly in iOS 5.0, so defer to CGBitmapContextCreate + size_t bytesPerRow = 0; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace); CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef); @@ -622,7 +651,7 @@ static UIImage * AFInflatedImageFromResponseWithDataAtScale(NSHTTPURLResponse *r CGImageRelease(inflatedImageRef); CGImageRelease(imageRef); - + return inflatedImage; } #endif @@ -638,9 +667,12 @@ static UIImage * AFInflatedImageFromResponseWithDataAtScale(NSHTTPURLResponse *r self.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"image/tiff", @"image/jpeg", @"image/gif", @"image/png", @"image/ico", @"image/x-icon", @"image/bmp", @"image/x-bmp", @"image/x-xbitmap", @"image/x-win-bitmap", nil]; -#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#if TARGET_OS_IOS self.imageScale = [[UIScreen mainScreen] scale]; self.automaticallyInflatesResponseImage = YES; +#elif TARGET_OS_WATCH + self.imageScale = [[WKInterfaceDevice currentDevice] screenScale]; + self.automaticallyInflatesResponseImage = YES; #endif return self; @@ -758,7 +790,7 @@ static UIImage * AFInflatedImageFromResponseWithDataAtScale(NSHTTPURLResponse *r return responseObject; } } - + return [super responseObjectForResponse:response data:data error:error]; } diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLSessionManager.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLSessionManager.h old mode 100644 new mode 100755 similarity index 78% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLSessionManager.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLSessionManager.h index f475773d023..4498c892943 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLSessionManager.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLSessionManager.h @@ -1,6 +1,5 @@ // AFURLSessionManager.h -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -25,7 +24,17 @@ #import "AFURLResponseSerialization.h" #import "AFURLRequestSerialization.h" #import "AFSecurityPolicy.h" +#if !TARGET_OS_WATCH #import "AFNetworkReachabilityManager.h" +#endif + +#ifndef NS_DESIGNATED_INITIALIZER +#if __has_attribute(objc_designated_initializer) +#define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) +#else +#define NS_DESIGNATED_INITIALIZER +#endif +#endif /** `AFURLSessionManager` creates and manages an `NSURLSession` object based on a specified `NSURLSessionConfiguration` object, which conforms to ``, ``, ``, and ``. @@ -82,7 +91,9 @@ @warning Managers for background sessions must be owned for the duration of their use. This can be accomplished by creating an application-wide or shared singleton instance. */ -#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090) +NS_ASSUME_NONNULL_BEGIN + +#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090) || TARGET_OS_WATCH @interface AFURLSessionManager : NSObject @@ -112,6 +123,7 @@ */ @property (nonatomic, strong) AFSecurityPolicy *securityPolicy; +#if !TARGET_OS_WATCH ///-------------------------------------- /// @name Monitoring Network Reachability ///-------------------------------------- @@ -120,6 +132,7 @@ The network reachability manager. `AFURLSessionManager` uses the `sharedManager` by default. */ @property (readwrite, nonatomic, strong) AFNetworkReachabilityManager *reachabilityManager; +#endif ///---------------------------- /// @name Getting Session Tasks @@ -152,12 +165,20 @@ /** The dispatch queue for `completionBlock`. If `NULL` (default), the main queue is used. */ -@property (nonatomic, strong) dispatch_queue_t completionQueue; +#if OS_OBJECT_USE_OBJC +@property (nonatomic, strong, nullable) dispatch_queue_t completionQueue; +#else +@property (nonatomic, assign, nullable) dispatch_queue_t completionQueue; +#endif /** The dispatch group for `completionBlock`. If `NULL` (default), a private dispatch group is used. */ -@property (nonatomic, strong) dispatch_group_t completionGroup; +#if OS_OBJECT_USE_OBJC +@property (nonatomic, strong, nullable) dispatch_group_t completionGroup; +#else +@property (nonatomic, assign, nullable) dispatch_group_t completionGroup; +#endif ///--------------------------------- /// @name Working Around System Bugs @@ -183,7 +204,7 @@ @return A manager for a newly-created session. */ -- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration; +- (instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)configuration NS_DESIGNATED_INITIALIZER; /** Invalidates the managed session, optionally canceling pending tasks. @@ -203,7 +224,7 @@ @param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any. */ - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request - completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler; + completionHandler:(nullable void (^)(NSURLResponse *response, id __nullable responseObject, NSError * __nullable error))completionHandler; ///--------------------------- /// @name Running Upload Tasks @@ -221,8 +242,8 @@ */ - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL - progress:(NSProgress * __autoreleasing *)progress - completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler; + progress:(NSProgress * __nullable __autoreleasing * __nullable)progress + completionHandler:(nullable void (^)(NSURLResponse *response, id __nullable responseObject, NSError * __nullable error))completionHandler; /** Creates an `NSURLSessionUploadTask` with the specified request for an HTTP body. @@ -233,9 +254,9 @@ @param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any. */ - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request - fromData:(NSData *)bodyData - progress:(NSProgress * __autoreleasing *)progress - completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler; + fromData:(nullable NSData *)bodyData + progress:(NSProgress * __nullable __autoreleasing * __nullable)progress + completionHandler:(nullable void (^)(NSURLResponse *response, id __nullable responseObject, NSError * __nullable error))completionHandler; /** Creates an `NSURLSessionUploadTask` with the specified streaming request. @@ -245,8 +266,8 @@ @param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any. */ - (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request - progress:(NSProgress * __autoreleasing *)progress - completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler; + progress:(NSProgress * __nullable __autoreleasing * __nullable)progress + completionHandler:(nullable void (^)(NSURLResponse *response, id __nullable responseObject, NSError * __nullable error))completionHandler; ///----------------------------- /// @name Running Download Tasks @@ -263,9 +284,9 @@ @warning If using a background `NSURLSessionConfiguration` on iOS, these blocks will be lost when the app is terminated. Background sessions may prefer to use `-setDownloadTaskDidFinishDownloadingBlock:` to specify the URL for saving the downloaded file, rather than the destination block of this method. */ - (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request - progress:(NSProgress * __autoreleasing *)progress - destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination - completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler; + progress:(NSProgress * __nullable __autoreleasing * __nullable)progress + destination:(nullable NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination + completionHandler:(nullable void (^)(NSURLResponse *response, NSURL * __nullable filePath, NSError * __nullable error))completionHandler; /** Creates an `NSURLSessionDownloadTask` with the specified resume data. @@ -276,9 +297,9 @@ @param completionHandler A block to be executed when a task finishes. This block has no return value and takes three arguments: the server response, the path of the downloaded file, and the error describing the network or parsing error that occurred, if any. */ - (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData - progress:(NSProgress * __autoreleasing *)progress - destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination - completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler; + progress:(NSProgress * __nullable __autoreleasing * __nullable)progress + destination:(nullable NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination + completionHandler:(nullable void (^)(NSURLResponse *response, NSURL * __nullable filePath, NSError * __nullable error))completionHandler; ///--------------------------------- /// @name Getting Progress for Tasks @@ -291,7 +312,7 @@ @return An `NSProgress` object reporting the upload progress of a task, or `nil` if the progress is unavailable. */ -- (NSProgress *)uploadProgressForTask:(NSURLSessionUploadTask *)uploadTask; +- (nullable NSProgress *)uploadProgressForTask:(NSURLSessionUploadTask *)uploadTask; /** Returns the download progress of the specified task. @@ -300,7 +321,7 @@ @return An `NSProgress` object reporting the download progress of a task, or `nil` if the progress is unavailable. */ -- (NSProgress *)downloadProgressForTask:(NSURLSessionDownloadTask *)downloadTask; +- (nullable NSProgress *)downloadProgressForTask:(NSURLSessionDownloadTask *)downloadTask; ///----------------------------------------- /// @name Setting Session Delegate Callbacks @@ -311,14 +332,14 @@ @param block A block object to be executed when the managed session becomes invalid. The block has no return value, and takes two arguments: the session, and the error related to the cause of invalidation. */ -- (void)setSessionDidBecomeInvalidBlock:(void (^)(NSURLSession *session, NSError *error))block; +- (void)setSessionDidBecomeInvalidBlock:(nullable void (^)(NSURLSession *session, NSError *error))block; /** Sets a block to be executed when a connection level authentication challenge has occurred, as handled by the `NSURLSessionDelegate` method `URLSession:didReceiveChallenge:completionHandler:`. @param block A block object to be executed when a connection level authentication challenge has occurred. The block returns the disposition of the authentication challenge, and takes three arguments: the session, the authentication challenge, and a pointer to the credential that should be used to resolve the challenge. */ -- (void)setSessionDidReceiveAuthenticationChallengeBlock:(NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential))block; +- (void)setSessionDidReceiveAuthenticationChallengeBlock:(nullable NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * __nullable __autoreleasing * __nullable credential))block; ///-------------------------------------- /// @name Setting Task Delegate Callbacks @@ -329,35 +350,35 @@ @param block A block object to be executed when a task requires a new request body stream. */ -- (void)setTaskNeedNewBodyStreamBlock:(NSInputStream * (^)(NSURLSession *session, NSURLSessionTask *task))block; +- (void)setTaskNeedNewBodyStreamBlock:(nullable NSInputStream * (^)(NSURLSession *session, NSURLSessionTask *task))block; /** Sets a block to be executed when an HTTP request is attempting to perform a redirection to a different URL, as handled by the `NSURLSessionTaskDelegate` method `URLSession:willPerformHTTPRedirection:newRequest:completionHandler:`. @param block A block object to be executed when an HTTP request is attempting to perform a redirection to a different URL. The block returns the request to be made for the redirection, and takes four arguments: the session, the task, the redirection response, and the request corresponding to the redirection response. */ -- (void)setTaskWillPerformHTTPRedirectionBlock:(NSURLRequest * (^)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request))block; +- (void)setTaskWillPerformHTTPRedirectionBlock:(nullable NSURLRequest * (^)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request))block; /** Sets a block to be executed when a session task has received a request specific authentication challenge, as handled by the `NSURLSessionTaskDelegate` method `URLSession:task:didReceiveChallenge:completionHandler:`. @param block A block object to be executed when a session task has received a request specific authentication challenge. The block returns the disposition of the authentication challenge, and takes four arguments: the session, the task, the authentication challenge, and a pointer to the credential that should be used to resolve the challenge. */ -- (void)setTaskDidReceiveAuthenticationChallengeBlock:(NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential))block; +- (void)setTaskDidReceiveAuthenticationChallengeBlock:(nullable NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, NSURLCredential * __nullable __autoreleasing * __nullable credential))block; /** Sets a block to be executed periodically to track upload progress, as handled by the `NSURLSessionTaskDelegate` method `URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:`. @param block A block object to be called when an undetermined number of bytes have been uploaded to the server. This block has no return value and takes five arguments: the session, the task, the number of bytes written since the last time the upload progress block was called, the total bytes written, and the total bytes expected to be written during the request, as initially determined by the length of the HTTP body. This block may be called multiple times, and will execute on the main thread. */ -- (void)setTaskDidSendBodyDataBlock:(void (^)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend))block; +- (void)setTaskDidSendBodyDataBlock:(nullable void (^)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend))block; /** Sets a block to be executed as the last message related to a specific task, as handled by the `NSURLSessionTaskDelegate` method `URLSession:task:didCompleteWithError:`. @param block A block object to be executed when a session task is completed. The block has no return value, and takes three arguments: the session, the task, and any error that occurred in the process of executing the task. */ -- (void)setTaskDidCompleteBlock:(void (^)(NSURLSession *session, NSURLSessionTask *task, NSError *error))block; +- (void)setTaskDidCompleteBlock:(nullable void (^)(NSURLSession *session, NSURLSessionTask *task, NSError * __nullable error))block; ///------------------------------------------- /// @name Setting Data Task Delegate Callbacks @@ -368,35 +389,35 @@ @param block A block object to be executed when a data task has received a response. The block returns the disposition of the session response, and takes three arguments: the session, the data task, and the received response. */ -- (void)setDataTaskDidReceiveResponseBlock:(NSURLSessionResponseDisposition (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response))block; +- (void)setDataTaskDidReceiveResponseBlock:(nullable NSURLSessionResponseDisposition (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response))block; /** Sets a block to be executed when a data task has become a download task, as handled by the `NSURLSessionDataDelegate` method `URLSession:dataTask:didBecomeDownloadTask:`. @param block A block object to be executed when a data task has become a download task. The block has no return value, and takes three arguments: the session, the data task, and the download task it has become. */ -- (void)setDataTaskDidBecomeDownloadTaskBlock:(void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask))block; +- (void)setDataTaskDidBecomeDownloadTaskBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask))block; /** Sets a block to be executed when a data task receives data, as handled by the `NSURLSessionDataDelegate` method `URLSession:dataTask:didReceiveData:`. @param block A block object to be called when an undetermined number of bytes have been downloaded from the server. This block has no return value and takes three arguments: the session, the data task, and the data received. This block may be called multiple times, and will execute on the session manager operation queue. */ -- (void)setDataTaskDidReceiveDataBlock:(void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data))block; +- (void)setDataTaskDidReceiveDataBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data))block; /** Sets a block to be executed to determine the caching behavior of a data task, as handled by the `NSURLSessionDataDelegate` method `URLSession:dataTask:willCacheResponse:completionHandler:`. @param block A block object to be executed to determine the caching behavior of a data task. The block returns the response to cache, and takes three arguments: the session, the data task, and the proposed cached URL response. */ -- (void)setDataTaskWillCacheResponseBlock:(NSCachedURLResponse * (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSCachedURLResponse *proposedResponse))block; +- (void)setDataTaskWillCacheResponseBlock:(nullable NSCachedURLResponse * (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSCachedURLResponse *proposedResponse))block; /** Sets a block to be executed once all messages enqueued for a session have been delivered, as handled by the `NSURLSessionDataDelegate` method `URLSessionDidFinishEventsForBackgroundURLSession:`. @param block A block object to be executed once all messages enqueued for a session have been delivered. The block has no return value and takes a single argument: the session. */ -- (void)setDidFinishEventsForBackgroundURLSessionBlock:(void (^)(NSURLSession *session))block; +- (void)setDidFinishEventsForBackgroundURLSessionBlock:(nullable void (^)(NSURLSession *session))block; ///----------------------------------------------- /// @name Setting Download Task Delegate Callbacks @@ -407,21 +428,21 @@ @param block A block object to be executed when a download task has completed. The block returns the URL the download should be moved to, and takes three arguments: the session, the download task, and the temporary location of the downloaded file. If the file manager encounters an error while attempting to move the temporary file to the destination, an `AFURLSessionDownloadTaskDidFailToMoveFileNotification` will be posted, with the download task as its object, and the user info of the error. */ -- (void)setDownloadTaskDidFinishDownloadingBlock:(NSURL * (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location))block; +- (void)setDownloadTaskDidFinishDownloadingBlock:(nullable NSURL * __nullable (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location))block; /** Sets a block to be executed periodically to track download progress, as handled by the `NSURLSessionDownloadDelegate` method `URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesWritten:totalBytesExpectedToWrite:`. @param block A block object to be called when an undetermined number of bytes have been downloaded from the server. This block has no return value and takes five arguments: the session, the download task, the number of bytes read since the last time the download progress block was called, the total bytes read, and the total bytes expected to be read during the request, as initially determined by the expected content size of the `NSHTTPURLResponse` object. This block may be called multiple times, and will execute on the session manager operation queue. */ -- (void)setDownloadTaskDidWriteDataBlock:(void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite))block; +- (void)setDownloadTaskDidWriteDataBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite))block; /** Sets a block to be executed when a download task has been resumed, as handled by the `NSURLSessionDownloadDelegate` method `URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:`. @param block A block object to be executed when a download task has been resumed. The block has no return value and takes four arguments: the session, the download task, the file offset of the resumed download, and the total number of bytes expected to be downloaded. */ -- (void)setDownloadTaskDidResumeBlock:(void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t fileOffset, int64_t expectedTotalBytes))block; +- (void)setDownloadTaskDidResumeBlock:(nullable void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t fileOffset, int64_t expectedTotalBytes))block; @end @@ -436,96 +457,98 @@ @deprecated Use `AFNetworkingTaskDidResumeNotification` instead. */ -extern NSString * const AFNetworkingTaskDidStartNotification DEPRECATED_ATTRIBUTE; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidStartNotification DEPRECATED_ATTRIBUTE; /** Posted when a task resumes. */ -extern NSString * const AFNetworkingTaskDidResumeNotification; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidResumeNotification; /** Posted when a task finishes executing. Includes a userInfo dictionary with additional information about the task. @deprecated Use `AFNetworkingTaskDidCompleteNotification` instead. */ -extern NSString * const AFNetworkingTaskDidFinishNotification DEPRECATED_ATTRIBUTE; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidFinishNotification DEPRECATED_ATTRIBUTE; /** Posted when a task finishes executing. Includes a userInfo dictionary with additional information about the task. */ -extern NSString * const AFNetworkingTaskDidCompleteNotification; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteNotification; /** Posted when a task suspends its execution. */ -extern NSString * const AFNetworkingTaskDidSuspendNotification; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidSuspendNotification; /** Posted when a session is invalidated. */ -extern NSString * const AFURLSessionDidInvalidateNotification; +FOUNDATION_EXPORT NSString * const AFURLSessionDidInvalidateNotification; /** Posted when a session download task encountered an error when moving the temporary download file to a specified destination. */ -extern NSString * const AFURLSessionDownloadTaskDidFailToMoveFileNotification; +FOUNDATION_EXPORT NSString * const AFURLSessionDownloadTaskDidFailToMoveFileNotification; /** The raw response data of the task. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if response data exists for the task. @deprecated Use `AFNetworkingTaskDidCompleteResponseDataKey` instead. */ -extern NSString * const AFNetworkingTaskDidFinishResponseDataKey DEPRECATED_ATTRIBUTE; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidFinishResponseDataKey DEPRECATED_ATTRIBUTE; /** The raw response data of the task. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if response data exists for the task. */ -extern NSString * const AFNetworkingTaskDidCompleteResponseDataKey; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteResponseDataKey; /** The serialized response object of the task. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if the response was serialized. @deprecated Use `AFNetworkingTaskDidCompleteSerializedResponseKey` instead. */ -extern NSString * const AFNetworkingTaskDidFinishSerializedResponseKey DEPRECATED_ATTRIBUTE; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidFinishSerializedResponseKey DEPRECATED_ATTRIBUTE; /** The serialized response object of the task. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if the response was serialized. */ -extern NSString * const AFNetworkingTaskDidCompleteSerializedResponseKey; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteSerializedResponseKey; /** The response serializer used to serialize the response. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if the task has an associated response serializer. @deprecated Use `AFNetworkingTaskDidCompleteResponseSerializerKey` instead. */ -extern NSString * const AFNetworkingTaskDidFinishResponseSerializerKey DEPRECATED_ATTRIBUTE; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidFinishResponseSerializerKey DEPRECATED_ATTRIBUTE; /** The response serializer used to serialize the response. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if the task has an associated response serializer. */ -extern NSString * const AFNetworkingTaskDidCompleteResponseSerializerKey; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteResponseSerializerKey; /** The file path associated with the download task. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if an the response data has been stored directly to disk. @deprecated Use `AFNetworkingTaskDidCompleteAssetPathKey` instead. */ -extern NSString * const AFNetworkingTaskDidFinishAssetPathKey DEPRECATED_ATTRIBUTE; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidFinishAssetPathKey DEPRECATED_ATTRIBUTE; /** The file path associated with the download task. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if an the response data has been stored directly to disk. */ -extern NSString * const AFNetworkingTaskDidCompleteAssetPathKey; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteAssetPathKey; /** Any error associated with the task, or the serialization of the response. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if an error exists. @deprecated Use `AFNetworkingTaskDidCompleteErrorKey` instead. */ -extern NSString * const AFNetworkingTaskDidFinishErrorKey DEPRECATED_ATTRIBUTE; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidFinishErrorKey DEPRECATED_ATTRIBUTE; /** Any error associated with the task, or the serialization of the response. Included in the userInfo dictionary of the `AFNetworkingTaskDidFinishNotification` if an error exists. */ -extern NSString * const AFNetworkingTaskDidCompleteErrorKey; +FOUNDATION_EXPORT NSString * const AFNetworkingTaskDidCompleteErrorKey; + +NS_ASSUME_NONNULL_END diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLSessionManager.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLSessionManager.m old mode 100644 new mode 100755 similarity index 85% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLSessionManager.m rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLSessionManager.m index d53e6ec2db2..8ec0f0843b2 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/AFNetworking/AFURLSessionManager.m +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/AFNetworking/AFURLSessionManager.m @@ -1,6 +1,5 @@ // AFURLSessionManager.m -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -8,10 +7,10 @@ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -155,10 +154,18 @@ didCompleteWithError:(NSError *)error __block NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = manager.responseSerializer; + //Performance Improvement from #2672 + NSData *data = nil; + if (self.mutableData) { + data = [self.mutableData copy]; + //We no longer need the reference, so nil it out to gain back some memory. + self.mutableData = nil; + } + if (self.downloadFileURL) { userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self.downloadFileURL; - } else if (self.mutableData) { - userInfo[AFNetworkingTaskDidCompleteResponseDataKey] = [NSData dataWithData:self.mutableData]; + } else if (data) { + userInfo[AFNetworkingTaskDidCompleteResponseDataKey] = data; } if (error) { @@ -176,7 +183,7 @@ didCompleteWithError:(NSError *)error } else { dispatch_async(url_session_manager_processing_queue(), ^{ NSError *serializationError = nil; - responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:[NSData dataWithData:self.mutableData] error:&serializationError]; + responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError]; if (self.downloadFileURL) { responseObject = self.downloadFileURL; @@ -194,7 +201,7 @@ didCompleteWithError:(NSError *)error if (self.completionHandler) { self.completionHandler(task.response, responseObject, serializationError); } - + dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo]; }); @@ -256,58 +263,129 @@ expectedTotalBytes:(int64_t)expectedTotalBytes { #pragma mark - -/* - A workaround for issues related to key-value observing the `state` of an `NSURLSessionTask`. - - See https://github.com/AFNetworking/AFNetworking/issues/1477 +/** + * A workaround for issues related to key-value observing the `state` of an `NSURLSessionTask`. + * + * See: + * - https://github.com/AFNetworking/AFNetworking/issues/1477 + * - https://github.com/AFNetworking/AFNetworking/issues/2638 + * - https://github.com/AFNetworking/AFNetworking/pull/2702 */ -static inline void af_swizzleSelector(Class class, SEL originalSelector, SEL swizzledSelector) { - Method originalMethod = class_getInstanceMethod(class, originalSelector); - Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); - if (class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))) { - class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); - } else { - method_exchangeImplementations(originalMethod, swizzledMethod); - } +static inline void af_swizzleSelector(Class theClass, SEL originalSelector, SEL swizzledSelector) { + Method originalMethod = class_getInstanceMethod(theClass, originalSelector); + Method swizzledMethod = class_getInstanceMethod(theClass, swizzledSelector); + method_exchangeImplementations(originalMethod, swizzledMethod); +} + +static inline BOOL af_addMethod(Class theClass, SEL selector, Method method) { + return class_addMethod(theClass, selector, method_getImplementation(method), method_getTypeEncoding(method)); } static NSString * const AFNSURLSessionTaskDidResumeNotification = @"com.alamofire.networking.nsurlsessiontask.resume"; static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofire.networking.nsurlsessiontask.suspend"; -@interface NSURLSessionTask (_AFStateObserving) +@interface _AFURLSessionTaskSwizzling : NSObject + @end -@implementation NSURLSessionTask (_AFStateObserving) +@implementation _AFURLSessionTaskSwizzling + (void)load { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - af_swizzleSelector([self class], @selector(resume), @selector(af_resume)); - af_swizzleSelector([self class], @selector(suspend), @selector(af_suspend)); - }); + /** + WARNING: Trouble Ahead + https://github.com/AFNetworking/AFNetworking/pull/2702 + */ + + if (NSClassFromString(@"NSURLSessionTask")) { + /** + iOS 7 and iOS 8 differ in NSURLSessionTask implementation, which makes the next bit of code a bit tricky. + Many Unit Tests have been built to validate as much of this behavior has possible. + Here is what we know: + - NSURLSessionTasks are implemented with class clusters, meaning the class you request from the API isn't actually the type of class you will get back. + - Simply referencing `[NSURLSessionTask class]` will not work. You need to ask an `NSURLSession` to actually create an object, and grab the class from there. + - On iOS 7, `localDataTask` is a `__NSCFLocalDataTask`, which inherits from `__NSCFLocalSessionTask`, which inherits from `__NSCFURLSessionTask`. + - On iOS 8, `localDataTask` is a `__NSCFLocalDataTask`, which inherits from `__NSCFLocalSessionTask`, which inherits from `NSURLSessionTask`. + - On iOS 7, `__NSCFLocalSessionTask` and `__NSCFURLSessionTask` are the only two classes that have their own implementations of `resume` and `suspend`, and `__NSCFLocalSessionTask` DOES NOT CALL SUPER. This means both classes need to be swizzled. + - On iOS 8, `NSURLSessionTask` is the only class that implements `resume` and `suspend`. This means this is the only class that needs to be swizzled. + - Because `NSURLSessionTask` is not involved in the class hierarchy for every version of iOS, its easier to add the swizzled methods to a dummy class and manage them there. + + Some Assumptions: + - No implementations of `resume` or `suspend` call super. If this were to change in a future version of iOS, we'd need to handle it. + - No background task classes override `resume` or `suspend` + + The current solution: + 1) Grab an instance of `__NSCFLocalDataTask` by asking an instance of `NSURLSession` for a data task. + 2) Grab a pointer to the original implementation of `af_resume` + 3) Check to see if the current class has an implementation of resume. If so, continue to step 4. + 4) Grab the super class of the current class. + 5) Grab a pointer for the current class to the current implementation of `resume`. + 6) Grab a pointer for the super class to the current implementation of `resume`. + 7) If the current class implementation of `resume` is not equal to the super class implementation of `resume` AND the current implementation of `resume` is not equal to the original implementation of `af_resume`, THEN swizzle the methods + 8) Set the current class to the super class, and repeat steps 3-8 + */ + NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; + NSURLSession * session = [NSURLSession sessionWithConfiguration:configuration]; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnonnull" + NSURLSessionDataTask *localDataTask = [session dataTaskWithURL:nil]; +#pragma clang diagnostic pop + IMP originalAFResumeIMP = method_getImplementation(class_getInstanceMethod([self class], @selector(af_resume))); + Class currentClass = [localDataTask class]; + + while (class_getInstanceMethod(currentClass, @selector(resume))) { + Class superClass = [currentClass superclass]; + IMP classResumeIMP = method_getImplementation(class_getInstanceMethod(currentClass, @selector(resume))); + IMP superclassResumeIMP = method_getImplementation(class_getInstanceMethod(superClass, @selector(resume))); + if (classResumeIMP != superclassResumeIMP && + originalAFResumeIMP != classResumeIMP) { + [self swizzleResumeAndSuspendMethodForClass:currentClass]; + } + currentClass = [currentClass superclass]; + } + + [localDataTask cancel]; + [session finishTasksAndInvalidate]; + } } -#pragma mark - ++ (void)swizzleResumeAndSuspendMethodForClass:(Class)theClass { + Method afResumeMethod = class_getInstanceMethod(self, @selector(af_resume)); + Method afSuspendMethod = class_getInstanceMethod(self, @selector(af_suspend)); + + if (af_addMethod(theClass, @selector(af_resume), afResumeMethod)) { + af_swizzleSelector(theClass, @selector(resume), @selector(af_resume)); + } + + if (af_addMethod(theClass, @selector(af_suspend), afSuspendMethod)) { + af_swizzleSelector(theClass, @selector(suspend), @selector(af_suspend)); + } +} + +- (NSURLSessionTaskState)state { + NSAssert(NO, @"State method should never be called in the actual dummy class"); + return NSURLSessionTaskStateCanceling; +} - (void)af_resume { - NSURLSessionTaskState state = self.state; + NSAssert([self respondsToSelector:@selector(state)], @"Does not respond to state"); + NSURLSessionTaskState state = [self state]; [self af_resume]; - + if (state != NSURLSessionTaskStateRunning) { [[NSNotificationCenter defaultCenter] postNotificationName:AFNSURLSessionTaskDidResumeNotification object:self]; } } - (void)af_suspend { - NSURLSessionTaskState state = self.state; + NSAssert([self respondsToSelector:@selector(state)], @"Does not respond to state"); + NSURLSessionTaskState state = [self state]; [self af_suspend]; - + if (state != NSURLSessionTaskStateSuspended) { [[NSNotificationCenter defaultCenter] postNotificationName:AFNSURLSessionTaskDidSuspendNotification object:self]; } } - @end #pragma mark - @@ -317,6 +395,7 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi @property (readwrite, nonatomic, strong) NSOperationQueue *operationQueue; @property (readwrite, nonatomic, strong) NSURLSession *session; @property (readwrite, nonatomic, strong) NSMutableDictionary *mutableTaskDelegatesKeyedByTaskIdentifier; +@property (readonly, nonatomic, copy) NSString *taskDescriptionForSessionTasks; @property (readwrite, nonatomic, strong) NSLock *lock; @property (readwrite, nonatomic, copy) AFURLSessionDidBecomeInvalidBlock sessionDidBecomeInvalid; @property (readwrite, nonatomic, copy) AFURLSessionDidReceiveAuthenticationChallengeBlock sessionDidReceiveAuthenticationChallenge; @@ -362,22 +441,24 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi self.securityPolicy = [AFSecurityPolicy defaultPolicy]; +#if !TARGET_OS_WATCH self.reachabilityManager = [AFNetworkReachabilityManager sharedManager]; +#endif self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init]; self.lock = [[NSLock alloc] init]; self.lock.name = AFURLSessionManagerLockName; - + [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) { for (NSURLSessionDataTask *task in dataTasks) { [self addDelegateForDataTask:task completionHandler:nil]; } - + for (NSURLSessionUploadTask *uploadTask in uploadTasks) { [self addDelegateForUploadTask:uploadTask progress:nil completionHandler:nil]; } - + for (NSURLSessionDownloadTask *downloadTask in downloadTasks) { [self addDelegateForDownloadTask:downloadTask progress:nil destination:nil completionHandler:nil]; } @@ -393,11 +474,16 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi [[NSNotificationCenter defaultCenter] removeObserver:self]; } +#pragma mark - + +- (NSString *)taskDescriptionForSessionTasks { + return [NSString stringWithFormat:@"%p", self]; +} + - (void)taskDidResume:(NSNotification *)notification { NSURLSessionTask *task = notification.object; - if ([task isKindOfClass:[NSURLSessionTask class]]) { - AFURLSessionManager *manager = [self delegateForTask:task].manager; - if ([manager isEqual:self]) { + if ([task respondsToSelector:@selector(taskDescription)]) { + if ([task.taskDescription isEqualToString:self.taskDescriptionForSessionTasks]) { dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidResumeNotification object:task]; }); @@ -407,9 +493,8 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi - (void)taskDidSuspend:(NSNotification *)notification { NSURLSessionTask *task = notification.object; - if ([task isKindOfClass:[NSURLSessionTask class]]) { - AFURLSessionManager *manager = [self delegateForTask:task].manager; - if ([manager isEqual:self]) { + if ([task respondsToSelector:@selector(taskDescription)]) { + if ([task.taskDescription isEqualToString:self.taskDescriptionForSessionTasks]) { dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidSuspendNotification object:task]; }); @@ -448,6 +533,7 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi delegate.manager = self; delegate.completionHandler = completionHandler; + dataTask.taskDescription = self.taskDescriptionForSessionTasks; [self setDelegate:delegate forTask:dataTask]; } @@ -463,11 +549,16 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi if(totalUnitCount == NSURLSessionTransferSizeUnknown) { NSString *contentLength = [uploadTask.originalRequest valueForHTTPHeaderField:@"Content-Length"]; if(contentLength) { - totalUnitCount = (int64_t) [contentLength longLongValue]; + totalUnitCount = (int64_t)[contentLength longLongValue]; } } - delegate.progress = [NSProgress progressWithTotalUnitCount:totalUnitCount]; + if (delegate.progress) { + delegate.progress.totalUnitCount = totalUnitCount; + } else { + delegate.progress = [NSProgress progressWithTotalUnitCount:totalUnitCount]; + } + delegate.progress.pausingHandler = ^{ [uploadTask suspend]; }; @@ -479,6 +570,8 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi *progress = delegate.progress; } + uploadTask.taskDescription = self.taskDescriptionForSessionTasks; + [self setDelegate:delegate forTask:uploadTask]; } @@ -501,6 +594,8 @@ static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofi *progress = delegate.progress; } + downloadTask.taskDescription = self.taskDescriptionForSessionTasks; + [self setDelegate:delegate forTask:downloadTask]; } @@ -871,7 +966,7 @@ didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge needNewBodyStream:(void (^)(NSInputStream *bodyStream))completionHandler { NSInputStream *inputStream = nil; - + if (self.taskNeedNewBodyStream) { inputStream = self.taskNeedNewBodyStream(session, task); } else if (task.originalRequest.HTTPBodyStream && [task.originalRequest.HTTPBodyStream conformsToProtocol:@protocol(NSCopying)]) { @@ -889,7 +984,7 @@ didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend { - + int64_t totalUnitCount = totalBytesExpectedToSend; if(totalUnitCount == NSURLSessionTransferSizeUnknown) { NSString *contentLength = [task.originalRequest valueForHTTPHeaderField:@"Content-Length"]; @@ -897,7 +992,7 @@ totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend totalUnitCount = (int64_t) [contentLength longLongValue]; } } - + AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task]; [delegate URLSession:session task:task didSendBodyData:bytesSent totalBytesSent:totalBytesSent totalBytesExpectedToSend:totalUnitCount]; @@ -1014,7 +1109,7 @@ didFinishDownloadingToURL:(NSURL *)location return; } } - + if (delegate) { [delegate URLSession:session downloadTask:downloadTask didFinishDownloadingToURL:location]; } diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SMTWiFiStatus/SMTWiFiStatus.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SMTWiFiStatus/SMTWiFiStatus.h new file mode 100644 index 00000000000..05278ab2c28 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SMTWiFiStatus/SMTWiFiStatus.h @@ -0,0 +1,22 @@ +// +// SMTWiFiStatus.h +// SAPTracker +// +// Created by Raimund Wege on 02.08.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// +// See: http://www.enigmaticape.com/blog/determine-wifi-enabled-ios-one-weird-trick + +#import + +typedef NS_ENUM(NSUInteger, WiFiStatus) { + On, + Off, + Unknown +}; + +@interface SMTWiFiStatus : NSObject + ++ (WiFiStatus)wifiStatus; + +@end diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SMTWiFiStatus/SMTWiFiStatus.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SMTWiFiStatus/SMTWiFiStatus.m new file mode 100644 index 00000000000..94b5075761d --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SMTWiFiStatus/SMTWiFiStatus.m @@ -0,0 +1,35 @@ +// +// SMTWiFiStatus.m +// SAPTracker +// +// Created by Raimund Wege on 02.08.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// +// See: http://www.enigmaticape.com/blog/determine-wifi-enabled-ios-one-weird-trick + +#import + +#import +#import +#import + +#import "SMTWiFiStatus.h" + +@implementation SMTWiFiStatus : NSObject + ++ (WiFiStatus)wifiStatus { + NSCountedSet *cset = [NSCountedSet new]; + struct ifaddrs *interfaces; + if (!getifaddrs(&interfaces)) { + for (struct ifaddrs *interface = interfaces; interface; interface = interface->ifa_next) { + if ((interface->ifa_flags & IFF_UP) == IFF_UP ) { + [cset addObject:[NSString stringWithUTF8String:interface->ifa_name]]; + } + } + } + freeifaddrs(interfaces); + NSUInteger count = [cset countForObject:@"awdl0"]; + return count > 1 ? On : (count > 0 ? Off : Unknown); +} + +@end diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVIndefiniteAnimatedView.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVIndefiniteAnimatedView.h new file mode 100755 index 00000000000..d6f1eaf0a4a --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVIndefiniteAnimatedView.h @@ -0,0 +1,17 @@ +// +// SVIndefiniteAnimatedView.h +// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD +// +// Copyright (c) 2014-2016 Guillaume Campagna. All rights reserved. +// + +#import + +@interface SVIndefiniteAnimatedView : UIView + +@property (nonatomic, assign) CGFloat strokeThickness; +@property (nonatomic, assign) CGFloat radius; +@property (nonatomic, strong) UIColor *strokeColor; + +@end + diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVIndefiniteAnimatedView.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVIndefiniteAnimatedView.m new file mode 100755 index 00000000000..235a0f92490 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVIndefiniteAnimatedView.m @@ -0,0 +1,137 @@ +// +// SVIndefiniteAnimatedView.m +// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD +// +// Copyright (c) 2014-2016 Guillaume Campagna. All rights reserved. +// + +#import "SVIndefiniteAnimatedView.h" +#import "SVProgressHUD.h" + +@interface SVIndefiniteAnimatedView () + +@property (nonatomic, strong) CAShapeLayer *indefiniteAnimatedLayer; + +@end + +@implementation SVIndefiniteAnimatedView + +- (void)willMoveToSuperview:(UIView*)newSuperview { + if (newSuperview) { + [self layoutAnimatedLayer]; + } else { + [_indefiniteAnimatedLayer removeFromSuperlayer]; + _indefiniteAnimatedLayer = nil; + } +} + +- (void)layoutAnimatedLayer { + CALayer *layer = self.indefiniteAnimatedLayer; + [self.layer addSublayer:layer]; + + CGFloat widthDiff = CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds); + CGFloat heightDiff = CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds); + layer.position = CGPointMake(CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds) / 2 - widthDiff / 2, CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds) / 2 - heightDiff / 2); +} + +- (CAShapeLayer*)indefiniteAnimatedLayer { + if(!_indefiniteAnimatedLayer) { + CGPoint arcCenter = CGPointMake(self.radius+self.strokeThickness/2+5, self.radius+self.strokeThickness/2+5); + UIBezierPath* smoothedPath = [UIBezierPath bezierPathWithArcCenter:arcCenter radius:self.radius startAngle:(CGFloat) (M_PI*3/2) endAngle:(CGFloat) (M_PI/2+M_PI*5) clockwise:YES]; + + _indefiniteAnimatedLayer = [CAShapeLayer layer]; + _indefiniteAnimatedLayer.contentsScale = [[UIScreen mainScreen] scale]; + _indefiniteAnimatedLayer.frame = CGRectMake(0.0f, 0.0f, arcCenter.x*2, arcCenter.y*2); + _indefiniteAnimatedLayer.fillColor = [UIColor clearColor].CGColor; + _indefiniteAnimatedLayer.strokeColor = self.strokeColor.CGColor; + _indefiniteAnimatedLayer.lineWidth = self.strokeThickness; + _indefiniteAnimatedLayer.lineCap = kCALineCapRound; + _indefiniteAnimatedLayer.lineJoin = kCALineJoinBevel; + _indefiniteAnimatedLayer.path = smoothedPath.CGPath; + + CALayer *maskLayer = [CALayer layer]; + + NSBundle *bundle = [NSBundle bundleForClass:[SVProgressHUD class]]; + NSURL *url = [bundle URLForResource:@"SVProgressHUD" withExtension:@"bundle"]; + NSBundle *imageBundle = [NSBundle bundleWithURL:url]; + + NSString *path = [imageBundle pathForResource:@"angle-mask" ofType:@"png"]; + + maskLayer.contents = (__bridge id)[[UIImage imageWithContentsOfFile:path] CGImage]; + maskLayer.frame = _indefiniteAnimatedLayer.bounds; + _indefiniteAnimatedLayer.mask = maskLayer; + + NSTimeInterval animationDuration = 1; + CAMediaTimingFunction *linearCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; + + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; + animation.fromValue = (id) 0; + animation.toValue = @(M_PI*2); + animation.duration = animationDuration; + animation.timingFunction = linearCurve; + animation.removedOnCompletion = NO; + animation.repeatCount = INFINITY; + animation.fillMode = kCAFillModeForwards; + animation.autoreverses = NO; + [_indefiniteAnimatedLayer.mask addAnimation:animation forKey:@"rotate"]; + + CAAnimationGroup *animationGroup = [CAAnimationGroup animation]; + animationGroup.duration = animationDuration; + animationGroup.repeatCount = INFINITY; + animationGroup.removedOnCompletion = NO; + animationGroup.timingFunction = linearCurve; + + CABasicAnimation *strokeStartAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"]; + strokeStartAnimation.fromValue = @0.015; + strokeStartAnimation.toValue = @0.515; + + CABasicAnimation *strokeEndAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; + strokeEndAnimation.fromValue = @0.485; + strokeEndAnimation.toValue = @0.985; + + animationGroup.animations = @[strokeStartAnimation, strokeEndAnimation]; + [_indefiniteAnimatedLayer addAnimation:animationGroup forKey:@"progress"]; + + } + return _indefiniteAnimatedLayer; +} + +- (void)setFrame:(CGRect)frame { + if(!CGRectEqualToRect(frame, super.frame)) { + [super setFrame:frame]; + + if(self.superview) { + [self layoutAnimatedLayer]; + } + } + +} + +- (void)setRadius:(CGFloat)radius { + if(radius != _radius) { + _radius = radius; + + [_indefiniteAnimatedLayer removeFromSuperlayer]; + _indefiniteAnimatedLayer = nil; + + if(self.superview) { + [self layoutAnimatedLayer]; + } + } +} + +- (void)setStrokeColor:(UIColor*)strokeColor { + _strokeColor = strokeColor; + _indefiniteAnimatedLayer.strokeColor = strokeColor.CGColor; +} + +- (void)setStrokeThickness:(CGFloat)strokeThickness { + _strokeThickness = strokeThickness; + _indefiniteAnimatedLayer.lineWidth = _strokeThickness; +} + +- (CGSize)sizeThatFits:(CGSize)size { + return CGSizeMake((self.radius+self.strokeThickness/2+5)*2, (self.radius+self.strokeThickness/2+5)*2); +} + +@end diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressAnimatedView.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressAnimatedView.h new file mode 100755 index 00000000000..6b4d54a0110 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressAnimatedView.h @@ -0,0 +1,17 @@ +// +// SVProgressAnimatedView.h +// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD +// +// Copyright (c) 2016 Tobias Tiemerding. All rights reserved. +// + +#import + +@interface SVProgressAnimatedView : UIView + +@property (nonatomic, assign) CGFloat radius; +@property (nonatomic, assign) CGFloat strokeThickness; +@property (nonatomic, strong) UIColor *strokeColor; +@property (nonatomic, assign) CGFloat strokeEnd; + +@end diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressAnimatedView.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressAnimatedView.m new file mode 100755 index 00000000000..3adb3c6e70d --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressAnimatedView.m @@ -0,0 +1,98 @@ +// +// SVProgressAnimatedView.m +// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD +// +// Copyright (c) 2016 Tobias Tiemerding. All rights reserved. +// + +#import "SVProgressAnimatedView.h" + +@interface SVProgressAnimatedView () + +@property (nonatomic, strong) CAShapeLayer *ringAnimatedLayer; + +@end + +@implementation SVProgressAnimatedView + +- (void)willMoveToSuperview:(UIView*)newSuperview { + if (newSuperview) { + [self layoutAnimatedLayer]; + } else { + [_ringAnimatedLayer removeFromSuperlayer]; + _ringAnimatedLayer = nil; + } +} + +- (void)layoutAnimatedLayer { + CALayer *layer = self.ringAnimatedLayer; + [self.layer addSublayer:layer]; + + CGFloat widthDiff = CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds); + CGFloat heightDiff = CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds); + layer.position = CGPointMake(CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds) / 2 - widthDiff / 2, CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds) / 2 - heightDiff / 2); +} + +- (CAShapeLayer*)ringAnimatedLayer { + if(!_ringAnimatedLayer) { + CGPoint arcCenter = CGPointMake(self.radius+self.strokeThickness/2+5, self.radius+self.strokeThickness/2+5); + UIBezierPath* smoothedPath = [UIBezierPath bezierPathWithArcCenter:arcCenter radius:self.radius startAngle:(CGFloat)-M_PI_2 endAngle:(CGFloat) (M_PI + M_PI_2) clockwise:YES]; + + _ringAnimatedLayer = [CAShapeLayer layer]; + _ringAnimatedLayer.contentsScale = [[UIScreen mainScreen] scale]; + _ringAnimatedLayer.frame = CGRectMake(0.0f, 0.0f, arcCenter.x*2, arcCenter.y*2); + _ringAnimatedLayer.fillColor = [UIColor clearColor].CGColor; + _ringAnimatedLayer.strokeColor = self.strokeColor.CGColor; + _ringAnimatedLayer.lineWidth = self.strokeThickness; + _ringAnimatedLayer.lineCap = kCALineCapRound; + _ringAnimatedLayer.lineJoin = kCALineJoinBevel; + _ringAnimatedLayer.path = smoothedPath.CGPath; + } + return _ringAnimatedLayer; +} + +- (void)setFrame:(CGRect)frame { + if(!CGRectEqualToRect(frame, super.frame)) { + [super setFrame:frame]; + + if(self.superview) { + [self layoutAnimatedLayer]; + } + } + +} + +- (void)setRadius:(CGFloat)radius { + if(radius != _radius) { + _radius = radius; + + [_ringAnimatedLayer removeFromSuperlayer]; + _ringAnimatedLayer = nil; + + if(self.superview) { + [self layoutAnimatedLayer]; + } + } +} + +- (void)setStrokeColor:(UIColor*)strokeColor { + _strokeColor = strokeColor; + _ringAnimatedLayer.strokeColor = strokeColor.CGColor; +} + +- (void)setStrokeThickness:(CGFloat)strokeThickness { + _strokeThickness = strokeThickness; + _ringAnimatedLayer.lineWidth = _strokeThickness; +} + +- (void)setStrokeEnd:(CGFloat)strokeEnd { + _strokeEnd = strokeEnd; + _ringAnimatedLayer.strokeEnd = _strokeEnd; +} + + +- (CGSize)sizeThatFits:(CGSize)size { + return CGSizeMake((self.radius+self.strokeThickness/2+5)*2, (self.radius+self.strokeThickness/2+5)*2); +} + +@end diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD-Prefix.pch b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD-Prefix.pch new file mode 100755 index 00000000000..2fff997888c --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD-Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'SVProgressHUD' target in the 'SVProgressHUD' project +// + +#ifdef __OBJC__ + #import +#endif diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/angle-mask.png b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/angle-mask.png new file mode 100755 index 00000000000..0150a03f535 Binary files /dev/null and b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/angle-mask.png differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/angle-mask@2x.png b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/angle-mask@2x.png new file mode 100755 index 00000000000..9a302b6801d Binary files /dev/null and b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/angle-mask@2x.png differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/angle-mask@3x.png b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/angle-mask@3x.png new file mode 100755 index 00000000000..d07f3ce67e8 Binary files /dev/null and b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/angle-mask@3x.png differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/error.png b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/error.png new file mode 100755 index 00000000000..a57c8e4462c Binary files /dev/null and b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/error.png differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/error@2x.png b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/error@2x.png new file mode 100755 index 00000000000..aaf67985478 Binary files /dev/null and b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/error@2x.png differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/error@3x.png b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/error@3x.png new file mode 100755 index 00000000000..c92518f8534 Binary files /dev/null and b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/error@3x.png differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/info.png b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/info.png new file mode 100755 index 00000000000..a3a1f75c268 Binary files /dev/null and b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/info.png differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/info@2x.png b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/info@2x.png new file mode 100755 index 00000000000..1b333e7b845 Binary files /dev/null and b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/info@2x.png differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/info@3x.png b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/info@3x.png new file mode 100755 index 00000000000..d56aa0c229f Binary files /dev/null and b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/info@3x.png differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/success.png b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/success.png new file mode 100755 index 00000000000..44769d028f9 Binary files /dev/null and b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/success.png differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/success@2x.png b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/success@2x.png new file mode 100755 index 00000000000..a9d16532fa8 Binary files /dev/null and b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/success@2x.png differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/success@3x.png b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/success@3x.png new file mode 100755 index 00000000000..42bad9be6bd Binary files /dev/null and b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.bundle/success@3x.png differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.h new file mode 100755 index 00000000000..993dda12e19 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.h @@ -0,0 +1,138 @@ +// +// SVProgressHUD.h +// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD +// +// Copyright (c) 2011-2016 Sam Vermette and contributors. All rights reserved. +// + +#import +#import + +#if __IPHONE_OS_VERSION_MAX_ALLOWED < 70000 + +#define UI_APPEARANCE_SELECTOR + +#endif + +extern NSString * const SVProgressHUDDidReceiveTouchEventNotification; +extern NSString * const SVProgressHUDDidTouchDownInsideNotification; +extern NSString * const SVProgressHUDWillDisappearNotification; +extern NSString * const SVProgressHUDDidDisappearNotification; +extern NSString * const SVProgressHUDWillAppearNotification; +extern NSString * const SVProgressHUDDidAppearNotification; + +extern NSString * const SVProgressHUDStatusUserInfoKey; + +typedef NS_ENUM(NSInteger, SVProgressHUDStyle) { + SVProgressHUDStyleLight, // default style, white HUD with black text, HUD background will be blurred on iOS 8 and above + SVProgressHUDStyleDark, // black HUD and white text, HUD background will be blurred on iOS 8 and above + SVProgressHUDStyleCustom // uses the fore- and background color properties +}; + +typedef NS_ENUM(NSUInteger, SVProgressHUDMaskType) { + SVProgressHUDMaskTypeNone = 1, // default mask type, allow user interactions while HUD is displayed + SVProgressHUDMaskTypeClear, // don't allow user interactions + SVProgressHUDMaskTypeBlack, // don't allow user interactions and dim the UI in the back of the HUD, as on iOS 7 and above + SVProgressHUDMaskTypeGradient, // don't allow user interactions and dim the UI with a a-la UIAlertView background gradient, as on iOS 6 + SVProgressHUDMaskTypeCustom // don't allow user interactions and dim the UI in the back of the HUD with a custom color +}; + +typedef NS_ENUM(NSUInteger, SVProgressHUDAnimationType) { + SVProgressHUDAnimationTypeFlat, // default animation type, custom flat animation (indefinite animated ring) + SVProgressHUDAnimationTypeNative // iOS native UIActivityIndicatorView +}; + +typedef void (^SVProgressHUDShowCompletion)(void); +typedef void (^SVProgressHUDDismissCompletion)(void); + +@interface SVProgressHUD : UIView + +#pragma mark - Customization + +@property (assign, nonatomic) SVProgressHUDStyle defaultStyle UI_APPEARANCE_SELECTOR; // default is SVProgressHUDStyleLight +@property (assign, nonatomic) SVProgressHUDMaskType defaultMaskType UI_APPEARANCE_SELECTOR; // default is SVProgressHUDMaskTypeNone +@property (assign, nonatomic) SVProgressHUDAnimationType defaultAnimationType UI_APPEARANCE_SELECTOR; // default is SVProgressHUDAnimationTypeFlat +@property (assign, nonatomic) CGSize minimumSize UI_APPEARANCE_SELECTOR; // default is CGSizeZero, can be used to avoid resizing for a larger message +@property (assign, nonatomic) CGFloat ringThickness UI_APPEARANCE_SELECTOR; // default is 2 pt +@property (assign, nonatomic) CGFloat ringRadius UI_APPEARANCE_SELECTOR; // default is 18 pt +@property (assign, nonatomic) CGFloat ringNoTextRadius UI_APPEARANCE_SELECTOR; // default is 24 pt +@property (assign, nonatomic) CGFloat cornerRadius UI_APPEARANCE_SELECTOR; // default is 14 pt +@property (strong, nonatomic) UIFont *font UI_APPEARANCE_SELECTOR; // default is [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline] +@property (strong, nonatomic) UIColor *backgroundColor UI_APPEARANCE_SELECTOR; // default is [UIColor whiteColor] +@property (strong, nonatomic) UIColor *foregroundColor UI_APPEARANCE_SELECTOR; // default is [UIColor blackColor] +@property (strong, nonatomic) UIColor *backgroundLayerColor UI_APPEARANCE_SELECTOR; // default is [UIColor colorWithWhite:0 alpha:0.4] +@property (strong, nonatomic) UIImage *infoImage UI_APPEARANCE_SELECTOR; // default is the bundled info image provided by Freepik +@property (strong, nonatomic) UIImage *successImage UI_APPEARANCE_SELECTOR; // default is the bundled success image provided by Freepik +@property (strong, nonatomic) UIImage *errorImage UI_APPEARANCE_SELECTOR; // default is the bundled error image provided by Freepik +@property (strong, nonatomic) UIView *viewForExtension UI_APPEARANCE_SELECTOR; // default is nil, only used if #define SV_APP_EXTENSIONS is set +@property (assign, nonatomic) NSTimeInterval minimumDismissTimeInterval; // default is 5.0 seconds + +@property (assign, nonatomic) UIOffset offsetFromCenter UI_APPEARANCE_SELECTOR; // default is 0, 0 + +@property (assign, nonatomic) NSTimeInterval fadeInAnimationDuration; // default is 0.15 +@property (assign, nonatomic) NSTimeInterval fadeOutAnimationDuration; // default is 0.15 + +@property (assign, nonatomic) UIWindowLevel maxSupportedWindowLevel; // default is UIWindowLevelNormal + ++ (void)setDefaultStyle:(SVProgressHUDStyle)style; // default is SVProgressHUDStyleLight ++ (void)setDefaultMaskType:(SVProgressHUDMaskType)maskType; // default is SVProgressHUDMaskTypeNone ++ (void)setDefaultAnimationType:(SVProgressHUDAnimationType)type; // default is SVProgressHUDAnimationTypeFlat ++ (void)setMinimumSize:(CGSize)minimumSize; // default is CGSizeZero, can be used to avoid resizing for a larger message ++ (void)setRingThickness:(CGFloat)ringThickness; // default is 2 pt ++ (void)setRingRadius:(CGFloat)radius; // default is 18 pt ++ (void)setRingNoTextRadius:(CGFloat)radius; // default is 24 pt ++ (void)setCornerRadius:(CGFloat)cornerRadius; // default is 14 pt ++ (void)setFont:(UIFont*)font; // default is [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline] ++ (void)setForegroundColor:(UIColor*)color; // default is [UIColor blackColor], only used for SVProgressHUDStyleCustom ++ (void)setBackgroundColor:(UIColor*)color; // default is [UIColor whiteColor], only used for SVProgressHUDStyleCustom ++ (void)setBackgroundLayerColor:(UIColor*)color; // default is [UIColor colorWithWhite:0 alpha:0.5], only used for SVProgressHUDMaskTypeBlack ++ (void)setInfoImage:(UIImage*)image; // default is the bundled info image provided by Freepik ++ (void)setSuccessImage:(UIImage*)image; // default is the bundled success image provided by Freepik ++ (void)setErrorImage:(UIImage*)image; // default is the bundled error image provided by Freepik ++ (void)setViewForExtension:(UIView*)view; // default is nil, only used if #define SV_APP_EXTENSIONS is set ++ (void)setMinimumDismissTimeInterval:(NSTimeInterval)interval; // default is 5.0 seconds ++ (void)setFadeInAnimationDuration:(NSTimeInterval)duration; // default is 0.15 seconds ++ (void)setFadeOutAnimationDuration:(NSTimeInterval)duration; // default is 0.15 seconds ++ (void)setMaxSupportedWindowLevel:(UIWindowLevel)windowLevel; // default is UIWindowLevelNormal + +#pragma mark - Show Methods + ++ (void)show; ++ (void)showWithMaskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use show and setDefaultMaskType: instead."))); ++ (void)showWithStatus:(NSString*)status; ++ (void)showWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showWithStatus: and setDefaultMaskType: instead."))); + ++ (void)showProgress:(float)progress; ++ (void)showProgress:(float)progress maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showProgress: and setDefaultMaskType: instead."))); ++ (void)showProgress:(float)progress status:(NSString*)status; ++ (void)showProgress:(float)progress status:(NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showProgress:status: and setDefaultMaskType: instead."))); + ++ (void)setStatus:(NSString*)status; // change the HUD loading status while it's showing + +// stops the activity indicator, shows a glyph + status, and dismisses the HUD a little bit later ++ (void)showInfoWithStatus:(NSString*)status; ++ (void)showInfoWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showInfoWithStatus: and setDefaultMaskType: instead."))); ++ (void)showSuccessWithStatus:(NSString*)status; ++ (void)showSuccessWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showSuccessWithStatus: and setDefaultMaskType: instead."))); ++ (void)showErrorWithStatus:(NSString*)status; ++ (void)showErrorWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showErrorWithStatus: and setDefaultMaskType: instead."))); + +// shows a image + status, use 28x28 white PNGs ++ (void)showImage:(UIImage*)image status:(NSString*)status; ++ (void)showImage:(UIImage*)image status:(NSString*)status maskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use showImage:status: and setDefaultMaskType: instead."))); + ++ (void)setOffsetFromCenter:(UIOffset)offset; ++ (void)resetOffsetFromCenter; + ++ (void)popActivity; // decrease activity count, if activity count == 0 the HUD is dismissed ++ (void)dismiss; ++ (void)dismissWithCompletion:(SVProgressHUDDismissCompletion)completion; ++ (void)dismissWithDelay:(NSTimeInterval)delay; ++ (void)dismissWithDelay:(NSTimeInterval)delay completion:(SVProgressHUDDismissCompletion)completion; + ++ (BOOL)isVisible; + ++ (NSTimeInterval)displayDurationForString:(NSString*)string; + +@end + diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.m new file mode 100755 index 00000000000..d42ec397e82 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVProgressHUD.m @@ -0,0 +1,1439 @@ +// +// SVProgressHUD.h +// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD +// +// Copyright (c) 2011-2016 Sam Vermette and contributors. All rights reserved. +// + +#if !__has_feature(objc_arc) +#error SVProgressHUD is ARC only. Either turn on ARC for the project or use -fobjc-arc flag +#endif + +#import "SVProgressHUD.h" +#import "SVIndefiniteAnimatedView.h" +#import "SVProgressAnimatedView.h" +#import "SVRadialGradientLayer.h" + +NSString * const SVProgressHUDDidReceiveTouchEventNotification = @"SVProgressHUDDidReceiveTouchEventNotification"; +NSString * const SVProgressHUDDidTouchDownInsideNotification = @"SVProgressHUDDidTouchDownInsideNotification"; +NSString * const SVProgressHUDWillDisappearNotification = @"SVProgressHUDWillDisappearNotification"; +NSString * const SVProgressHUDDidDisappearNotification = @"SVProgressHUDDidDisappearNotification"; +NSString * const SVProgressHUDWillAppearNotification = @"SVProgressHUDWillAppearNotification"; +NSString * const SVProgressHUDDidAppearNotification = @"SVProgressHUDDidAppearNotification"; + +NSString * const SVProgressHUDStatusUserInfoKey = @"SVProgressHUDStatusUserInfoKey"; + +static const CGFloat SVProgressHUDParallaxDepthPoints = 10; +static const CGFloat SVProgressHUDUndefinedProgress = -1; +static const CGFloat SVProgressHUDDefaultAnimationDuration = 0.15; + +@interface SVProgressHUD () + +@property (nonatomic, strong, readonly) NSTimer *fadeOutTimer; +@property (nonatomic, readonly, getter = isClear) BOOL clear; + +@property (nonatomic, strong) UIControl *overlayView; +@property (nonatomic, strong) UIView *hudView; + +@property (nonatomic, strong) UILabel *statusLabel; +@property (nonatomic, strong) UIImageView *imageView; +@property (nonatomic, strong) UIView *indefiniteAnimatedView; +@property (nonatomic, strong) SVProgressAnimatedView *ringView; +@property (nonatomic, strong) SVProgressAnimatedView *backgroundRingView; +@property (nonatomic, strong) CALayer *backgroundLayer; + +@property (nonatomic, readwrite) CGFloat progress; +@property (nonatomic, readwrite) NSUInteger activityCount; + +@property (nonatomic, readonly) CGFloat visibleKeyboardHeight; + +- (void)updateHUDFrame; +- (void)updateMask; +- (void)updateBlurBounds; +#if TARGET_OS_IOS +- (void)updateMotionEffectForOrientation:(UIInterfaceOrientation)orientation; +#endif +- (void)updateMotionEffectForXMotionEffectType:(UIInterpolatingMotionEffectType)xMotionEffectType yMotionEffectType:(UIInterpolatingMotionEffectType)yMotionEffectType; +- (void)updateViewHierarchy; + +- (void)setStatus:(NSString*)status; +- (void)setFadeOutTimer:(NSTimer*)timer; + +- (void)registerNotifications; +- (NSDictionary*)notificationUserInfo; + +- (void)positionHUD:(NSNotification*)notification; +- (void)moveToPoint:(CGPoint)newCenter rotateAngle:(CGFloat)angle; + +- (void)overlayViewDidReceiveTouchEvent:(id)sender forEvent:(UIEvent*)event; + +- (void)showProgress:(float)progress status:(NSString*)status; +- (void)showImage:(UIImage*)image status:(NSString*)status duration:(NSTimeInterval)duration; +- (void)showStatus:(NSString*)status; + +- (void)dismiss; +- (void)dismissWithDelay:(NSTimeInterval)delay completion:(SVProgressHUDDismissCompletion)completion; + +- (UIView*)indefiniteAnimatedView; +- (SVProgressAnimatedView*)ringView; +- (SVProgressAnimatedView*)backgroundRingView; + +- (void)cancelRingLayerAnimation; +- (void)cancelIndefiniteAnimatedViewAnimation; + +- (UIColor*)foregroundColorForStyle; +- (UIColor*)backgroundColorForStyle; +- (UIImage*)image:(UIImage*)image withTintColor:(UIColor*)color; + +@end + + +@implementation SVProgressHUD { + BOOL _isInitializing; +} + ++ (SVProgressHUD*)sharedView { + static dispatch_once_t once; + + static SVProgressHUD *sharedView; +#if !defined(SV_APP_EXTENSIONS) + dispatch_once(&once, ^{ sharedView = [[self alloc] initWithFrame:[[[UIApplication sharedApplication] delegate] window].bounds]; }); +#else + dispatch_once(&once, ^{ sharedView = [[self alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; }); +#endif + return sharedView; +} + + +#pragma mark - Setters + ++ (void)setStatus:(NSString*)status { + [[self sharedView] setStatus:status]; +} + ++ (void)setDefaultStyle:(SVProgressHUDStyle)style { + [self sharedView].defaultStyle = style; +} + ++ (void)setDefaultMaskType:(SVProgressHUDMaskType)maskType { + [self sharedView].defaultMaskType = maskType; +} + ++ (void)setDefaultAnimationType:(SVProgressHUDAnimationType)type { + [self sharedView].defaultAnimationType = type; +} + ++ (void)setMinimumSize:(CGSize)minimumSize { + [self sharedView].minimumSize = minimumSize; +} + ++ (void)setRingThickness:(CGFloat)ringThickness { + [self sharedView].ringThickness = ringThickness; +} + ++ (void)setRingRadius:(CGFloat)radius { + [self sharedView].ringRadius = radius; +} + ++ (void)setRingNoTextRadius:(CGFloat)radius { + [self sharedView].ringNoTextRadius = radius; +} + ++ (void)setCornerRadius:(CGFloat)cornerRadius { + [self sharedView].cornerRadius = cornerRadius; +} + ++ (void)setFont:(UIFont*)font { + [self sharedView].font = font; +} + ++ (void)setForegroundColor:(UIColor*)color { + [self sharedView].foregroundColor = color; +} + ++ (void)setBackgroundColor:(UIColor*)color { + [self sharedView].backgroundColor = color; +} + ++ (void)setBackgroundLayerColor:(UIColor*)color { + [self sharedView].backgroundLayerColor = color; +} + ++ (void)setInfoImage:(UIImage*)image { + [self sharedView].infoImage = image; +} + ++ (void)setSuccessImage:(UIImage*)image { + [self sharedView].successImage = image; +} + ++ (void)setErrorImage:(UIImage*)image { + [self sharedView].errorImage = image; +} + ++ (void)setViewForExtension:(UIView*)view { + [self sharedView].viewForExtension = view; +} + ++ (void)setMinimumDismissTimeInterval:(NSTimeInterval)interval { + [self sharedView].minimumDismissTimeInterval = interval; +} + ++ (void)setFadeInAnimationDuration:(NSTimeInterval)duration { + [self sharedView].fadeInAnimationDuration = duration; +} + ++ (void)setFadeOutAnimationDuration:(NSTimeInterval)duration { + [self sharedView].fadeOutAnimationDuration = duration; +} + ++ (void)setMaxSupportedWindowLevel:(UIWindowLevel)windowLevel { + [self sharedView].maxSupportedWindowLevel = windowLevel; +} + +#pragma mark - Show Methods + ++ (void)show { + [self showWithStatus:nil]; +} + ++ (void)showWithMaskType:(SVProgressHUDMaskType)maskType { + SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; + [self setDefaultMaskType:maskType]; + [self show]; + [self setDefaultMaskType:existingMaskType]; +} + ++ (void)showWithStatus:(NSString*)status { + [self sharedView]; + [self showProgress:SVProgressHUDUndefinedProgress status:status]; +} + ++ (void)showWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { + SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; + [self setDefaultMaskType:maskType]; + [self showWithStatus:status]; + [self setDefaultMaskType:existingMaskType]; +} + ++ (void)showProgress:(float)progress { + [self showProgress:progress status:nil]; +} + ++ (void)showProgress:(float)progress maskType:(SVProgressHUDMaskType)maskType { + SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; + [self setDefaultMaskType:maskType]; + [self showProgress:progress]; + [self setDefaultMaskType:existingMaskType]; +} + ++ (void)showProgress:(float)progress status:(NSString*)status { + [[self sharedView] showProgress:progress status:status]; +} + ++ (void)showProgress:(float)progress status:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { + SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; + [self setDefaultMaskType:maskType]; + [self showProgress:progress status:status]; + [self setDefaultMaskType:existingMaskType]; +} + + +#pragma mark - Show, then automatically dismiss methods + ++ (void)showInfoWithStatus:(NSString*)status { + [self showImage:[self sharedView].infoImage status:status]; +} + ++ (void)showInfoWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { + SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; + [self setDefaultMaskType:maskType]; + [self showInfoWithStatus:status]; + [self setDefaultMaskType:existingMaskType]; +} + ++ (void)showSuccessWithStatus:(NSString*)status { + [self showImage:[self sharedView].successImage status:status]; +} + ++ (void)showSuccessWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { + SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; + [self setDefaultMaskType:maskType]; + [self showSuccessWithStatus:status]; + [self setDefaultMaskType:existingMaskType]; +} + ++ (void)showErrorWithStatus:(NSString*)status { + [self showImage:[self sharedView].errorImage status:status]; +} + ++ (void)showErrorWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { + SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; + [self setDefaultMaskType:maskType]; + [self showErrorWithStatus:status]; + [self setDefaultMaskType:existingMaskType]; +} + ++ (void)showImage:(UIImage*)image status:(NSString*)status { + NSTimeInterval displayInterval = [self displayDurationForString:status]; + [[self sharedView] showImage:image status:status duration:displayInterval]; +} + ++ (void)showImage:(UIImage*)image status:(NSString*)status maskType:(SVProgressHUDMaskType)maskType { + SVProgressHUDMaskType existingMaskType = [self sharedView].defaultMaskType; + [self setDefaultMaskType:maskType]; + [self showImage:image status:status]; + [self setDefaultMaskType:existingMaskType]; +} + + +#pragma mark - Dismiss Methods + ++ (void)popActivity { + if([self sharedView].activityCount > 0) { + [self sharedView].activityCount--; + } + if([self sharedView].activityCount == 0) { + [[self sharedView] dismiss]; + } +} + ++ (void)dismiss { + [self dismissWithDelay:0.0 completion:nil]; +} + ++ (void)dismissWithCompletion:(SVProgressHUDDismissCompletion)completion { + [self dismissWithDelay:0.0 completion:completion]; +} + ++ (void)dismissWithDelay:(NSTimeInterval)delay { + [self dismissWithDelay:delay completion:nil]; +} + ++ (void)dismissWithDelay:(NSTimeInterval)delay completion:(SVProgressHUDDismissCompletion)completion { + [[self sharedView] dismissWithDelay:delay completion:completion]; +} + + +#pragma mark - Offset + ++ (void)setOffsetFromCenter:(UIOffset)offset { + [self sharedView].offsetFromCenter = offset; +} + ++ (void)resetOffsetFromCenter { + [self setOffsetFromCenter:UIOffsetZero]; +} + + +#pragma mark - Instance Methods + +- (instancetype)initWithFrame:(CGRect)frame { + if((self = [super initWithFrame:frame])) { + _isInitializing = YES; + + self.userInteractionEnabled = NO; + _backgroundColor = [UIColor clearColor]; + _foregroundColor = [UIColor blackColor]; + _backgroundLayerColor = [UIColor colorWithWhite:0 alpha:0.4]; + + self.alpha = 0.0f; + self.activityCount = 0; + + // Set default values + _defaultMaskType = SVProgressHUDMaskTypeNone; + _defaultStyle = SVProgressHUDStyleLight; + _defaultAnimationType = SVProgressHUDAnimationTypeFlat; + + if ([UIFont respondsToSelector:@selector(preferredFontForTextStyle:)]) { + _font = [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]; + } else { + _font = [UIFont systemFontOfSize:14.0f]; + } + + NSBundle *bundle = [NSBundle bundleForClass:[SVProgressHUD class]]; + NSURL *url = [bundle URLForResource:@"SVProgressHUD" withExtension:@"bundle"]; + NSBundle *imageBundle = [NSBundle bundleWithURL:url]; + + UIImage* infoImage = [UIImage imageWithContentsOfFile:[imageBundle pathForResource:@"info" ofType:@"png"]]; + UIImage* successImage = [UIImage imageWithContentsOfFile:[imageBundle pathForResource:@"success" ofType:@"png"]]; + UIImage* errorImage = [UIImage imageWithContentsOfFile:[imageBundle pathForResource:@"error" ofType:@"png"]]; + + if ([[UIImage class] instancesRespondToSelector:@selector(imageWithRenderingMode:)]) { + _infoImage = [infoImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + _successImage = [successImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + _errorImage = [errorImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + } else { + _infoImage = infoImage; + _successImage = successImage; + _errorImage = errorImage; + } + + _ringThickness = 2.0f; + _ringRadius = 18.0f; + _ringNoTextRadius = 24.0f; + + _cornerRadius = 14.0f; + + _minimumDismissTimeInterval = 5.0; + + _fadeInAnimationDuration = SVProgressHUDDefaultAnimationDuration; + _fadeOutAnimationDuration = SVProgressHUDDefaultAnimationDuration; + + _maxSupportedWindowLevel = UIWindowLevelNormal; + + // Accessibility support + self.accessibilityIdentifier = @"SVProgressHUD"; + self.accessibilityLabel = @"SVProgressHUD"; + self.isAccessibilityElement = YES; + + _isInitializing = NO; + } + return self; +} + +- (void)updateHUDFrame { + // For the beginning use default values, these + // might get update if string is too large etc. + CGFloat hudWidth = 100.0f; + CGFloat hudHeight = 100.0f; + CGFloat stringHeightBuffer = 20.0f; + CGFloat stringAndContentHeightBuffer = 80.0f; + CGRect labelRect = CGRectZero; + + // Check if an image or progress ring is displayed + BOOL imageUsed = (self.imageView.image) && !(self.imageView.hidden); + BOOL progressUsed = self.imageView.hidden; + + // Calculate size of string and update HUD size + NSString *string = self.statusLabel.text; + if(string) { + CGSize constraintSize = CGSizeMake(200.0f, 300.0f); + CGRect stringRect; + if([string respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) { + stringRect = [string boundingRectWithSize:constraintSize + options:(NSStringDrawingOptions)(NSStringDrawingUsesFontLeading|NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesLineFragmentOrigin) + attributes:@{NSFontAttributeName: self.statusLabel.font} + context:NULL]; + } else { + CGSize stringSize; + if([string respondsToSelector:@selector(sizeWithAttributes:)]) { + stringSize = [string sizeWithAttributes:@{NSFontAttributeName:[UIFont fontWithName:self.statusLabel.font.fontName size:self.statusLabel.font.pointSize]}]; + } else { +#if TARGET_OS_IOS +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" + stringSize = [string sizeWithFont:self.statusLabel.font constrainedToSize:CGSizeMake(200.0f, 300.0f)]; +#pragma clang diagnostic pop +#endif + } + stringRect = CGRectMake(0.0f, 0.0f, stringSize.width, stringSize.height); + } + + CGFloat stringWidth = stringRect.size.width; + CGFloat stringHeight = ceilf(CGRectGetHeight(stringRect)); + + if(imageUsed || progressUsed) { + hudHeight = stringAndContentHeightBuffer + stringHeight; + } else { + hudHeight = stringHeightBuffer + stringHeight; + } + if(stringWidth > hudWidth) { + hudWidth = ceilf(stringWidth/2)*2; + } + CGFloat labelRectY = (imageUsed || progressUsed) ? 68.0f : 9.0f; + if(hudHeight > 100.0f) { + labelRect = CGRectMake(12.0f, labelRectY, hudWidth, stringHeight); + hudWidth += 24.0f; + } else { + hudWidth += 24.0f; + labelRect = CGRectMake(0.0f, labelRectY, hudWidth, stringHeight); + } + } + + // Update values on subviews + self.hudView.bounds = CGRectMake(0.0f, 0.0f, MAX(self.minimumSize.width, hudWidth), MAX(self.minimumSize.height, hudHeight)); + labelRect.size.width += MAX(0, self.minimumSize.width - hudWidth); + [self updateBlurBounds]; + + if(string) { + self.imageView.center = CGPointMake(CGRectGetWidth(self.hudView.bounds)/2, 36.0f); + } else { + self.imageView.center = CGPointMake(CGRectGetWidth(self.hudView.bounds)/2, CGRectGetHeight(self.hudView.bounds)/2); + } + + self.statusLabel.hidden = NO; + self.statusLabel.frame = labelRect; + + // Animate value update + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + + if(string) { + if(self.defaultAnimationType == SVProgressHUDAnimationTypeFlat) { + SVIndefiniteAnimatedView *indefiniteAnimationView = (SVIndefiniteAnimatedView*)self.indefiniteAnimatedView; + indefiniteAnimationView.radius = self.ringRadius; + [indefiniteAnimationView sizeToFit]; + } + + CGPoint center = CGPointMake((CGRectGetWidth(self.hudView.bounds)/2), 36.0f); + self.indefiniteAnimatedView.center = center; + + if(self.progress != SVProgressHUDUndefinedProgress) { + self.backgroundRingView.center = self.ringView.center = CGPointMake((CGRectGetWidth(self.hudView.bounds)/2), 36.0f); + } + } else { + if(self.defaultAnimationType == SVProgressHUDAnimationTypeFlat) { + SVIndefiniteAnimatedView *indefiniteAnimationView = (SVIndefiniteAnimatedView*)self.indefiniteAnimatedView; + indefiniteAnimationView.radius = self.ringNoTextRadius; + [indefiniteAnimationView sizeToFit]; + } + + CGPoint center = CGPointMake((CGRectGetWidth(self.hudView.bounds)/2), CGRectGetHeight(self.hudView.bounds)/2); + self.indefiniteAnimatedView.center = center; + + if(self.progress != SVProgressHUDUndefinedProgress) { + self.backgroundRingView.center = self.ringView.center = CGPointMake((CGRectGetWidth(self.hudView.bounds)/2), CGRectGetHeight(self.hudView.bounds)/2); + } + } + + [CATransaction commit]; +} + +- (void)updateMask { + if(self.backgroundLayer) { + [self.backgroundLayer removeFromSuperlayer]; + self.backgroundLayer = nil; + } + switch (self.defaultMaskType) { + case SVProgressHUDMaskTypeCustom: + case SVProgressHUDMaskTypeBlack:{ + + self.backgroundLayer = [CALayer layer]; + self.backgroundLayer.frame = self.bounds; + self.backgroundLayer.backgroundColor = self.defaultMaskType == SVProgressHUDMaskTypeCustom ? self.backgroundLayerColor.CGColor : [UIColor colorWithWhite:0 alpha:0.4].CGColor; + [self.backgroundLayer setNeedsDisplay]; + + [self.layer insertSublayer:self.backgroundLayer atIndex:0]; + break; + } + + case SVProgressHUDMaskTypeGradient:{ + SVRadialGradientLayer *layer = [SVRadialGradientLayer layer]; + self.backgroundLayer = layer; + self.backgroundLayer.frame = self.bounds; + CGPoint gradientCenter = self.center; + gradientCenter.y = (self.bounds.size.height - self.visibleKeyboardHeight)/2; + layer.gradientCenter = gradientCenter; + [self.backgroundLayer setNeedsDisplay]; + + [self.layer insertSublayer:self.backgroundLayer atIndex:0]; + break; + } + default: + break; + } +} + +- (void)updateBlurBounds { +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + if(NSClassFromString(@"UIBlurEffect") && self.defaultStyle != SVProgressHUDStyleCustom) { + // Remove any old instances of UIVisualEffectViews + for (UIView *subview in self.hudView.subviews) { + if([subview isKindOfClass:[UIVisualEffectView class]]) { + [subview removeFromSuperview]; + } + } + + if(self.backgroundColorForStyle != [UIColor clearColor]) { + // Create blur effect + UIBlurEffectStyle blurEffectStyle = self.defaultStyle == SVProgressHUDStyleDark ? UIBlurEffectStyleDark : UIBlurEffectStyleLight; + UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:blurEffectStyle]; + UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; + blurEffectView.autoresizingMask = self.hudView.autoresizingMask; + blurEffectView.frame = self.hudView.bounds; + + // Add vibrancy to the blur effect to make it more vivid + UIVibrancyEffect *vibrancyEffect = [UIVibrancyEffect effectForBlurEffect:blurEffect]; + UIVisualEffectView *vibrancyEffectView = [[UIVisualEffectView alloc] initWithEffect:vibrancyEffect]; + vibrancyEffectView.autoresizingMask = blurEffectView.autoresizingMask; + vibrancyEffectView.bounds = blurEffectView.bounds; + [blurEffectView.contentView addSubview:vibrancyEffectView]; + + [self.hudView insertSubview:blurEffectView atIndex:0]; + } + } +#endif +} + +#if TARGET_OS_IOS +- (void)updateMotionEffectForOrientation:(UIInterfaceOrientation)orientation { + UIInterpolatingMotionEffectType xMotionEffectType = UIInterfaceOrientationIsPortrait(orientation) ? UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis : UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis; + UIInterpolatingMotionEffectType yMotionEffectType = UIInterfaceOrientationIsPortrait(orientation) ? UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis : UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis; + [self updateMotionEffectForXMotionEffectType:xMotionEffectType yMotionEffectType:yMotionEffectType]; +} +#endif + +- (void)updateMotionEffectForXMotionEffectType:(UIInterpolatingMotionEffectType)xMotionEffectType yMotionEffectType:(UIInterpolatingMotionEffectType)yMotionEffectType { + if([self.hudView respondsToSelector:@selector(addMotionEffect:)]) { + UIInterpolatingMotionEffect *effectX = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:xMotionEffectType]; + effectX.minimumRelativeValue = @(-SVProgressHUDParallaxDepthPoints); + effectX.maximumRelativeValue = @(SVProgressHUDParallaxDepthPoints); + + UIInterpolatingMotionEffect *effectY = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:yMotionEffectType]; + effectY.minimumRelativeValue = @(-SVProgressHUDParallaxDepthPoints); + effectY.maximumRelativeValue = @(SVProgressHUDParallaxDepthPoints); + + UIMotionEffectGroup *effectGroup = [[UIMotionEffectGroup alloc] init]; + effectGroup.motionEffects = @[effectX, effectY]; + + // Clear old motion effect, then add new motion effects + self.hudView.motionEffects = @[]; + [self.hudView addMotionEffect:effectGroup]; + } +} + +- (void)updateViewHierarchy { + // Add the overlay (e.g. black, gradient) to the application window if necessary + if(!self.overlayView.superview) { +#if !defined(SV_APP_EXTENSIONS) + // Default case: iterate over UIApplication windows + NSEnumerator *frontToBackWindows = [UIApplication.sharedApplication.windows reverseObjectEnumerator]; + for (UIWindow *window in frontToBackWindows) { + BOOL windowOnMainScreen = window.screen == UIScreen.mainScreen; + BOOL windowIsVisible = !window.hidden && window.alpha > 0; + BOOL windowLevelSupported = (window.windowLevel >= UIWindowLevelNormal && window.windowLevel <= self.maxSupportedWindowLevel); + + if(windowOnMainScreen && windowIsVisible && windowLevelSupported) { + [window addSubview:self.overlayView]; + break; + } + } +#else + // If SVProgressHUD ist used inside an app extension add it to the given view + if(self.viewForExtension) { + [self.viewForExtension addSubview:self.overlayView]; + } +#endif + } else { + // The HUD is already on screen, but maybot not in front. Therefore + // ensure that overlay will be on top of rootViewController (which may + // be changed during runtime). + [self.overlayView.superview bringSubviewToFront:self.overlayView]; + } + + + // Add self to the overlay view + if(!self.superview){ + [self.overlayView addSubview:self]; + } + if(!self.hudView.superview) { + [self addSubview:self.hudView]; + } +} + +- (void)setStatus:(NSString*)status { + self.statusLabel.text = status; + [self updateHUDFrame]; +} + +- (void)setFadeOutTimer:(NSTimer*)timer { + if(_fadeOutTimer) { + [_fadeOutTimer invalidate], _fadeOutTimer = nil; + } + if(timer) { + _fadeOutTimer = timer; + } +} + + +#pragma mark - Notifications and their handling + +- (void)registerNotifications { +#if TARGET_OS_IOS + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(positionHUD:) + name:UIApplicationDidChangeStatusBarOrientationNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(positionHUD:) + name:UIKeyboardWillHideNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(positionHUD:) + name:UIKeyboardDidHideNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(positionHUD:) + name:UIKeyboardWillShowNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(positionHUD:) + name:UIKeyboardDidShowNotification + object:nil]; +#endif + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(positionHUD:) + name:UIApplicationDidBecomeActiveNotification + object:nil]; +} + +- (NSDictionary*)notificationUserInfo{ + return (self.statusLabel.text ? @{SVProgressHUDStatusUserInfoKey : self.statusLabel.text} : nil); +} + +- (void)positionHUD:(NSNotification*)notification { + CGFloat keyboardHeight = 0.0f; + double animationDuration = 0.0; + +#if !defined(SV_APP_EXTENSIONS) && TARGET_OS_IOS + self.frame = [[[UIApplication sharedApplication] delegate] window].bounds; + UIInterfaceOrientation orientation = UIApplication.sharedApplication.statusBarOrientation; +#elif !defined(SV_APP_EXTENSIONS) + self.frame = [UIApplication sharedApplication].keyWindow.bounds; +#else + if (self.viewForExtension) { + self.frame = self.viewForExtension.frame; + } else { + self.frame = UIScreen.mainScreen.bounds; + } + UIInterfaceOrientation orientation = CGRectGetWidth(self.frame) > CGRectGetHeight(self.frame) ? UIInterfaceOrientationLandscapeLeft : UIInterfaceOrientationPortrait; +#endif + + // no transforms applied to window in iOS 8, but only if compiled with iOS 8 sdk as base sdk, otherwise system supports old rotation logic. + BOOL ignoreOrientation = NO; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + if([[NSProcessInfo processInfo] respondsToSelector:@selector(operatingSystemVersion)]) { + ignoreOrientation = YES; + } +#endif + +#if TARGET_OS_IOS + // Get keyboardHeight in regards to current state + if(notification) { + NSDictionary* keyboardInfo = [notification userInfo]; + CGRect keyboardFrame = [keyboardInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue]; + animationDuration = [keyboardInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; + + if(notification.name == UIKeyboardWillShowNotification || notification.name == UIKeyboardDidShowNotification) { + keyboardHeight = CGRectGetWidth(keyboardFrame); + + if(ignoreOrientation || UIInterfaceOrientationIsPortrait(orientation)) { + keyboardHeight = CGRectGetHeight(keyboardFrame); + } + } + } else { + keyboardHeight = self.visibleKeyboardHeight; + } +#endif + + // Get the currently active frame of the display (depends on orientation) + CGRect orientationFrame = self.bounds; + +#if !defined(SV_APP_EXTENSIONS) && TARGET_OS_IOS + CGRect statusBarFrame = UIApplication.sharedApplication.statusBarFrame; +#else + CGRect statusBarFrame = CGRectZero; +#endif + +#if TARGET_OS_IOS + if(!ignoreOrientation && UIInterfaceOrientationIsLandscape(orientation)) { + float temp = CGRectGetWidth(orientationFrame); + orientationFrame.size.width = CGRectGetHeight(orientationFrame); + orientationFrame.size.height = temp; + + temp = CGRectGetWidth(statusBarFrame); + statusBarFrame.size.width = CGRectGetHeight(statusBarFrame); + statusBarFrame.size.height = temp; + } + + // Update the motion effects in regards to orientation + [self updateMotionEffectForOrientation:orientation]; +#else + [self updateMotionEffectForXMotionEffectType:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis yMotionEffectType:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; +#endif + + // Calculate available height for display + CGFloat activeHeight = CGRectGetHeight(orientationFrame); + if(keyboardHeight > 0) { + activeHeight += CGRectGetHeight(statusBarFrame)*2; + } + activeHeight -= keyboardHeight; + + CGFloat posX = CGRectGetWidth(orientationFrame)/2.0f; + CGFloat posY = floorf(activeHeight*0.45f); + + CGFloat rotateAngle = 0.0; + CGPoint newCenter = CGPointMake(posX, posY); + + // Update posX and posY in regards to orientation +#if TARGET_OS_IOS + if(!ignoreOrientation) { + switch (orientation) { + case UIInterfaceOrientationPortraitUpsideDown: + rotateAngle = (CGFloat) M_PI; + newCenter = CGPointMake(posX, CGRectGetHeight(orientationFrame)-posY); + break; + case UIInterfaceOrientationLandscapeLeft: + rotateAngle = (CGFloat) (-M_PI/2.0f); + newCenter = CGPointMake(posY, posX); + break; + case UIInterfaceOrientationLandscapeRight: + rotateAngle = (CGFloat) (M_PI/2.0f); + newCenter = CGPointMake(CGRectGetHeight(orientationFrame)-posY, posX); + break; + default: // Same as UIInterfaceOrientationPortrait + rotateAngle = 0.0f; + newCenter = CGPointMake(posX, posY); + break; + } + } +#endif + + if(notification) { + // Animate update if notification was present + __weak SVProgressHUD *weakSelf = self; + [UIView animateWithDuration:animationDuration + delay:0 + options:UIViewAnimationOptionAllowUserInteraction + animations:^{ + __strong SVProgressHUD *strongSelf = weakSelf; + if(strongSelf) { + [strongSelf moveToPoint:newCenter rotateAngle:rotateAngle]; + [strongSelf.hudView setNeedsDisplay]; + } + } completion:NULL]; + } else { + [self moveToPoint:newCenter rotateAngle:rotateAngle]; + [self.hudView setNeedsDisplay]; + } + + [self updateMask]; +} + +- (void)moveToPoint:(CGPoint)newCenter rotateAngle:(CGFloat)angle { + self.hudView.transform = CGAffineTransformMakeRotation(angle); + self.hudView.center = CGPointMake(newCenter.x + self.offsetFromCenter.horizontal, newCenter.y + self.offsetFromCenter.vertical); +} + + +#pragma mark - Event handling + +- (void)overlayViewDidReceiveTouchEvent:(id)sender forEvent:(UIEvent*)event { + [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidReceiveTouchEventNotification + object:self + userInfo:[self notificationUserInfo]]; + + UITouch *touch = event.allTouches.anyObject; + CGPoint touchLocation = [touch locationInView:self]; + + if(CGRectContainsPoint(self.hudView.frame, touchLocation)) { + [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidTouchDownInsideNotification + object:self + userInfo:[self notificationUserInfo]]; + } +} + + +#pragma mark - Master show/dismiss methods + +- (void)showProgress:(float)progress status:(NSString*)status { + __weak SVProgressHUD *weakSelf = self; + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + __strong SVProgressHUD *strongSelf = weakSelf; + if(strongSelf){ + // Update / Check view hierarchy to ensure the HUD is visible + [strongSelf updateViewHierarchy]; + + // Reset imageView and fadeout timer if an image is currently displayed + strongSelf.imageView.hidden = YES; + strongSelf.imageView.image = nil; + + if(strongSelf.fadeOutTimer) { + strongSelf.activityCount = 0; + } + strongSelf.fadeOutTimer = nil; + + // Update text and set progress to the given value + strongSelf.statusLabel.text = status; + strongSelf.progress = progress; + + // Choose the "right" indicator depending on the progress + if(progress >= 0) { + // Cancel the indefiniteAnimatedView, then show the ringLayer + [strongSelf cancelIndefiniteAnimatedViewAnimation]; + + // Add ring to HUD and set progress + [strongSelf.hudView addSubview:strongSelf.ringView]; + [strongSelf.hudView addSubview:strongSelf.backgroundRingView]; + strongSelf.ringView.strokeEnd = progress; + + // Update the activity count + if(progress == 0) { + strongSelf.activityCount++; + } + } else { + // Cancel the ringLayer animation, then show the indefiniteAnimatedView + [strongSelf cancelRingLayerAnimation]; + + // Add indefiniteAnimatedView to HUD + [strongSelf.hudView addSubview:strongSelf.indefiniteAnimatedView]; + if([strongSelf.indefiniteAnimatedView respondsToSelector:@selector(startAnimating)]) { + [(id)strongSelf.indefiniteAnimatedView startAnimating]; + } + + // Update the activity count + strongSelf.activityCount++; + } + + // Show + [strongSelf showStatus:status]; + } + }]; +} + +- (void)showImage:(UIImage*)image status:(NSString*)status duration:(NSTimeInterval)duration { + __weak SVProgressHUD *weakSelf = self; + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + __strong SVProgressHUD *strongSelf = weakSelf; + if(strongSelf){ + // Update / Check view hierarchy to ensure the HUD is visible + [strongSelf updateViewHierarchy]; + + // Reset progress and cancel any running animation + strongSelf.progress = SVProgressHUDUndefinedProgress; + [strongSelf cancelRingLayerAnimation]; + [strongSelf cancelIndefiniteAnimatedViewAnimation]; + + // Update imageView + UIColor *tintColor = strongSelf.foregroundColorForStyle; + UIImage *tintedImage = image; + if([strongSelf.imageView respondsToSelector:@selector(setTintColor:)]) { + if (tintedImage.renderingMode != UIImageRenderingModeAlwaysTemplate) { + tintedImage = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + } + strongSelf.imageView.tintColor = tintColor; + } else { + tintedImage = [strongSelf image:image withTintColor:tintColor]; + } + strongSelf.imageView.image = tintedImage; + strongSelf.imageView.hidden = NO; + + // Update text + strongSelf.statusLabel.text = status; + + // Show + [strongSelf showStatus:status]; + + // An image will dismissed automatically. Therefore we start a timer + // which then will call dismiss after the predefined duration + strongSelf.fadeOutTimer = [NSTimer timerWithTimeInterval:duration target:strongSelf selector:@selector(dismiss) userInfo:nil repeats:NO]; + [[NSRunLoop mainRunLoop] addTimer:strongSelf.fadeOutTimer forMode:NSRunLoopCommonModes]; + } + }]; +} + +- (void)showStatus:(NSString*)status { + // Update the HUDs frame to the new content and position HUD + [self updateHUDFrame]; + [self positionHUD:nil]; + + // Update accessibility as well as user interaction + if(self.defaultMaskType != SVProgressHUDMaskTypeNone) { + self.overlayView.userInteractionEnabled = YES; + self.accessibilityLabel = status; + self.isAccessibilityElement = YES; + } else { + self.overlayView.userInteractionEnabled = NO; + self.hudView.accessibilityLabel = status; + self.hudView.isAccessibilityElement = YES; + } + + // Show overlay + self.overlayView.backgroundColor = [UIColor clearColor]; + + // Show if not already visible (depending on alpha) + if(self.alpha != 1.0f || self.hudView.alpha != 1.0f) { + // Post notification to inform user + [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDWillAppearNotification + object:self + userInfo:[self notificationUserInfo]]; + + // Zoom HUD a little to make a nice appear / pop up animation + self.hudView.transform = CGAffineTransformScale(self.hudView.transform, 1.3, 1.3); + + // Set initial values to handle iOS 7 (and above) UIToolbar which not answers well to hierarchy opacity change + self.alpha = 0.0f; + self.hudView.alpha = 0.0f; + + // Define blocks + __weak SVProgressHUD *weakSelf = self; + + __block void (^animationsBlock)(void) = ^{ + __strong SVProgressHUD *strongSelf = weakSelf; + if(strongSelf) { + // Shrink HUD to finish pop up animation + strongSelf.hudView.transform = CGAffineTransformScale(strongSelf.hudView.transform, 1/1.3f, 1/1.3f); + strongSelf.alpha = 1.0f; + strongSelf.hudView.alpha = 1.0f; + } + }; + + __block void (^completionBlock)(void) = ^{ + __strong SVProgressHUD *strongSelf = weakSelf; + if(strongSelf) { + // Check if we really achieved to show the HUD (<=> alpha values are applied) + // and the change of these values has not been cancelled in between + // e.g. due to a dismissmal + if(strongSelf.alpha == 1.0f && strongSelf.hudView.alpha == 1.0f){ + // Register observer <=> we now have to handle orientation changes etc. + [strongSelf registerNotifications]; + + // Post notification to inform user + [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidAppearNotification + object:strongSelf + userInfo:[strongSelf notificationUserInfo]]; + } + } + + // Update accessibility + UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); + UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, status); + }; + + if (self.fadeInAnimationDuration > 0) { + // Animate appearance + [UIView animateWithDuration:self.fadeInAnimationDuration + delay:0 + options:(UIViewAnimationOptions) (UIViewAnimationOptionAllowUserInteraction | UIViewAnimationCurveEaseOut | UIViewAnimationOptionBeginFromCurrentState) + animations:^{ + animationsBlock(); + } completion:^(BOOL finished) { + completionBlock(); + }]; + } else { + animationsBlock(); + completionBlock(); + } + + // Inform iOS to redraw the view hierarchy + [self setNeedsDisplay]; + } +} + +- (void)dismiss { + [self dismissWithDelay:0.0 completion:nil]; +} + +- (void)dismissWithDelay:(NSTimeInterval)delay completion:(SVProgressHUDDismissCompletion)completion { + __weak SVProgressHUD *weakSelf = self; + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + __strong SVProgressHUD *strongSelf = weakSelf; + if(strongSelf){ + // Post notification to inform user + [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDWillDisappearNotification + object:nil + userInfo:[strongSelf notificationUserInfo]]; + + // Reset activity count + strongSelf.activityCount = 0; + + // Define blocks + __block void (^animationsBlock)(void) = ^{ + strongSelf.hudView.transform = CGAffineTransformScale(strongSelf.hudView.transform, 1/1.3f, 1/1.3f); + strongSelf.alpha = 0.0f; + strongSelf.hudView.alpha = 0.0f; + }; + + __block void (^completionBlock)(void) = ^{ + // Check if we really achieved to dismiss the HUD (<=> alpha values are applied) + // and the change of these values has not been cancelled in between + // e.g. due to a new show + if(strongSelf.alpha == 0.0f && strongSelf.hudView.alpha == 0.0f){ + // Clean up view hierarchy (overlays) + [strongSelf.overlayView removeFromSuperview]; + [strongSelf.hudView removeFromSuperview]; + [strongSelf removeFromSuperview]; + + // Reset progress and cancel any running animation + strongSelf.progress = SVProgressHUDUndefinedProgress; + [strongSelf cancelRingLayerAnimation]; + [strongSelf cancelIndefiniteAnimatedViewAnimation]; + + // Remove observer <=> we do not have to handle orientation changes etc. + [[NSNotificationCenter defaultCenter] removeObserver:strongSelf]; + + // Post notification to inform user + [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidDisappearNotification + object:strongSelf + userInfo:[strongSelf notificationUserInfo]]; + + // Tell the rootViewController to update the StatusBar appearance +#if !defined(SV_APP_EXTENSIONS) && TARGET_OS_IOS + UIViewController *rootController = [[UIApplication sharedApplication] keyWindow].rootViewController; + if([rootController respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) { + [rootController setNeedsStatusBarAppearanceUpdate]; + } +#endif + // Update accessibility + UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); + + // Run an (optional) completionHandler + if (completion) { + completion(); + } + } + }; + + if (strongSelf.fadeOutAnimationDuration > 0) { + // Animate appearance + [UIView animateWithDuration:strongSelf.fadeOutAnimationDuration + delay:delay + options:(UIViewAnimationOptions) (UIViewAnimationOptionAllowUserInteraction | UIViewAnimationCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState) + animations:^{ + animationsBlock(); + } completion:^(BOOL finished) { + completionBlock(); + }]; + } else { + animationsBlock(); + completionBlock(); + } + + // Inform iOS to redraw the view hierarchy + [strongSelf setNeedsDisplay]; + } else if (completion) { + // Run an (optional) completionHandler + completion(); + } + }]; +} + + +#pragma mark - Ring progress animation + +- (UIView*)indefiniteAnimatedView { + // Get the correct spinner for defaultAnimationType + if(self.defaultAnimationType == SVProgressHUDAnimationTypeFlat){ + // Check if spinner exists and is an object of different class + if(_indefiniteAnimatedView && ![_indefiniteAnimatedView isKindOfClass:[SVIndefiniteAnimatedView class]]){ + [_indefiniteAnimatedView removeFromSuperview]; + _indefiniteAnimatedView = nil; + } + + if(!_indefiniteAnimatedView){ + _indefiniteAnimatedView = [[SVIndefiniteAnimatedView alloc] initWithFrame:CGRectZero]; + } + + // Update styling + SVIndefiniteAnimatedView *indefiniteAnimatedView = (SVIndefiniteAnimatedView*)_indefiniteAnimatedView; + indefiniteAnimatedView.strokeColor = self.foregroundColorForStyle; + indefiniteAnimatedView.strokeThickness = self.ringThickness; + indefiniteAnimatedView.radius = self.statusLabel.text ? self.ringRadius : self.ringNoTextRadius; + } else { + // Check if spinner exists and is an object of different class + if(_indefiniteAnimatedView && ![_indefiniteAnimatedView isKindOfClass:[UIActivityIndicatorView class]]){ + [_indefiniteAnimatedView removeFromSuperview]; + _indefiniteAnimatedView = nil; + } + + if(!_indefiniteAnimatedView){ + _indefiniteAnimatedView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; + } + + // Update styling + UIActivityIndicatorView *activityIndicatorView = (UIActivityIndicatorView*)_indefiniteAnimatedView; + activityIndicatorView.color = self.foregroundColorForStyle; + } + [_indefiniteAnimatedView sizeToFit]; + + return _indefiniteAnimatedView; +} + +- (SVProgressAnimatedView*)ringView { + if(!_ringView) { + _ringView = [[SVProgressAnimatedView alloc] initWithFrame:CGRectZero]; + } + + // Update styling + _ringView.strokeColor = self.foregroundColorForStyle; + _ringView.strokeThickness = self.ringThickness; + _ringView.radius = self.statusLabel.text ? self.ringRadius : self.ringNoTextRadius; + + return _ringView; +} + +- (SVProgressAnimatedView*)backgroundRingView { + if(!_backgroundRingView) { + _backgroundRingView = [[SVProgressAnimatedView alloc] initWithFrame:CGRectZero]; + _backgroundRingView.strokeEnd = 1.0f; + } + + // Update styling + _backgroundRingView.strokeColor = [self.foregroundColorForStyle colorWithAlphaComponent:0.1f]; + _backgroundRingView.strokeThickness = self.ringThickness; + _backgroundRingView.radius = self.statusLabel.text ? self.ringRadius : self.ringNoTextRadius; + + return _backgroundRingView; +} + +- (void)cancelRingLayerAnimation { + // Animate value update, stop animation + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + + [self.hudView.layer removeAllAnimations]; + self.ringView.strokeEnd = 0.0f; + + [CATransaction commit]; + + // Remove from view + [self.ringView removeFromSuperview]; + [self.backgroundRingView removeFromSuperview]; +} + +- (void)cancelIndefiniteAnimatedViewAnimation { + // Stop animation + if([self.indefiniteAnimatedView respondsToSelector:@selector(stopAnimating)]) { + [(id)self.indefiniteAnimatedView stopAnimating]; + } + // Remove from view + [self.indefiniteAnimatedView removeFromSuperview]; +} + + +#pragma mark - Utilities + ++ (BOOL)isVisible { + return ([self sharedView].alpha > 0); +} + + +#pragma mark - Getters + ++ (NSTimeInterval)displayDurationForString:(NSString*)string { + return MAX((float)string.length * 0.06 + 0.5, [self sharedView].minimumDismissTimeInterval); +} + +- (UIColor*)foregroundColorForStyle { + if(self.defaultStyle == SVProgressHUDStyleLight) { + return [UIColor blackColor]; + } else if(self.defaultStyle == SVProgressHUDStyleDark) { + return [UIColor whiteColor]; + } else { + return self.foregroundColor; + } +} + +- (UIColor*)backgroundColorForStyle { + if(self.defaultStyle == SVProgressHUDStyleLight) { + return [UIColor whiteColor]; + } else if(self.defaultStyle == SVProgressHUDStyleDark) { + return [UIColor blackColor]; + } else { + return self.backgroundColor; + } +} + +- (UIImage*)image:(UIImage*)image withTintColor:(UIColor*)color { + CGRect rect = CGRectMake(0.0f, 0.0f, image.size.width, image.size.height); + UIGraphicsBeginImageContextWithOptions(rect.size, NO, image.scale); + CGContextRef c = UIGraphicsGetCurrentContext(); + [image drawInRect:rect]; + CGContextSetFillColorWithColor(c, [color CGColor]); + CGContextSetBlendMode(c, kCGBlendModeSourceAtop); + CGContextFillRect(c, rect); + UIImage *tintedImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return tintedImage; +} + +- (BOOL)isClear { // used for iOS 7 and above + return (self.defaultMaskType == SVProgressHUDMaskTypeClear || self.defaultMaskType == SVProgressHUDMaskTypeNone); +} + +- (UIControl*)overlayView { + if(!_overlayView) { + _overlayView = [[UIControl alloc] init]; + _overlayView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + _overlayView.backgroundColor = [UIColor clearColor]; + [_overlayView addTarget:self action:@selector(overlayViewDidReceiveTouchEvent:forEvent:) forControlEvents:UIControlEventTouchDown]; + } + // Update frame +#if !defined(SV_APP_EXTENSIONS) + CGRect windowBounds = [[[UIApplication sharedApplication] delegate] window].bounds; + _overlayView.frame = windowBounds; +#else + _overlayView.frame = [UIScreen mainScreen].bounds; +#endif + + return _overlayView; +} + +- (UIView*)hudView { + if(!_hudView) { + _hudView = [[UIView alloc] initWithFrame:CGRectZero]; + _hudView.layer.masksToBounds = YES; + _hudView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin; + } + + // Update styling + _hudView.layer.cornerRadius = self.cornerRadius; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + // On iOS 8, the background color is set via a UIVisualEffectsView, see updateBlurBounds: + _hudView.backgroundColor = self.defaultStyle == SVProgressHUDStyleCustom ? self.backgroundColor : [UIColor clearColor]; +#else + _hudView.backgroundColor = self.backgroundColorForStyle; +#endif + return _hudView; +} + +- (UILabel*)statusLabel { + if(!_statusLabel) { + _statusLabel = [[UILabel alloc] initWithFrame:CGRectZero]; + _statusLabel.backgroundColor = [UIColor clearColor]; + _statusLabel.adjustsFontSizeToFitWidth = YES; + _statusLabel.textAlignment = NSTextAlignmentCenter; + _statusLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; + _statusLabel.numberOfLines = 0; + } + if(!_statusLabel.superview) { + [self.hudView addSubview:_statusLabel]; + } + + // Update styling + _statusLabel.textColor = self.foregroundColorForStyle; + _statusLabel.font = self.font; + + return _statusLabel; +} + +- (UIImageView*)imageView { + if(!_imageView) { + _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 28.0f, 28.0f)]; + } + if(!_imageView.superview) { + [self.hudView addSubview:_imageView]; + } + return _imageView; +} + +- (CGFloat)visibleKeyboardHeight { +#if !defined(SV_APP_EXTENSIONS) + UIWindow *keyboardWindow = nil; + for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) { + if(![[testWindow class] isEqual:[UIWindow class]]) { + keyboardWindow = testWindow; + break; + } + } + + for (__strong UIView *possibleKeyboard in [keyboardWindow subviews]) { + if([possibleKeyboard isKindOfClass:NSClassFromString(@"UIPeripheralHostView")] || [possibleKeyboard isKindOfClass:NSClassFromString(@"UIKeyboard")]) { + return CGRectGetHeight(possibleKeyboard.bounds); + } else if([possibleKeyboard isKindOfClass:NSClassFromString(@"UIInputSetContainerView")]) { + for (__strong UIView *possibleKeyboardSubview in [possibleKeyboard subviews]) { + if([possibleKeyboardSubview isKindOfClass:NSClassFromString(@"UIInputSetHostView")]) { + return CGRectGetHeight(possibleKeyboardSubview.bounds); + } + } + } + } +#endif + return 0; +} + + +#pragma mark - UIAppearance Setters + +- (void)setDefaultStyle:(SVProgressHUDStyle)style { + if (!_isInitializing) _defaultStyle = style; +} + +- (void)setDefaultMaskType:(SVProgressHUDMaskType)maskType { + if (!_isInitializing) _defaultMaskType = maskType; +} + +- (void)setDefaultAnimationType:(SVProgressHUDAnimationType)animationType { + if (!_isInitializing) _defaultAnimationType = animationType; +} + +- (void)setMinimumSize:(CGSize)minimumSize { + if (!_isInitializing) _minimumSize = minimumSize; +} + +- (void)setRingThickness:(CGFloat)ringThickness { + if (!_isInitializing) _ringThickness = ringThickness; +} + +- (void)setRingRadius:(CGFloat)ringRadius { + if (!_isInitializing) _ringRadius = ringRadius; +} + +- (void)setRingNoTextRadius:(CGFloat)ringNoTextRadius { + if (!_isInitializing) _ringNoTextRadius = ringNoTextRadius; +} + +- (void)setCornerRadius:(CGFloat)cornerRadius { + if (!_isInitializing) _cornerRadius = cornerRadius; +} + +- (void)setFont:(UIFont*)font { + if (!_isInitializing) _font = font; +} + +- (void)setForegroundColor:(UIColor*)color { + if (!_isInitializing) _foregroundColor = color; +} + +- (void)setBackgroundColor:(UIColor*)color { + if (!_isInitializing) _backgroundColor = color; +} + +- (void)setBackgroundLayerColor:(UIColor*)color { + if (!_isInitializing) _backgroundLayerColor = color; +} + +- (void)setInfoImage:(UIImage*)image { + if (!_isInitializing) _infoImage = image; +} + +- (void)setSuccessImage:(UIImage*)image { + if (!_isInitializing) _successImage = image; +} + +- (void)setErrorImage:(UIImage*)image { + if (!_isInitializing) _errorImage = image; +} + +- (void)setViewForExtension:(UIView*)view { + if (!_isInitializing) _viewForExtension = view; +} + +- (void)setOffsetFromCenter:(UIOffset)offset { + if (!_isInitializing) _offsetFromCenter = offset; +} + +- (void)setMinimumDismissTimeInterval:(NSTimeInterval)minimumDismissTimeInterval { + if (!_isInitializing) _minimumDismissTimeInterval = minimumDismissTimeInterval; +} + +- (void)setFadeInAnimationDuration:(NSTimeInterval)duration { + if (!_isInitializing) _fadeInAnimationDuration = duration; +} + +- (void)setFadeOutAnimationDuration:(NSTimeInterval)duration { + if (!_isInitializing) _fadeOutAnimationDuration = duration; +} + +- (void)setMaxSupportedWindowLevel:(UIWindowLevel)maxSupportedWindowLevel { + if (!_isInitializing) _maxSupportedWindowLevel = maxSupportedWindowLevel; +} + +@end + diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVRadialGradientLayer.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVRadialGradientLayer.h new file mode 100755 index 00000000000..634449e604c --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVRadialGradientLayer.h @@ -0,0 +1,14 @@ +// +// SVRadialGradientLayer.h +// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD +// +// Copyright (c) 2014-2016 Tobias Tiemerding. All rights reserved. +// + +#import + +@interface SVRadialGradientLayer : CALayer + +@property (nonatomic) CGPoint gradientCenter; + +@end diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVRadialGradientLayer.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVRadialGradientLayer.m new file mode 100755 index 00000000000..d6d58275328 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/SVProgressHUD/SVRadialGradientLayer.m @@ -0,0 +1,25 @@ +// +// SVRadialGradientLayer.m +// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD +// +// Copyright (c) 2014-2016 Tobias Tiemerding. All rights reserved. +// + +#import "SVRadialGradientLayer.h" + +@implementation SVRadialGradientLayer + +- (void)drawInContext:(CGContextRef)context { + size_t locationsCount = 2; + CGFloat locations[2] = {0.0f, 1.0f}; + CGFloat colors[8] = {0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.75f}; + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, colors, locations, locationsCount); + CGColorSpaceRelease(colorSpace); + + float radius = MIN(self.bounds.size.width , self.bounds.size.height); + CGContextDrawRadialGradient (context, gradient, self.gradientCenter, 0, self.gradientCenter, radius, kCGGradientDrawsAfterEndLocation); + CGGradientRelease(gradient); +} + +@end diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Libraries/TSMarkdownParser/TSMarkdownParser-Prefix.pch b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/TSMarkdownParser/TSMarkdownParser-Prefix.pch new file mode 100755 index 00000000000..594d3b51cb4 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/TSMarkdownParser/TSMarkdownParser-Prefix.pch @@ -0,0 +1,10 @@ +// +// Prefix header +// +// The contents of this file are implicitly included at the beginning of every source file. +// + +#ifdef __OBJC__ + #import + +#endif \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/Pods/TSMarkdownParser/TSMarkdownParser/TSMarkdownParser.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/TSMarkdownParser/TSMarkdownParser.h old mode 100644 new mode 100755 similarity index 98% rename from ios/SAPTracker/src/xcode/Pods/TSMarkdownParser/TSMarkdownParser/TSMarkdownParser.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/TSMarkdownParser/TSMarkdownParser.h index 8771677beee..63678a40237 --- a/ios/SAPTracker/src/xcode/Pods/TSMarkdownParser/TSMarkdownParser/TSMarkdownParser.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/TSMarkdownParser/TSMarkdownParser.h @@ -6,7 +6,7 @@ // Copyright (c) 2014 Computertalk Sweden. All rights reserved. // -#import +#import typedef void (^TSMarkdownParserMatchBlock)(NSTextCheckingResult *match, NSMutableAttributedString *attributedString); typedef void (^TSMarkdownParserFormattingBlock)(NSMutableAttributedString *attributedString, NSRange range); diff --git a/ios/SAPTracker/src/xcode/Pods/TSMarkdownParser/TSMarkdownParser/TSMarkdownParser.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/TSMarkdownParser/TSMarkdownParser.m old mode 100644 new mode 100755 similarity index 99% rename from ios/SAPTracker/src/xcode/Pods/TSMarkdownParser/TSMarkdownParser/TSMarkdownParser.m rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/TSMarkdownParser/TSMarkdownParser.m index 790d1707e8c..103d615a3bf --- a/ios/SAPTracker/src/xcode/Pods/TSMarkdownParser/TSMarkdownParser/TSMarkdownParser.m +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/TSMarkdownParser/TSMarkdownParser.m @@ -6,7 +6,6 @@ // Copyright (c) 2014 Computertalk Sweden. All rights reserved. // -#import #import "TSMarkdownParser.h" @interface TSExpressionBlockPair : NSObject @@ -60,7 +59,7 @@ } + (instancetype)standardParser { - TSMarkdownParser *defaultParser = [TSMarkdownParser new]; + TSMarkdownParser *defaultParser = [self new]; __weak TSMarkdownParser *weakParser = defaultParser; diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h old mode 100644 new mode 100755 similarity index 88% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h index 312d680e0d3..3c7649bd696 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h @@ -1,6 +1,5 @@ // AFNetworkActivityIndicatorManager.h -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -28,6 +27,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** `AFNetworkActivityIndicatorManager` manages the state of the network activity indicator in the status bar. When enabled, it will listen for notifications indicating that a network request operation has started or finished, and start or stop animating the indicator accordingly. The number of active requests is incremented and decremented much like a stack or a semaphore, and the activity indicator will animate so long as that number is greater than zero. @@ -35,11 +36,12 @@ [[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES]; - By setting `isNetworkActivityIndicatorVisible` to `YES` for `sharedManager`, the network activity indicator will show and hide automatically as requests start and finish. You should not ever need to call `incrementActivityCount` or `decrementActivityCount` yourself. + By setting `enabled` to `YES` for `sharedManager`, the network activity indicator will show and hide automatically as requests start and finish. You should not ever need to call `incrementActivityCount` or `decrementActivityCount` yourself. See the Apple Human Interface Guidelines section about the Network Activity Indicator for more information: http://developer.apple.com/library/iOS/#documentation/UserExperience/Conceptual/MobileHIG/UIElementGuidelines/UIElementGuidelines.html#//apple_ref/doc/uid/TP40006556-CH13-SW44 */ +NS_EXTENSION_UNAVAILABLE_IOS("Use view controller based solutions where appropriate instead.") @interface AFNetworkActivityIndicatorManager : NSObject /** @@ -73,4 +75,6 @@ @end +NS_ASSUME_NONNULL_END + #endif diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m old mode 100644 new mode 100755 similarity index 98% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m index c2d855a59c4..cf131804893 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m @@ -1,6 +1,5 @@ // AFNetworkActivityIndicatorManager.m -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -121,7 +120,7 @@ static NSURLRequest * AFNetworkRequestFromNotification(NSNotification *notificat @synchronized(self) { _activityCount = activityCount; } - + dispatch_async(dispatch_get_main_queue(), ^{ [self updateNetworkActivityIndicatorVisibilityDelayed]; }); @@ -133,7 +132,7 @@ static NSURLRequest * AFNetworkRequestFromNotification(NSNotification *notificat _activityCount++; } [self didChangeValueForKey:@"activityCount"]; - + dispatch_async(dispatch_get_main_queue(), ^{ [self updateNetworkActivityIndicatorVisibilityDelayed]; }); @@ -148,7 +147,7 @@ static NSURLRequest * AFNetworkRequestFromNotification(NSNotification *notificat #pragma clang diagnostic pop } [self didChangeValueForKey:@"activityCount"]; - + dispatch_async(dispatch_get_main_queue(), ^{ [self updateNetworkActivityIndicatorVisibilityDelayed]; }); diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h old mode 100644 new mode 100755 similarity index 90% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h index 1c1f8dd6f8d..0c8f9b52d73 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h @@ -1,6 +1,5 @@ // UIActivityIndicatorView+AFNetworking.h -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -45,7 +44,7 @@ @param task The task. If `nil`, automatic updating from any previously specified operation will be disabled. */ #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 -- (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task; +- (void)setAnimatingWithStateOfTask:(nullable NSURLSessionTask *)task; #endif ///--------------------------------------- @@ -54,10 +53,10 @@ /** Binds the animating state to the execution state of the specified operation. - + @param operation The operation. If `nil`, automatic updating from any previously specified operation will be disabled. */ -- (void)setAnimatingWithStateOfOperation:(AFURLConnectionOperation *)operation; +- (void)setAnimatingWithStateOfOperation:(nullable AFURLConnectionOperation *)operation; @end diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m old mode 100644 new mode 100755 similarity index 51% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m index 6627dbb1b83..dd362b0171a --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m @@ -1,6 +1,5 @@ // UIActivityIndicatorView+AFNetworking.m -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -21,6 +20,7 @@ // THE SOFTWARE. #import "UIActivityIndicatorView+AFNetworking.h" +#import #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) @@ -30,8 +30,51 @@ #import "AFURLSessionManager.h" #endif +@interface AFActivityIndicatorViewNotificationObserver : NSObject +@property (readonly, nonatomic, weak) UIActivityIndicatorView *activityIndicatorView; +- (instancetype)initWithActivityIndicatorView:(UIActivityIndicatorView *)activityIndicatorView; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 +- (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task; +#endif +- (void)setAnimatingWithStateOfOperation:(AFURLConnectionOperation *)operation; + +@end + @implementation UIActivityIndicatorView (AFNetworking) +- (AFActivityIndicatorViewNotificationObserver *)af_notificationObserver { + AFActivityIndicatorViewNotificationObserver *notificationObserver = objc_getAssociatedObject(self, @selector(af_notificationObserver)); + if (notificationObserver == nil) { + notificationObserver = [[AFActivityIndicatorViewNotificationObserver alloc] initWithActivityIndicatorView:self]; + objc_setAssociatedObject(self, @selector(af_notificationObserver), notificationObserver, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + return notificationObserver; +} + +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 +- (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task { + [[self af_notificationObserver] setAnimatingWithStateOfTask:task]; +} +#endif + +- (void)setAnimatingWithStateOfOperation:(AFURLConnectionOperation *)operation { + [[self af_notificationObserver] setAnimatingWithStateOfOperation:operation]; +} + +@end + +@implementation AFActivityIndicatorViewNotificationObserver + +- (instancetype)initWithActivityIndicatorView:(UIActivityIndicatorView *)activityIndicatorView +{ + self = [super init]; + if (self) { + _activityIndicatorView = activityIndicatorView; + } + return self; +} + #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 - (void)setAnimatingWithStateOfTask:(NSURLSessionTask *)task { NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; @@ -39,14 +82,19 @@ [notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil]; [notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil]; [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil]; - + if (task) { if (task.state != NSURLSessionTaskStateCompleted) { + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreceiver-is-weak" +#pragma clang diagnostic ignored "-Warc-repeated-use-of-weak" if (task.state == NSURLSessionTaskStateRunning) { - [self startAnimating]; + [self.activityIndicatorView startAnimating]; } else { - [self stopAnimating]; + [self.activityIndicatorView stopAnimating]; } +#pragma clang diagnostic pop [notificationCenter addObserver:self selector:@selector(af_startAnimating) name:AFNetworkingTaskDidResumeNotification object:task]; [notificationCenter addObserver:self selector:@selector(af_stopAnimating) name:AFNetworkingTaskDidCompleteNotification object:task]; @@ -66,11 +114,16 @@ if (operation) { if (![operation isFinished]) { + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreceiver-is-weak" +#pragma clang diagnostic ignored "-Warc-repeated-use-of-weak" if ([operation isExecuting]) { - [self startAnimating]; + [self.activityIndicatorView startAnimating]; } else { - [self stopAnimating]; + [self.activityIndicatorView stopAnimating]; } +#pragma clang diagnostic pop [notificationCenter addObserver:self selector:@selector(af_startAnimating) name:AFNetworkingOperationDidStartNotification object:operation]; [notificationCenter addObserver:self selector:@selector(af_stopAnimating) name:AFNetworkingOperationDidFinishNotification object:operation]; @@ -82,16 +135,37 @@ - (void)af_startAnimating { dispatch_async(dispatch_get_main_queue(), ^{ - [self startAnimating]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreceiver-is-weak" + [self.activityIndicatorView startAnimating]; +#pragma clang diagnostic pop }); } - (void)af_stopAnimating { dispatch_async(dispatch_get_main_queue(), ^{ - [self stopAnimating]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreceiver-is-weak" + [self.activityIndicatorView stopAnimating]; +#pragma clang diagnostic pop }); } +#pragma mark - + +- (void)dealloc { + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 + [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil]; + [notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil]; + [notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil]; +#endif + + [notificationCenter removeObserver:self name:AFNetworkingOperationDidStartNotification object:nil]; + [notificationCenter removeObserver:self name:AFNetworkingOperationDidFinishNotification object:nil]; +} + @end #endif diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIAlertView+AFNetworking.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIAlertView+AFNetworking.h old mode 100644 new mode 100755 similarity index 79% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIAlertView+AFNetworking.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIAlertView+AFNetworking.h index b94f1cb8e09..97f5622bbf4 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIAlertView+AFNetworking.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIAlertView+AFNetworking.h @@ -1,6 +1,5 @@ // UIAlertView+AFNetworking.h -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -28,6 +27,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + @class AFURLConnectionOperation; /** @@ -41,18 +42,18 @@ /** Shows an alert view with the error of the specified session task, if any. - + @param task The session task. @param delegate The alert view delegate. */ #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 + (void)showAlertViewForTaskWithErrorOnCompletion:(NSURLSessionTask *)task - delegate:(id)delegate; + delegate:(nullable id)delegate NS_EXTENSION_UNAVAILABLE_IOS("Not available in app extensions."); #endif /** Shows an alert view with the error of the specified session task, if any, with a custom cancel button title and other button titles. - + @param task The session task. @param delegate The alert view delegate. @param cancelButtonTitle The title of the cancel button or nil if there is no cancel button. Using this argument is equivalent to setting the cancel button index to the value returned by invoking addButtonWithTitle: specifying this title. @@ -60,9 +61,9 @@ */ #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 + (void)showAlertViewForTaskWithErrorOnCompletion:(NSURLSessionTask *)task - delegate:(id)delegate - cancelButtonTitle:(NSString *)cancelButtonTitle - otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION; + delegate:(nullable id)delegate + cancelButtonTitle:(nullable NSString *)cancelButtonTitle + otherButtonTitles:(nullable NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION NS_EXTENSION_UNAVAILABLE_IOS("Not available in app extensions."); #endif ///------------------------------------------ @@ -76,7 +77,7 @@ @param delegate The alert view delegate. */ + (void)showAlertViewForRequestOperationWithErrorOnCompletion:(AFURLConnectionOperation *)operation - delegate:(id)delegate; + delegate:(nullable id)delegate NS_EXTENSION_UNAVAILABLE_IOS("Not available in app extensions."); /** Shows an alert view with the error of the specified request operation, if any, with a custom cancel button title and other button titles. @@ -87,10 +88,12 @@ @param otherButtonTitles The title of another button. Using this argument is equivalent to invoking addButtonWithTitle: with this title to add more buttons. Too many buttons can cause the alert view to scroll. For guidelines on the best ways to use an alert in an app, see "Temporary Views". Titles of additional buttons to add to the receiver, terminated with `nil`. */ + (void)showAlertViewForRequestOperationWithErrorOnCompletion:(AFURLConnectionOperation *)operation - delegate:(id)delegate - cancelButtonTitle:(NSString *)cancelButtonTitle - otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION; + delegate:(nullable id)delegate + cancelButtonTitle:(nullable NSString *)cancelButtonTitle + otherButtonTitles:(nullable NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION NS_EXTENSION_UNAVAILABLE_IOS("Not available in app extensions."); @end +NS_ASSUME_NONNULL_END + #endif diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIAlertView+AFNetworking.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIAlertView+AFNetworking.m old mode 100644 new mode 100755 similarity index 65% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIAlertView+AFNetworking.m rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIAlertView+AFNetworking.m index b7e2a26cb2b..0d1e9e7193d --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIAlertView+AFNetworking.m +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIAlertView+AFNetworking.m @@ -1,6 +1,5 @@ // UIAlertView+AFNetworking.m -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -62,17 +61,32 @@ static void AFGetAlertViewTitleAndMessageFromError(NSError *error, NSString * __ cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION { - __block id observer = [[NSNotificationCenter defaultCenter] addObserverForName:AFNetworkingTaskDidCompleteNotification object:task queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notification) { + NSMutableArray *mutableOtherTitles = [NSMutableArray array]; + va_list otherButtonTitleList; + va_start(otherButtonTitleList, otherButtonTitles); + { + for (NSString *otherButtonTitle = otherButtonTitles; otherButtonTitle != nil; otherButtonTitle = va_arg(otherButtonTitleList, NSString *)) { + [mutableOtherTitles addObject:otherButtonTitle]; + } + } + va_end(otherButtonTitleList); + __block __weak id observer = [[NSNotificationCenter defaultCenter] addObserverForName:AFNetworkingTaskDidCompleteNotification object:task queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notification) { NSError *error = notification.userInfo[AFNetworkingTaskDidCompleteErrorKey]; if (error) { NSString *title, *message; AFGetAlertViewTitleAndMessageFromError(error, &title, &message); - [[[UIAlertView alloc] initWithTitle:title message:message delegate:delegate cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitles, nil] show]; + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:nil delegate:delegate cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil, nil]; + for (NSString *otherButtonTitle in mutableOtherTitles) { + [alertView addButtonWithTitle:otherButtonTitle]; + } + [alertView setTitle:title]; + [alertView setMessage:message]; + [alertView show]; } - [[NSNotificationCenter defaultCenter] removeObserver:observer name:AFNetworkingTaskDidCompleteNotification object:notification.object]; + [[NSNotificationCenter defaultCenter] removeObserver:observer]; }]; } #endif @@ -82,7 +96,7 @@ static void AFGetAlertViewTitleAndMessageFromError(NSError *error, NSString * __ + (void)showAlertViewForRequestOperationWithErrorOnCompletion:(AFURLConnectionOperation *)operation delegate:(id)delegate { - [self showAlertViewForRequestOperationWithErrorOnCompletion:operation delegate:delegate cancelButtonTitle:NSLocalizedStringFromTable(@"Dismiss", @"AFNetworking", @"UIAlert View Cancel Button Title") otherButtonTitles:nil, nil]; + [self showAlertViewForRequestOperationWithErrorOnCompletion:operation delegate:delegate cancelButtonTitle:NSLocalizedStringFromTable(@"Dismiss", @"AFNetworking", @"UIAlertView Cancel Button Title") otherButtonTitles:nil, nil]; } + (void)showAlertViewForRequestOperationWithErrorOnCompletion:(AFURLConnectionOperation *)operation @@ -90,7 +104,17 @@ static void AFGetAlertViewTitleAndMessageFromError(NSError *error, NSString * __ cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION { - __block id observer = [[NSNotificationCenter defaultCenter] addObserverForName:AFNetworkingOperationDidFinishNotification object:operation queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notification) { + NSMutableArray *mutableOtherTitles = [NSMutableArray array]; + va_list otherButtonTitleList; + va_start(otherButtonTitleList, otherButtonTitles); + { + for (NSString *otherButtonTitle = otherButtonTitles; otherButtonTitle != nil; otherButtonTitle = va_arg(otherButtonTitleList, NSString *)) { + [mutableOtherTitles addObject:otherButtonTitle]; + } + } + va_end(otherButtonTitleList); + + __block __weak id observer = [[NSNotificationCenter defaultCenter] addObserverForName:AFNetworkingOperationDidFinishNotification object:operation queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notification) { if (notification.object && [notification.object isKindOfClass:[AFURLConnectionOperation class]]) { NSError *error = [(AFURLConnectionOperation *)notification.object error]; @@ -98,11 +122,17 @@ static void AFGetAlertViewTitleAndMessageFromError(NSError *error, NSString * __ NSString *title, *message; AFGetAlertViewTitleAndMessageFromError(error, &title, &message); - [[[UIAlertView alloc] initWithTitle:title message:message delegate:delegate cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitles, nil] show]; + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:nil delegate:delegate cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil, nil]; + for (NSString *otherButtonTitle in mutableOtherTitles) { + [alertView addButtonWithTitle:otherButtonTitle]; + } + [alertView setTitle:title]; + [alertView setMessage:message]; + [alertView show]; } } - [[NSNotificationCenter defaultCenter] removeObserver:observer name:AFNetworkingOperationDidFinishNotification object:notification.object]; + [[NSNotificationCenter defaultCenter] removeObserver:observer]; }]; } diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIButton+AFNetworking.h old mode 100644 new mode 100755 similarity index 84% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIButton+AFNetworking.h index e6ed6de04cf..7289bdb4799 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIButton+AFNetworking.h @@ -1,6 +1,5 @@ // UIButton+AFNetworking.h -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -28,11 +27,13 @@ #import +NS_ASSUME_NONNULL_BEGIN + @protocol AFURLResponseSerialization, AFImageCache; /** This category adds methods to the UIKit framework's `UIButton` class. The methods in this category provide support for loading remote images and background images asynchronously from a URL. - + @warning Compound values for control `state` (such as `UIControlStateHighlighted | UIControlStateDisabled`) are unsupported. */ @interface UIButton (AFNetworking) @@ -42,7 +43,7 @@ ///---------------------------- /** - The image cache used to improve image loadiing performance on scroll views. By default, `UIButton` will use the `sharedImageCache` of `UIImageView`. + The image cache used to improve image loading performance on scroll views. By default, `UIButton` will use the `sharedImageCache` of `UIImageView`. */ + (id )sharedImageCache; @@ -51,7 +52,7 @@ @param imageCache The image cache. */ -+ (void)setSharedImageCache:(id )imageCache; ++ (void)setSharedImageCache:(__nullable id )imageCache; ///------------------------------------ /// @name Accessing Response Serializer @@ -70,9 +71,9 @@ /** Asynchronously downloads an image from the specified URL, and sets it as the image for the specified state once the request is finished. Any previous image request for the receiver will be cancelled. - + If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. - + @param state The control state. @param url The URL used for the image request. */ @@ -81,35 +82,35 @@ /** Asynchronously downloads an image from the specified URL, and sets it as the image for the specified state once the request is finished. Any previous image request for the receiver will be cancelled. - + If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. - + @param state The control state. @param url The URL used for the image request. @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the button will not change its image until the image request finishes. */ - (void)setImageForState:(UIControlState)state withURL:(NSURL *)url - placeholderImage:(UIImage *)placeholderImage; + placeholderImage:(nullable UIImage *)placeholderImage; /** Asynchronously downloads an image from the specified URL request, and sets it as the image for the specified state once the request is finished. Any previous image request for the receiver will be cancelled. If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. - + If a success block is specified, it is the responsibility of the block to set the image of the button before returning. If no success block is specified, the default behavior of setting the image with `setImage:forState:` is applied. @param state The control state. @param urlRequest The URL request used for the image request. @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the button will not change its image until the image request finishes. - @param success A block to be executed when the image request operation finishes successfully. This block has no return value and takes two arguments: the server response and the image. If the image was returned from cache, the request and response parameters will be `nil`. + @param success A block to be executed when the image request operation finishes successfully. This block has no return value and takes two arguments: the server response and the image. If the image was returned from cache, the response parameter will be `nil`. @param failure A block object to be executed when the image request operation finishes unsuccessfully, or that finishes successfully. This block has no return value and takes a single argument: the error that occurred. */ - (void)setImageForState:(UIControlState)state withURLRequest:(NSURLRequest *)urlRequest - placeholderImage:(UIImage *)placeholderImage - success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success - failure:(void (^)(NSError *error))failure; + placeholderImage:(nullable UIImage *)placeholderImage + success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * __nullable response, UIImage *image))success + failure:(nullable void (^)(NSError *error))failure; ///------------------------------- @@ -138,7 +139,7 @@ */ - (void)setBackgroundImageForState:(UIControlState)state withURL:(NSURL *)url - placeholderImage:(UIImage *)placeholderImage; + placeholderImage:(nullable UIImage *)placeholderImage; /** Asynchronously downloads an image from the specified URL request, and sets it as the image for the specified state once the request is finished. Any previous image request for the receiver will be cancelled. @@ -150,12 +151,14 @@ @param state The control state. @param urlRequest The URL request used for the image request. @param placeholderImage The background image to be set initially, until the background image request finishes. If `nil`, the button will not change its background image until the background image request finishes. + @param success A block to be executed when the image request operation finishes successfully. This block has no return value and takes two arguments: the server response and the image. If the image was returned from cache, the response parameter will be `nil`. + @param failure A block object to be executed when the image request operation finishes unsuccessfully, or that finishes successfully. This block has no return value and takes a single argument: the error that occurred. */ - (void)setBackgroundImageForState:(UIControlState)state withURLRequest:(NSURLRequest *)urlRequest - placeholderImage:(UIImage *)placeholderImage - success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success - failure:(void (^)(NSError *error))failure; + placeholderImage:(nullable UIImage *)placeholderImage + success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * __nullable response, UIImage *image))success + failure:(nullable void (^)(NSError *error))failure; ///------------------------------ @@ -164,18 +167,20 @@ /** Cancels any executing image operation for the specified control state of the receiver, if one exists. - + @param state The control state. */ - (void)cancelImageRequestOperationForState:(UIControlState)state; /** Cancels any executing background image operation for the specified control state of the receiver, if one exists. - + @param state The control state. */ - (void)cancelBackgroundImageRequestOperationForState:(UIControlState)state; @end +NS_ASSUME_NONNULL_END + #endif diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIButton+AFNetworking.m old mode 100644 new mode 100755 similarity index 94% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.m rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIButton+AFNetworking.m index a225290a25a..e5c36a5592e --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIButton+AFNetworking.m +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIButton+AFNetworking.m @@ -1,6 +1,5 @@ // UIButton+AFNetworking.m -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -122,7 +121,7 @@ static const char * af_backgroundImageRequestOperationKeyForState(UIControlState #pragma clang diagnostic pop } -+ (void)setSharedImageCache:(id )imageCache { ++ (void)setSharedImageCache:(__nullable id )imageCache { objc_setAssociatedObject(self, @selector(sharedImageCache), imageCache, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @@ -166,7 +165,7 @@ static const char * af_backgroundImageRequestOperationKeyForState(UIControlState - (void)setImageForState:(UIControlState)state withURLRequest:(NSURLRequest *)urlRequest placeholderImage:(UIImage *)placeholderImage - success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success + success:(void (^)(NSURLRequest *request, NSHTTPURLResponse * __nullable response, UIImage *image))success failure:(void (^)(NSError *error))failure { [self cancelImageRequestOperationForState:state]; @@ -174,7 +173,7 @@ static const char * af_backgroundImageRequestOperationKeyForState(UIControlState UIImage *cachedImage = [[[self class] sharedImageCache] cachedImageForRequest:urlRequest]; if (cachedImage) { if (success) { - success(nil, nil, cachedImage); + success(urlRequest, nil, cachedImage); } else { [self setImage:cachedImage forState:state]; } @@ -199,7 +198,7 @@ static const char * af_backgroundImageRequestOperationKeyForState(UIControlState } [[[strongSelf class] sharedImageCache] cacheImage:responseObject forRequest:urlRequest]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if ([[urlRequest URL] isEqual:[operation.response URL]]) { + if ([[urlRequest URL] isEqual:[operation.request URL]]) { if (failure) { failure(error); } @@ -232,7 +231,7 @@ static const char * af_backgroundImageRequestOperationKeyForState(UIControlState - (void)setBackgroundImageForState:(UIControlState)state withURLRequest:(NSURLRequest *)urlRequest placeholderImage:(UIImage *)placeholderImage - success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success + success:(void (^)(NSURLRequest *request, NSHTTPURLResponse * __nullable response, UIImage *image))success failure:(void (^)(NSError *error))failure { [self cancelBackgroundImageRequestOperationForState:state]; @@ -240,7 +239,7 @@ static const char * af_backgroundImageRequestOperationKeyForState(UIControlState UIImage *cachedImage = [[[self class] sharedImageCache] cachedImageForRequest:urlRequest]; if (cachedImage) { if (success) { - success(nil, nil, cachedImage); + success(urlRequest, nil, cachedImage); } else { [self setBackgroundImage:cachedImage forState:state]; } @@ -263,8 +262,9 @@ static const char * af_backgroundImageRequestOperationKeyForState(UIControlState [strongSelf setBackgroundImage:responseObject forState:state]; } } + [[[strongSelf class] sharedImageCache] cacheImage:responseObject forRequest:urlRequest]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if ([[urlRequest URL] isEqual:[operation.response URL]]) { + if ([[urlRequest URL] isEqual:[operation.request URL]]) { if (failure) { failure(error); } diff --git a/ios/SAPTracker/src/xcode/LICENSE.txt b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIImage+AFNetworking.h old mode 100644 new mode 100755 similarity index 80% rename from ios/SAPTracker/src/xcode/LICENSE.txt rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIImage+AFNetworking.h index 1f7db9e996b..32929202b04 --- a/ios/SAPTracker/src/xcode/LICENSE.txt +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIImage+AFNetworking.h @@ -1,7 +1,8 @@ -AFNetworking -// AFNetworking.h // -// Copyright (c) 2013 AFNetworking (http://afnetworking.com/) +// UIImage+AFNetworking.h +// +// +// Created by Paulo Ferreira on 08/07/15. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -19,4 +20,16 @@ AFNetworking // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. \ No newline at end of file +// THE SOFTWARE. + +#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) + +#import + +@interface UIImage (AFNetworking) + ++ (UIImage*) safeImageWithData:(NSData*)data; + +@end + +#endif diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIImageView+AFNetworking.h old mode 100644 new mode 100755 similarity index 84% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIImageView+AFNetworking.h index 5d523636e88..bf619154886 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIImageView+AFNetworking.h @@ -1,6 +1,5 @@ // UIImageView+AFNetworking.h -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -28,6 +27,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + @protocol AFURLResponseSerialization, AFImageCache; /** @@ -40,16 +41,16 @@ ///---------------------------- /** - The image cache used to improve image loadiing performance on scroll views. By default, this is an `NSCache` subclass conforming to the `AFImageCache` protocol, which listens for notification warnings and evicts objects accordingly. + The image cache used to improve image loading performance on scroll views. By default, this is an `NSCache` subclass conforming to the `AFImageCache` protocol, which listens for notification warnings and evicts objects accordingly. */ + (id )sharedImageCache; /** Set the cache used for image loading. - + @param imageCache The image cache. */ -+ (void)setSharedImageCache:(id )imageCache; ++ (void)setSharedImageCache:(__nullable id )imageCache; ///------------------------------------ /// @name Accessing Response Serializer @@ -57,7 +58,7 @@ /** The response serializer used to create an image representation from the server response and response data. By default, this is an instance of `AFImageResponseSerializer`. - + @discussion Subclasses of `AFImageResponseSerializer` could be used to perform post-processing, such as color correction, face detection, or other effects. See https://github.com/AFNetworking/AFCoreImageSerializer */ @property (nonatomic, strong) id imageResponseSerializer; @@ -67,8 +68,8 @@ ///-------------------- /** - Asynchronously downloads an image from the specified URL, and sets it once the request is finished. Any previous image request for the receiver will be cancelled. - + Asynchronously downloads an image from the specified URL, and sets it once the request is finished. Any previous image request for the receiver will be cancelled. + If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. By default, URL requests have a `Accept` header field value of "image / *", a cache policy of `NSURLCacheStorageAllowed` and a timeout interval of 30 seconds, and are set not handle cookies. To configure URL requests differently, use `setImageWithURLRequest:placeholderImage:success:failure:` @@ -78,8 +79,8 @@ - (void)setImageWithURL:(NSURL *)url; /** - Asynchronously downloads an image from the specified URL, and sets it once the request is finished. Any previous image request for the receiver will be cancelled. - + Asynchronously downloads an image from the specified URL, and sets it once the request is finished. Any previous image request for the receiver will be cancelled. + If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. By default, URL requests have a `Accept` header field value of "image / *", a cache policy of `NSURLCacheStorageAllowed` and a timeout interval of 30 seconds, and are set not handle cookies. To configure URL requests differently, use `setImageWithURLRequest:placeholderImage:success:failure:` @@ -88,24 +89,24 @@ @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the image view will not change its image until the image request finishes. */ - (void)setImageWithURL:(NSURL *)url - placeholderImage:(UIImage *)placeholderImage; + placeholderImage:(nullable UIImage *)placeholderImage; /** - Asynchronously downloads an image from the specified URL request, and sets it once the request is finished. Any previous image request for the receiver will be cancelled. - + Asynchronously downloads an image from the specified URL request, and sets it once the request is finished. Any previous image request for the receiver will be cancelled. + If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. - + If a success block is specified, it is the responsibility of the block to set the image of the image view before returning. If no success block is specified, the default behavior of setting the image with `self.image = image` is applied. @param urlRequest The URL request used for the image request. @param placeholderImage The image to be set initially, until the image request finishes. If `nil`, the image view will not change its image until the image request finishes. - @param success A block to be executed when the image request operation finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the image created from the response data of request. If the image was returned from cache, the request and response parameters will be `nil`. + @param success A block to be executed when the image request operation finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the image created from the response data of request. If the image was returned from cache, the response parameter will be `nil`. @param failure A block object to be executed when the image request operation finishes unsuccessfully, or that finishes successfully. This block has no return value and takes three arguments: the request sent from the client, the response received from the server, and the error object describing the network or parsing error that occurred. */ - (void)setImageWithURLRequest:(NSURLRequest *)urlRequest - placeholderImage:(UIImage *)placeholderImage - success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success - failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure; + placeholderImage:(nullable UIImage *)placeholderImage + success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * __nullable response, UIImage *image))success + failure:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * __nullable response, NSError *error))failure; /** Cancels any executing image operation for the receiver, if one exists. @@ -122,17 +123,17 @@ @protocol AFImageCache /** - Returns a cached image for the specififed request, if available. - + Returns a cached image for the specified request, if available. + @param request The image request. - + @return The cached image. */ -- (UIImage *)cachedImageForRequest:(NSURLRequest *)request; +- (nullable UIImage *)cachedImageForRequest:(NSURLRequest *)request; /** Caches a particular image for the specified request. - + @param image The image to cache. @param request The request to be used as a cache key. */ @@ -140,4 +141,6 @@ forRequest:(NSURLRequest *)request; @end +NS_ASSUME_NONNULL_END + #endif diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIImageView+AFNetworking.m old mode 100644 new mode 100755 similarity index 95% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.m rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIImageView+AFNetworking.m index c06aa9ca4c2..2efc1606c35 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.m +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIImageView+AFNetworking.m @@ -1,6 +1,5 @@ // UIImageView+AFNetworking.m -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -82,7 +81,7 @@ #pragma clang diagnostic pop } -+ (void)setSharedImageCache:(id )imageCache { ++ (void)setSharedImageCache:(__nullable id )imageCache { objc_setAssociatedObject(self, @selector(sharedImageCache), imageCache, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @@ -122,15 +121,15 @@ - (void)setImageWithURLRequest:(NSURLRequest *)urlRequest placeholderImage:(UIImage *)placeholderImage - success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success - failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure + success:(void (^)(NSURLRequest *request, NSHTTPURLResponse * __nullable response, UIImage *image))success + failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse * __nullable response, NSError *error))failure { [self cancelImageRequestOperation]; UIImage *cachedImage = [[[self class] sharedImageCache] cachedImageForRequest:urlRequest]; if (cachedImage) { if (success) { - success(nil, nil, cachedImage); + success(urlRequest, nil, cachedImage); } else { self.image = cachedImage; } @@ -140,7 +139,7 @@ if (placeholderImage) { self.image = placeholderImage; } - + __weak __typeof(self)weakSelf = self; self.af_imageRequestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest]; self.af_imageRequestOperation.responseSerializer = self.imageResponseSerializer; diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIKit+AFNetworking.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIKit+AFNetworking.h old mode 100644 new mode 100755 similarity index 97% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIKit+AFNetworking.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIKit+AFNetworking.h index 94082f6cb58..49850ede78a --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIKit+AFNetworking.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIKit+AFNetworking.h @@ -20,6 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#if TARGET_OS_IOS #import #ifndef _UIKIT_AFNETWORKING_ @@ -31,8 +32,8 @@ #import "UIAlertView+AFNetworking.h" #import "UIButton+AFNetworking.h" #import "UIImageView+AFNetworking.h" - #import "UIKit+AFNetworking.h" #import "UIProgressView+AFNetworking.h" #import "UIRefreshControl+AFNetworking.h" #import "UIWebView+AFNetworking.h" #endif /* _UIKIT_AFNETWORKING_ */ +#endif diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIProgressView+AFNetworking.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIProgressView+AFNetworking.h old mode 100644 new mode 100755 similarity index 96% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIProgressView+AFNetworking.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIProgressView+AFNetworking.h index 3f1bc086f5e..5c00d6d4195 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIProgressView+AFNetworking.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIProgressView+AFNetworking.h @@ -1,6 +1,5 @@ // UIProgressView+AFNetworking.h -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -28,6 +27,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + @class AFURLConnectionOperation; /** @@ -41,7 +42,7 @@ /** Binds the progress to the upload progress of the specified session task. - + @param task The session task. @param animated `YES` if the change should be animated, `NO` if the change should happen immediately. */ @@ -85,4 +86,6 @@ @end +NS_ASSUME_NONNULL_END + #endif diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIProgressView+AFNetworking.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIProgressView+AFNetworking.m old mode 100644 new mode 100755 similarity index 98% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIProgressView+AFNetworking.m rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIProgressView+AFNetworking.m index 927f56d843b..ad2c280ba8d --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIProgressView+AFNetworking.m +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIProgressView+AFNetworking.m @@ -1,6 +1,5 @@ // UIProgressView+AFNetworking.m -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIRefreshControl+AFNetworking.h old mode 100644 new mode 100755 similarity index 91% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIRefreshControl+AFNetworking.h index 37ce772de0d..a65e390d37d --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIRefreshControl+AFNetworking.h @@ -28,10 +28,12 @@ #import +NS_ASSUME_NONNULL_BEGIN + @class AFURLConnectionOperation; /** - This category adds methods to the UIKit framework's `UIRefreshControl` class. The methods in this category provide support for automatically begining and ending refreshing depending on the loading state of a request operation or session task. + This category adds methods to the UIKit framework's `UIRefreshControl` class. The methods in this category provide support for automatically beginning and ending refreshing depending on the loading state of a request operation or session task. */ @interface UIRefreshControl (AFNetworking) @@ -42,7 +44,7 @@ /** Binds the refreshing state to the state of the specified task. - @param task The task. If `nil`, automatic updating from any previously specified operation will be diabled. + @param task The task. If `nil`, automatic updating from any previously specified operation will be disabled. */ #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 - (void)setRefreshingWithStateOfTask:(NSURLSessionTask *)task; @@ -61,4 +63,6 @@ @end +NS_ASSUME_NONNULL_END + #endif diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIRefreshControl+AFNetworking.m old mode 100644 new mode 100755 similarity index 52% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.m rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIRefreshControl+AFNetworking.m index e266451fe51..4c19245a0cb --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIRefreshControl+AFNetworking.m +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIRefreshControl+AFNetworking.m @@ -21,6 +21,7 @@ // THE SOFTWARE. #import "UIRefreshControl+AFNetworking.h" +#import #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) @@ -30,8 +31,51 @@ #import "AFURLSessionManager.h" #endif +@interface AFRefreshControlNotificationObserver : NSObject +@property (readonly, nonatomic, weak) UIRefreshControl *refreshControl; +- (instancetype)initWithActivityRefreshControl:(UIRefreshControl *)refreshControl; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 +- (void)setRefreshingWithStateOfTask:(NSURLSessionTask *)task; +#endif +- (void)setRefreshingWithStateOfOperation:(AFURLConnectionOperation *)operation; + +@end + @implementation UIRefreshControl (AFNetworking) +- (AFRefreshControlNotificationObserver *)af_notificationObserver { + AFRefreshControlNotificationObserver *notificationObserver = objc_getAssociatedObject(self, @selector(af_notificationObserver)); + if (notificationObserver == nil) { + notificationObserver = [[AFRefreshControlNotificationObserver alloc] initWithActivityRefreshControl:self]; + objc_setAssociatedObject(self, @selector(af_notificationObserver), notificationObserver, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + return notificationObserver; +} + +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 +- (void)setRefreshingWithStateOfTask:(NSURLSessionTask *)task { + [[self af_notificationObserver] setRefreshingWithStateOfTask:task]; +} +#endif + +- (void)setRefreshingWithStateOfOperation:(AFURLConnectionOperation *)operation { + [[self af_notificationObserver] setRefreshingWithStateOfOperation:operation]; +} + +@end + +@implementation AFRefreshControlNotificationObserver + +- (instancetype)initWithActivityRefreshControl:(UIRefreshControl *)refreshControl +{ + self = [super init]; + if (self) { + _refreshControl = refreshControl; + } + return self; +} + #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 - (void)setRefreshingWithStateOfTask:(NSURLSessionTask *)task { NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; @@ -41,15 +85,19 @@ [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil]; if (task) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreceiver-is-weak" +#pragma clang diagnostic ignored "-Warc-repeated-use-of-weak" if (task.state == NSURLSessionTaskStateRunning) { - [self beginRefreshing]; + [self.refreshControl beginRefreshing]; [notificationCenter addObserver:self selector:@selector(af_beginRefreshing) name:AFNetworkingTaskDidResumeNotification object:task]; [notificationCenter addObserver:self selector:@selector(af_endRefreshing) name:AFNetworkingTaskDidCompleteNotification object:task]; [notificationCenter addObserver:self selector:@selector(af_endRefreshing) name:AFNetworkingTaskDidSuspendNotification object:task]; } else { - [self endRefreshing]; + [self.refreshControl endRefreshing]; } +#pragma clang diagnostic pop } } #endif @@ -61,16 +109,20 @@ [notificationCenter removeObserver:self name:AFNetworkingOperationDidFinishNotification object:nil]; if (operation) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreceiver-is-weak" +#pragma clang diagnostic ignored "-Warc-repeated-use-of-weak" if (![operation isFinished]) { if ([operation isExecuting]) { - [self beginRefreshing]; + [self.refreshControl beginRefreshing]; } else { - [self endRefreshing]; + [self.refreshControl endRefreshing]; } [notificationCenter addObserver:self selector:@selector(af_beginRefreshing) name:AFNetworkingOperationDidStartNotification object:operation]; [notificationCenter addObserver:self selector:@selector(af_endRefreshing) name:AFNetworkingOperationDidFinishNotification object:operation]; } +#pragma clang diagnostic pop } } @@ -78,16 +130,37 @@ - (void)af_beginRefreshing { dispatch_async(dispatch_get_main_queue(), ^{ - [self beginRefreshing]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreceiver-is-weak" + [self.refreshControl beginRefreshing]; +#pragma clang diagnostic pop }); } - (void)af_endRefreshing { dispatch_async(dispatch_get_main_queue(), ^{ - [self endRefreshing]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreceiver-is-weak" + [self.refreshControl endRefreshing]; +#pragma clang diagnostic pop }); } +#pragma mark - + +- (void)dealloc { + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 + [notificationCenter removeObserver:self name:AFNetworkingTaskDidCompleteNotification object:nil]; + [notificationCenter removeObserver:self name:AFNetworkingTaskDidResumeNotification object:nil]; + [notificationCenter removeObserver:self name:AFNetworkingTaskDidSuspendNotification object:nil]; +#endif + + [notificationCenter removeObserver:self name:AFNetworkingOperationDidStartNotification object:nil]; + [notificationCenter removeObserver:self name:AFNetworkingOperationDidFinishNotification object:nil]; +} + @end #endif diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIWebView+AFNetworking.h b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIWebView+AFNetworking.h old mode 100644 new mode 100755 similarity index 86% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIWebView+AFNetworking.h rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIWebView+AFNetworking.h index 202e8f4ea29..5d61d6a7406 --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIWebView+AFNetworking.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIWebView+AFNetworking.h @@ -1,6 +1,5 @@ // UIWebView+AFNetworking.h -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -28,12 +27,14 @@ #import +NS_ASSUME_NONNULL_BEGIN + @class AFHTTPRequestSerializer, AFHTTPResponseSerializer; @protocol AFURLRequestSerialization, AFURLResponseSerialization; /** This category adds methods to the UIKit framework's `UIWebView` class. The methods in this category provide increased control over the request cycle, including progress monitoring and success / failure handling. - + @discussion When using these category methods, make sure to assign `delegate` for the web view, which implements `–webView:shouldStartLoadWithRequest:navigationType:` appropriately. This allows for tapped links to be loaded through AFNetworking, and can ensure that `canGoBack` & `canGoForward` update their values correctly. */ @interface UIWebView (AFNetworking) @@ -50,16 +51,16 @@ /** Asynchronously loads the specified request. - + @param request A URL request identifying the location of the content to load. This must not be `nil`. @param progress A block object to be called when an undetermined number of bytes have been downloaded from the server. This block has no return value and takes three arguments: the number of bytes read since the last time the download progress block was called, the total bytes read, and the total bytes expected to be read during the request, as initially determined by the expected content size of the `NSHTTPURLResponse` object. This block may be called multiple times, and will execute on the main thread. @param success A block object to be executed when the request finishes loading successfully. This block returns the HTML string to be loaded by the web view, and takes two arguments: the response, and the response string. @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a single argument: the error that occurred. */ - (void)loadRequest:(NSURLRequest *)request - progress:(void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))progress - success:(NSString * (^)(NSHTTPURLResponse *response, NSString *HTML))success - failure:(void (^)(NSError *error))failure; + progress:(nullable void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))progress + success:(nullable NSString * (^)(NSHTTPURLResponse *response, NSString *HTML))success + failure:(nullable void (^)(NSError *error))failure; /** Asynchronously loads the data associated with a particular request with a specified MIME type and text encoding. @@ -72,12 +73,14 @@ @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a single argument: the error that occurred. */ - (void)loadRequest:(NSURLRequest *)request - MIMEType:(NSString *)MIMEType - textEncodingName:(NSString *)textEncodingName - progress:(void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))progress - success:(NSData * (^)(NSHTTPURLResponse *response, NSData *data))success - failure:(void (^)(NSError *error))failure; + MIMEType:(nullable NSString *)MIMEType + textEncodingName:(nullable NSString *)textEncodingName + progress:(nullable void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))progress + success:(nullable NSData * (^)(NSHTTPURLResponse *response, NSData *data))success + failure:(nullable void (^)(NSError *error))failure; @end +NS_ASSUME_NONNULL_END + #endif diff --git a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIWebView+AFNetworking.m b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIWebView+AFNetworking.m old mode 100644 new mode 100755 similarity index 94% rename from ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIWebView+AFNetworking.m rename to ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIWebView+AFNetworking.m index 525d02aeadc..93eacaa0c1b --- a/ios/SAPTracker/src/xcode/Pods/AFNetworking/UIKit+AFNetworking/UIWebView+AFNetworking.m +++ b/ios/SAPTracker/src/xcode/SAPTracker/Libraries/UIKit+AFNetworking/UIWebView+AFNetworking.m @@ -1,6 +1,5 @@ // UIWebView+AFNetworking.m -// -// Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com) +// Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -136,6 +135,11 @@ #pragma clang diagnostic ignored "-Wgnu" __strong __typeof(weakSelf) strongSelf = weakSelf; [strongSelf loadData:data MIMEType:(MIMEType ?: [operation.response MIMEType]) textEncodingName:(textEncodingName ?: [operation.response textEncodingName]) baseURL:[operation.response URL]]; + + if ([strongSelf.delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) { + [strongSelf.delegate webViewDidFinishLoad:strongSelf]; + } + #pragma clang diagnostic pop } failure:^(AFHTTPRequestOperation * __unused operation, NSError *error) { if (failure) { @@ -144,6 +148,10 @@ }]; [self.af_HTTPRequestOperation start]; + + if ([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) { + [self.delegate webViewDidStartLoad:self]; + } } @end diff --git a/ios/SAPTracker/src/xcode/SAPTracker/LicenseViewController.swift b/ios/SAPTracker/src/xcode/SAPTracker/LicenseViewController.swift index a8ab987aa11..e697c3d9c85 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/LicenseViewController.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/LicenseViewController.swift @@ -14,6 +14,7 @@ class LicenseViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() + navigationItem.title = Translation.LicenseView.Title.String if let file = NSBundle.mainBundle().pathForResource("Acknowledgements", ofType: "markdown") { let license = try? NSString(contentsOfFile: file, encoding: NSUTF8StringEncoding) if (license != nil) { diff --git a/ios/SAPTracker/src/xcode/SAPTracker/LocationData.swift b/ios/SAPTracker/src/xcode/SAPTracker/LocationData.swift new file mode 100644 index 00000000000..c5f7ea2edc8 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/LocationData.swift @@ -0,0 +1,34 @@ +// +// LocationData.swift +// SAPTracker +// +// Created by Raimund Wege on 06.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import UIKit +import CoreLocation + +class LocationData: NSObject { + + struct LocationValidation { + static let requiredAccuracy: CLLocationAccuracy = 10 + static let maxElapsedTime: NSTimeInterval = 10 + } + + var location: CLLocation + + init(location: CLLocation) { + self.location = location + super.init() + } + + var isValid: Bool { + get { + guard location.horizontalAccuracy >= 0 && location.horizontalAccuracy <= LocationValidation.requiredAccuracy else { return false } + guard location.timestamp.timeIntervalSinceDate(NSDate()) <= LocationValidation.maxElapsedTime else { return false } + return true; + } + } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/LocationManager.swift b/ios/SAPTracker/src/xcode/SAPTracker/LocationManager.swift index 79e8327c34d..ffc8f4f0674 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/LocationManager.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/LocationManager.swift @@ -1,5 +1,5 @@ // -// LocationController.swift +// LocationManager.swift // SAPTracker // // Created by computing on 17/10/14. @@ -9,16 +9,46 @@ import Foundation import CoreLocation -class LocationManager: NSObject, CLLocationManagerDelegate { +class LocationManager: NSObject { struct NotificationType { - static let locationServicesDisabled = "locationServicesDisabled" - static let trackingStarted = "trackingStarted" - static let trackingStopped = "trackingStopped" - static let newLocation = "newLocation" - static let locationManagerFailed = "locationManagerFailed" + static let Started = "LocationManager.Started" + static let Stopped = "LocationManager.Stopped" + static let Updated = "LocationManager.Updated" + static let Failed = "LocationManager.Failed" } + struct UserInfo { + static let Error = "NSError" + static let LocationData = "LocationData" + static let Status = "Status" + } + + enum Status: String { + case Tracking + case NotTracking + var description: String { + switch self { + case .Tracking: return Translation.LocationManager.Status.Tracking.String + case .NotTracking: return Translation.LocationManager.Status.NotTracking.String + } + } + } + + enum LocationManagerError: ErrorType { + case LocationServicesDenied + case LocationServicesDisabled + var description: String { + switch self { + case .LocationServicesDenied: return Translation.LocationManager.LocationServicesDeniedError.String + case .LocationServicesDisabled: return Translation.LocationManager.LocationServicesDisabledError.String + } + } + } + + private let locationManager: CLLocationManager! + private (set) var isTracking: Bool = false + class var sharedManager: LocationManager { struct Singleton { static let sharedManager = LocationManager() @@ -26,88 +56,79 @@ class LocationManager: NSObject, CLLocationManagerDelegate { return Singleton.sharedManager } - private var coreLocationManager: CLLocationManager = CLLocationManager() - - var isTracking: Bool = false - override init() { + locationManager = CLLocationManager() super.init() - coreLocationManager.delegate = self + setup() } - func startTracking() -> String? { - if (!CLLocationManager.locationServicesEnabled()) { - return NSLocalizedString("Please enable location services.", comment: "") - } - if (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.Denied) { - return NSLocalizedString("Please enable location services for this app.", comment: "") - } - if (coreLocationManager.respondsToSelector("requestAlwaysAuthorization")) { - coreLocationManager.requestAlwaysAuthorization() - } - - // Now try everything to allow the app to use the GPS sensor - // while in background - coreLocationManager.pausesLocationUpdatesAutomatically = false; + // MARK: - Setup + + private func setup() { + setupLocationManager() + } + + private func setupLocationManager() { + locationManager.pausesLocationUpdatesAutomatically = false; if #available(iOS 9, *) { - coreLocationManager.allowsBackgroundLocationUpdates = true; + locationManager.allowsBackgroundLocationUpdates = true; + } + locationManager.delegate = self + } + + // MARK: - Methods + + func startTracking() throws { + guard CLLocationManager.locationServicesEnabled() else { + throw LocationManagerError.LocationServicesDisabled + } + guard CLLocationManager.authorizationStatus() != CLAuthorizationStatus.Denied else { + throw LocationManagerError.LocationServicesDenied } - coreLocationManager.startUpdatingLocation() - coreLocationManager.startUpdatingHeading() - coreLocationManager.delegate = self + // Ask user to always track location + locationManager.requestAlwaysAuthorization() + + // Start location updates + locationManager.startUpdatingLocation() + locationManager.startUpdatingHeading() isTracking = true; - let notification = NSNotification(name: NotificationType.trackingStarted, object: self) + + // Send notification + let notification = NSNotification(name: NotificationType.Started, object: self) NSNotificationQueue.defaultQueue().enqueueNotification(notification, postingStyle: NSPostingStyle.PostASAP) - return nil } func stopTracking() { - coreLocationManager.stopUpdatingLocation() - coreLocationManager.stopUpdatingHeading() + + // Stop location updates + locationManager.stopUpdatingLocation() + locationManager.stopUpdatingHeading() isTracking = false; - let notification = NSNotification(name: NotificationType.trackingStopped, object: self) + + // Send notification + let notification = NSNotification(name: NotificationType.Stopped, object: self) + NSNotificationQueue.defaultQueue().enqueueNotification(notification, postingStyle: NSPostingStyle.PostASAP) + } + +} + +// MARK: - CLLocationManagerDelegate + +extension LocationManager: CLLocationManagerDelegate { + + func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { + guard let location = locations.last else { return } + let locationData = LocationData(location: location) + let userInfo = [UserInfo.LocationData: locationData] + let notification = NSNotification(name: NotificationType.Updated, object: self, userInfo: userInfo) + NSNotificationQueue.defaultQueue().enqueueNotification(notification, postingStyle: NSPostingStyle.PostASAP) + } + + func locationManager(manager: CLLocationManager, didFailWithError error: NSError) { + let userInfo = [UserInfo.Error: error] + let notification = NSNotification(name: NotificationType.Failed, object: self, userInfo: userInfo) NSNotificationQueue.defaultQueue().enqueueNotification(notification, postingStyle: NSPostingStyle.PostASAP) } - func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [CLLocation]!) { - let location = locations.last - let notification = NSNotification(name: NotificationType.newLocation, object: self, userInfo:LocationManager.dictionaryForLocation(location!)) - NSNotificationQueue.defaultQueue().enqueueNotification(notification, postingStyle: NSPostingStyle.PostASAP) - } - - func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) { - let notification = NSNotification(name: NotificationType.locationManagerFailed, object: self, userInfo: ["error": error]) - NSNotificationQueue.defaultQueue().enqueueNotification(notification, postingStyle: NSPostingStyle.PostASAP) - } - - // MARK: - - /* Create dictionary for location. */ - class func dictionaryForLocation(location: CLLocation) -> [String: AnyObject] { - return [ - "timestamp": location.timestamp.timeIntervalSince1970, - "latitude" : location.coordinate.latitude, - "longitude": location.coordinate.longitude, - "speed": location.speed, - "course": location.course, - "horizontalAccuracy": location.horizontalAccuracy, - "isValid": isLocationValid(location) - ] - } - - static let REQ_ACCURACY : CLLocationAccuracy = 10 - static let REQ_TIME : NSTimeInterval = 10 - class func isLocationValid(location: CLLocation) -> Bool { - let accuracy = location.horizontalAccuracy - let time = location.timestamp - let elapsed = time.timeIntervalSinceDate(NSDate()) - if elapsed > REQ_TIME { - return false - } - if accuracy < 0 || accuracy > REQ_ACCURACY { - return false - } - return true; - } - } diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Main.storyboard b/ios/SAPTracker/src/xcode/SAPTracker/Main.storyboard new file mode 100644 index 00000000000..8e2ed15f496 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Main.storyboard @@ -0,0 +1,1927 @@ + + + + + + + + + + OpenSans-Bold + OpenSans-Bold + OpenSans-Bold + OpenSans-Bold + OpenSans-Bold + OpenSans-Bold + + + OpenSans-Light + OpenSans-Light + OpenSans-Light + + + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + OpenSans + + + OpenSans-Semibold + OpenSans-Semibold + OpenSans-Semibold + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Preferences.swift b/ios/SAPTracker/src/xcode/SAPTracker/Preferences.swift new file mode 100644 index 00000000000..94d89bf17c8 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Preferences.swift @@ -0,0 +1,101 @@ +// +// Preferences.swift +// SAPTracker +// +// Created by Raimund Wege on 26.05.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import UIKit + +class Preferences: NSObject { + + struct NotificationType { + static let BatterySavingChanged = "BatterySavingChanged" + static let NewCheckInURLChanged = "NewCheckInURLChanged" + } + + struct UserInfo { + static let BatterySaving = "BatterySaving" + static let CheckInURL = "CheckInURL" + } + + struct PreferenceKey { + static let CodeConventionRead = "CodeConventionRead" + static let BatterySaving = "BatterySaving" + static let NewCheckInURL = "NewCheckInURL" + static let TermsAccepted = "TermsAccepted" + static let UUID = "udid" + } + + private static let preferences = NSUserDefaults.standardUserDefaults() + + // MARK: - CodeConventionRead + + class var codeConventionRead: Bool { + get { + return preferences.boolForKey(PreferenceKey.CodeConventionRead) + } + set(value) { + preferences.setBool(value, forKey:PreferenceKey.CodeConventionRead) + preferences.synchronize() + } + } + + // MARK: - NewCheckInURL + + class var newCheckInURL: String? { + get { + return preferences.stringForKey(PreferenceKey.NewCheckInURL) + } + set(value) { + preferences.setObject(value, forKey: PreferenceKey.NewCheckInURL) + preferences.synchronize() + + // Send notification + var userInfo = [String: AnyObject]() + userInfo[UserInfo.CheckInURL] = value + let notification = NSNotification(name: NotificationType.NewCheckInURLChanged, object: self, userInfo: userInfo) + NSNotificationQueue.defaultQueue().enqueueNotification(notification, postingStyle: NSPostingStyle.PostASAP) + } + } + + // MARK: - TermsAccepted + + class var termsAccepted: Bool { + get { + return preferences.boolForKey(PreferenceKey.TermsAccepted) + } + set(value) { + preferences.setBool(value, forKey:PreferenceKey.TermsAccepted) + preferences.synchronize() + } + } + + // MARK: - UUID + + static private(set) var uuid: String? = { + let uuid = preferences.stringForKey(PreferenceKey.UUID) ?? NSUUID().UUIDString.lowercaseString + preferences.setObject(uuid, forKey: PreferenceKey.UUID) + preferences.synchronize() + return uuid + }() + + // MARK: - BatterySaving + + class var batterySaving: Bool { + get { + return preferences.boolForKey(PreferenceKey.BatterySaving) + } + set(value) { + preferences.setBool(value, forKey: PreferenceKey.BatterySaving) + preferences.synchronize() + + // Send notification + let userInfo = [UserInfo.BatterySaving: value] + let notification = NSNotification(name: NotificationType.BatterySavingChanged, object: self, userInfo: userInfo) + NSNotificationQueue.defaultQueue().enqueueNotification(notification, postingStyle: NSPostingStyle.PostASAP) + } + } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/QRCodeData.swift b/ios/SAPTracker/src/xcode/SAPTracker/QRCodeData.swift deleted file mode 100644 index 35520fbd661..00000000000 --- a/ios/SAPTracker/src/xcode/SAPTracker/QRCodeData.swift +++ /dev/null @@ -1,52 +0,0 @@ -// -// QRCodeManager.swift -// SAPTracker -// -// Created by computing on 22/10/14. -// Copyright (c) 2014 com.sap.sailing. All rights reserved. -// - -import Foundation - -public class QRCodeData { - - struct Keys { - static let eventId = "event_id" - static let leaderBoardName = "leaderboard_name" - static let competitorId = "competitor_id" - } - - public var serverUrl: String? - public var eventId: String? - public var leaderBoardName: String? - public var competitorId: String? - - public init() { - } - - public func parseString(urlString: String) -> Bool { - let url = NSURL(string: urlString) - if (url == nil || url!.host == nil || url!.query == nil) { - return false - } - - // Set server url - serverUrl = url!.scheme + "://" + url!.host! - if ((url!.port) != nil) { - serverUrl! += ":" + url!.port!.stringValue - } - - // Get query parameter - eventId = getQueryStringParameter(url!.absoluteString, param: QRCodeData.Keys.eventId) // queryStringDictionary[QRCodeData.Keys.eventId] - leaderBoardName = getQueryStringParameter(url!.absoluteString, param: QRCodeData.Keys.leaderBoardName) - competitorId = getQueryStringParameter(url!.absoluteString, param: QRCodeData.Keys.competitorId) // queryStringDictionary[QRCodeData.Keys.competitorId] - return eventId != nil && leaderBoardName != nil && competitorId != nil - } - - func getQueryStringParameter(url: String, param: String) -> String? { - return NSURLComponents(string: url)?.queryItems?.filter({ (item) -> Bool in - item.name == param - }).first?.value?.stringByRemovingPercentEncoding; - } - -} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/QRCodeManager.swift b/ios/SAPTracker/src/xcode/SAPTracker/QRCodeManager.swift deleted file mode 100644 index 671a4cb884e..00000000000 --- a/ios/SAPTracker/src/xcode/SAPTracker/QRCodeManager.swift +++ /dev/null @@ -1,216 +0,0 @@ -// -// QRCodeManager.swift -// SAPTracker -// -// Created by computing on 17/11/14. -// Copyright (c) 2014 com.sap.sailing. All rights reserved. -// - -import Foundation -import UIKit -import AVFoundation - -@objc protocol QRCodeManagerDelegate { - optional var activityIndicatorView: UIActivityIndicatorView { get } - optional func qrCodeOK() - optional func qrCodeCancel() -} - -class QRCodeManager : NSObject, UIAlertViewDelegate { - - enum AlertView: Int { - case IncorrectQRCode, AcceptMapping, ServerError - } - - private var delegate: QRCodeManagerDelegate - private var qrcodeData: QRCodeData? - private var eventDictionary: [String: AnyObject]? - private var leaderBoardDictionary: [String: AnyObject]? - private var competitorDictionary: [String: AnyObject]? - private var teamImageURL: String? - - init(delegate: QRCodeManagerDelegate) { - self.delegate = delegate - } - - class func deviceCanReadQRCodes() -> Bool { - var session: AVCaptureSession! - var output: AVCaptureMetadataOutput! - (session, output) = QRCodeManager.setUpCaptureSession(nil) - let types = output.availableMetadataObjectTypes as! [String] - var deviceCanReadQRCodes = false - for type in types { - if type == AVMetadataObjectTypeQRCode { - deviceCanReadQRCodes = true - break - } - } - return deviceCanReadQRCodes - } - - class func setUpCaptureSession(delegate: AVCaptureMetadataOutputObjectsDelegate?) -> (session: AVCaptureSession!, output: AVCaptureMetadataOutput!) { - let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo) - let output = AVCaptureMetadataOutput() - let session = AVCaptureSession() - do { - let input = try AVCaptureDeviceInput(device: device); - output.setMetadataObjectsDelegate(delegate, queue: dispatch_get_main_queue()) - session.canSetSessionPreset(AVCaptureSessionPresetHigh) - if session.canAddInput(input) { - session.addInput(input) - } - if session.canAddOutput(output) { - session.addOutput(output) - } - } catch { - print(error) - } - return (session, output) - } - - func parseUrl(url: NSString) { - - qrcodeData = QRCodeData() - let parseSuccess = qrcodeData!.parseString(url as String) - if !parseSuccess { - let alertView = UIAlertView(title: NSLocalizedString("Incorrect QR Code", comment: ""), message: "", delegate: self, cancelButtonTitle: nil, otherButtonTitles: NSLocalizedString("Cancel", comment: "")) - alertView.tag = AlertView.IncorrectQRCode.rawValue; - alertView.show() - return - } - - self.delegate.activityIndicatorView?.startAnimating() - - let checkIn = DataManager.sharedManager.getCheckIn(qrcodeData!.eventId!, leaderBoardName: qrcodeData!.leaderBoardName!, competitorId: qrcodeData!.competitorId!) - - // already checked in - if checkIn != nil { - - // overwrite server URL in case its changed - checkIn!.serverUrl = qrcodeData!.serverUrl! - self.delegate.activityIndicatorView?.stopAnimating() - self.delegate.qrCodeOK?() - - } else { - APIManager.sharedManager.initManager(qrcodeData!.serverUrl!) - - // get event - APIManager.sharedManager.getEvent(qrcodeData!.eventId, - success: { (operation, eventResponseObject) -> Void in - self.eventDictionary = eventResponseObject as? [String: AnyObject] - APIManager.sharedManager.getLeaderBoard(self.qrcodeData!.leaderBoardName, - - // get leader board - success: { (operation, leaderBoardResponseObject) -> Void in - self.leaderBoardDictionary = leaderBoardResponseObject as? [String: AnyObject] - APIManager.sharedManager.getCompetitor(self.qrcodeData!.competitorId, - - // get competitor - success: { (operation, competitorResponseObject) -> Void in - - APIManager.sharedManager.teamImage(self.qrcodeData!.competitorId, result: { (imageUrl) -> Void in - - self.delegate.activityIndicatorView?.stopAnimating() - - self.competitorDictionary = competitorResponseObject as? [String: AnyObject] - - self.teamImageURL = imageUrl - - let competitorName = (self.competitorDictionary!["name"]) as! String - let leaderBoardName = (self.leaderBoardDictionary!["name"]) as! String - let sailId = (self.competitorDictionary!["sailID"]) as! String - let title = String(format:NSLocalizedString("Hello %@. Welcome to %@. You are registered as %@.", comment: ""), competitorName, leaderBoardName, sailId) - let alertView = UIAlertView(title: title, message: "", delegate: self, cancelButtonTitle: NSLocalizedString("Cancel", comment: ""), otherButtonTitles: NSLocalizedString("OK", comment: "")) - alertView.tag = AlertView.AcceptMapping.rawValue; - alertView.show() - }) - - }, failure: { (operation, error) -> Void in - self.delegate.activityIndicatorView?.stopAnimating() - let title = String(format: NSLocalizedString("Couldn't get competitor %@", comment: ""), self.qrcodeData!.competitorId!) - let alertView = UIAlertView(title: title, message: error.localizedDescription, delegate: self, cancelButtonTitle: NSLocalizedString("Cancel", comment: "")) - alertView.tag = AlertView.ServerError.rawValue; - alertView.show() - - }) }, failure: { (operation, error) -> Void in - self.delegate.activityIndicatorView?.stopAnimating() - let title = String(format: NSLocalizedString("Couldn't get leader board %@", comment: ""), self.qrcodeData!.leaderBoardName!) - let alertView = UIAlertView(title: title, message: error.localizedDescription, delegate: self, cancelButtonTitle: NSLocalizedString("Cancel", comment: "")) - alertView.tag = AlertView.ServerError.rawValue; - alertView.show() - }) - - }, failure: { (operation, error) -> Void in - self.delegate.activityIndicatorView?.stopAnimating() - let title = String(format: NSLocalizedString("Couldn't get event %@", comment: ""), self.qrcodeData!.eventId!) - let alertView = UIAlertView(title: title, message: error.localizedDescription, delegate: self, cancelButtonTitle: NSLocalizedString("Cancel", comment: "")) - alertView.tag = AlertView.ServerError.rawValue; - alertView.show() - }) - } - } - - - /* Alert view delegate */ - func alertView(alertView: UIAlertView, clickedButtonAtIndex buttonIndex: Int) { - switch alertView.tag { - // Stop tracking? - case AlertView.AcceptMapping.rawValue: - switch buttonIndex { - case alertView.cancelButtonIndex: - cancel() - break - default: - checkIn() - break - } - break - default: - cancel() - break - } - } - - private func checkIn() { - let leaderBoardName = leaderBoardDictionary!["name"] as! String - let competitorId = competitorDictionary!["id"] as! String - let now = NSDate() - let fromMillis = Int64(now.timeIntervalSince1970 * 1000) - let checkIn = DataManager.sharedManager.newCheckIn() - checkIn.serverUrl = self.qrcodeData!.serverUrl! - checkIn.eventId = self.qrcodeData!.eventId! - checkIn.leaderBoardName = self.qrcodeData!.leaderBoardName! - checkIn.competitorId = self.qrcodeData!.competitorId! - checkIn.lastSyncDate = NSDate() - checkIn.imageUrl = teamImageURL - - APIManager.sharedManager.checkIn(leaderBoardName, competitorId: competitorId, deviceUuid: DeviceUDIDManager.UDID, pushDeviceId: "", fromMillis: fromMillis, - success: { (operation, eventResponseObject) -> Void in - - // create core data objects - let event = DataManager.sharedManager.newEvent(checkIn) - event.initWithDictionary(self.eventDictionary!) - let leaderBoard = DataManager.sharedManager.newLeaderBoard(checkIn) - leaderBoard.initWithDictionary(self.leaderBoardDictionary!) - let competitor = DataManager.sharedManager.newCompetitor(checkIn) - competitor.initWithDictionary(self.competitorDictionary!) - DataManager.sharedManager.saveContext() - - self.delegate.qrCodeOK?() - }, failure: { (operation, error) -> Void in - self.delegate.activityIndicatorView?.stopAnimating() - let title = String(format:NSLocalizedString("Couldn't check-in to %@", comment: ""), leaderBoardName); - let alertView = UIAlertView(title: title, message: error.localizedDescription, delegate: self, cancelButtonTitle: NSLocalizedString("Cancel", comment: "")) - alertView.tag = AlertView.ServerError.rawValue; - alertView.show() - }) - } - - private func cancel() { - eventDictionary = nil - leaderBoardDictionary = nil - competitorDictionary = nil - delegate.qrCodeCancel?() - } - -} \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Regatta+CoreDataProperties.swift b/ios/SAPTracker/src/xcode/SAPTracker/Regatta+CoreDataProperties.swift new file mode 100644 index 00000000000..c8141fc3cd1 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Regatta+CoreDataProperties.swift @@ -0,0 +1,26 @@ +// +// Regatta+CoreDataProperties.swift +// SAPTracker +// +// Created by Raimund Wege on 04.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// +// Choose "Create NSManagedObject Subclass…" from the Core Data editor menu +// to delete and recreate this implementation file for your updated model. +// + +import Foundation +import CoreData + +extension Regatta { + + @NSManaged var serverURL: String + @NSManaged var teamImageData: NSData? + @NSManaged var teamImageRetry: Bool + @NSManaged var teamImageURL: String? + @NSManaged var competitor: Competitor + @NSManaged var event: Event + @NSManaged var gpsFixes: NSSet? + @NSManaged var leaderboard: Leaderboard + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Regatta.swift b/ios/SAPTracker/src/xcode/SAPTracker/Regatta.swift new file mode 100644 index 00000000000..a440c395a97 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Regatta.swift @@ -0,0 +1,33 @@ +// +// Regatta.swift +// SAPTracker +// +// Created by Raimund Wege on 04.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import Foundation +import CoreData + +@objc(Regatta) +class Regatta: NSManagedObject { + + func updateWithRegattaData(regattaData: RegattaData) { + serverURL = regattaData.serverURL + teamImageURL = regattaData.teamImageURL + teamImageRetry = false + event.updateWithEventData(regattaData.eventData) + leaderboard.updateWithLeaderboardData(regattaData.leaderboardData) + competitor.updateWithCompetitorData(regattaData.competitorData) + } + + func eventURL() -> NSURL? { + return NSURL(string: "\(serverURL)/gwt/Home.html?navigationTab=Regattas#EventPlace:eventId=\(event.eventID)") + } + + func leaderboardURL() -> NSURL? { + guard let name = leaderboard.nameWithQueryAllowedCharacters() else { return nil } + return NSURL(string: "\(serverURL)/gwt/Leaderboard.html?name=\(name)&showRaceDetails=false&embedded=true&hideToolbar=true") + } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/RegattaController.swift b/ios/SAPTracker/src/xcode/SAPTracker/RegattaController.swift new file mode 100644 index 00000000000..9f5afaf4813 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/RegattaController.swift @@ -0,0 +1,165 @@ +// +// RegattaController.swift +// SAPTracker +// +// Created by Raimund Wege on 05.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import UIKit + +class RegattaController: NSObject { + + let regatta: Regatta + + var sendingBackgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid + var sendingDate: NSDate = NSDate() + + private (set) var isTracking: Bool = false + + init(regatta: Regatta) { + self.regatta = regatta + super.init() + subscribeForNotifications() + } + + deinit { + unsubscribeFromNotifications() + } + + // MARK: - Notifications + + private func subscribeForNotifications() { + NSNotificationCenter.defaultCenter().addObserver(self, + selector:#selector(locationManagerUpdated(_:)), + name:LocationManager.NotificationType.Updated, + object: nil + ) + NSNotificationCenter.defaultCenter().addObserver(self, + selector:#selector(batterySavingChanged(_:)), + name:Preferences.NotificationType.BatterySavingChanged, + object: nil + ) + } + + private func unsubscribeFromNotifications() { + NSNotificationCenter.defaultCenter().removeObserver(self) + } + + @objc private func locationManagerUpdated(notification: NSNotification) { + dispatch_async(dispatch_get_main_queue(), { + guard self.isTracking else { return } + guard let locationData = notification.userInfo?[LocationManager.UserInfo.LocationData] as? LocationData else { return } + guard locationData.isValid else { return } + let gpsFix = CoreDataManager.sharedManager.newGPSFix(self.regatta) + gpsFix.updateWithLocationData(locationData) + CoreDataManager.sharedManager.saveContext() + if self.sendingDate.compare(NSDate()) == .OrderedAscending { + self.sendingDate = NSDate().dateByAddingTimeInterval(BatteryManager.sharedManager.sendingPeriod) + self.beginGPSFixSendingInBackgroundTask() + } + }) + } + + @objc private func batterySavingChanged(notification: NSNotification) { + dispatch_async(dispatch_get_main_queue(), { + guard let batterySaving = notification.userInfo?[Preferences.UserInfo.BatterySaving] as? Bool else { return } + if !batterySaving { + self.sendingDate = NSDate() // Send next GPS fixes soon as possible + } + }) + } + + // MARK: - Background Task + + private func beginGPSFixSendingInBackgroundTask() { + sendingBackgroundTask = UIApplication.sharedApplication().beginBackgroundTaskWithName("Send GPS Fixes", expirationHandler: { + self.endGPSFixSendingInBackgroundTask() + }) + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { + self.gpsFixController.sendSlice({ (withSuccess) in + self.endGPSFixSendingInBackgroundTask() + }) + }) + } + + private func endGPSFixSendingInBackgroundTask() { + UIApplication.sharedApplication().endBackgroundTask(sendingBackgroundTask) + sendingBackgroundTask = UIBackgroundTaskInvalid + } + + // MARK: - Update + + func update(completion: () -> Void) { + let regattaData = RegattaData(serverURL: regatta.serverURL, + eventID: regatta.event.eventID, + leaderboardName: regatta.leaderboard.name, + competitorID: regatta.competitor.competitorID + ) + requestManager.getRegattaData(regattaData, + success: { (regattaData) in self.updateSuccess(regattaData, completion: completion) }, + failure: { (error) in self.updateFailure(completion) } + ) + } + + func updateSuccess(regattaData: RegattaData, completion: () -> Void) { + regatta.event.updateWithEventData(regattaData.eventData) + regatta.leaderboard.updateWithLeaderboardData(regattaData.leaderboardData) + regatta.competitor.updateWithCompetitorData(regattaData.competitorData) + CoreDataManager.sharedManager.saveContext() + completion() + } + + func updateFailure(completion: () -> Void) { + completion() + } + + // MARK: - Tracking + + func startTracking() throws { + isTracking = false + try LocationManager.sharedManager.startTracking() + isTracking = true + } + + func stopTracking() { + isTracking = false + LocationManager.sharedManager.stopTracking() + } + + // MARK: - TeamImage + + func postTeamImageData(imageData: NSData, + success: (teamImageURL: String) -> Void, + failure: (error: RequestManager.Error) -> Void) + { + requestManager.postTeamImageData(imageData, + competitorID: regatta.competitor.competitorID, + success: success, + failure: failure + ) + } + + // MARK: - CheckOut + + func checkOut(completion: (withSuccess: Bool) -> Void) { + requestManager.postCheckOut(regatta.leaderboard.name, + competitorId: regatta.competitor.competitorID, + success: { () in completion(withSuccess: true) }, + failure: { (error) in completion(withSuccess: false) } + ) + } + + // MARK: - Properties + + lazy var gpsFixController: GPSFixController = { + let gpsFixController = GPSFixController(regatta: self.regatta) + return gpsFixController + }() + + lazy var requestManager: RequestManager = { + let requestManager = RequestManager(baseURLString: self.regatta.serverURL) + return requestManager + }() + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/RegattaData.swift b/ios/SAPTracker/src/xcode/SAPTracker/RegattaData.swift new file mode 100644 index 00000000000..1f80e9203f8 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/RegattaData.swift @@ -0,0 +1,93 @@ +// +// RegattaData.swift +// SAPTracker +// +// Created by Raimund Wege on 25.05.16. +// Copyright (c) 2014 com.sap.sailing. All rights reserved. +// + +import Foundation + +public class RegattaData: NSObject { + + private struct ItemNames { + static let EventID = "event_id" + static let LeaderboardName = "leaderboard_name" + static let CompetitorID = "competitor_id" + } + + let serverURL: String + let eventID: String + let leaderboardName: String + let competitorID: String + + var eventData = EventData() + var leaderboardData = LeaderboardData() + var competitorData = CompetitorData() + var teamImageURL: String? + + override init() { + serverURL = "" + eventID = "" + leaderboardName = "" + competitorID = "" + super.init() + } + + init(serverURL: String, + eventID: String, + leaderboardName: String, + competitorID: String) + { + self.serverURL = serverURL + self.eventID = eventID + self.leaderboardName = leaderboardName + self.competitorID = competitorID + super.init() + } + + init(regatta: Regatta) { + serverURL = regatta.serverURL + eventID = regatta.event.eventID + competitorID = regatta.competitor.competitorID + leaderboardName = regatta.leaderboard.name + super.init() + } + + convenience init?(url: NSURL) { + guard let host = url.host else { return nil } + guard let components = NSURLComponents(string: url.absoluteString) else { return nil } + + // Set server URL + let serverURL = url.scheme + "://" + host + (url.port != nil ? ":" + url.port!.stringValue : "") + + // In query component replace '+' occurrences with '%20' as a workaround for bug 3664 + components.percentEncodedQuery = components.percentEncodedQuery?.stringByReplacingOccurrencesOfString("+", withString: "%20") + let queryItems = components.queryItems + + // Get check-in items + guard let eventID = RegattaData.queryItemValue(queryItems, itemName: ItemNames.EventID) else { return nil } + guard let leaderboardName = RegattaData.queryItemValue(queryItems, itemName: ItemNames.LeaderboardName) else { return nil } + guard let competitorID = RegattaData.queryItemValue(queryItems, itemName: ItemNames.CompetitorID) else { return nil } + + // Init with values + self.init(serverURL: serverURL, + eventID: eventID, + leaderboardName: leaderboardName, + competitorID: competitorID) + } + + convenience init?(urlString: String) { + guard let url = NSURL(string: urlString) else { return nil } + + // Init with URL + self.init(url: url) + } + + // MARK: - Helper + + class private func queryItemValue(queryItems: [NSURLQueryItem]?, itemName: String) -> String? { + return queryItems?.filter({(item) -> Bool in item.name == itemName}).first?.value + } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/RegattaViewController.swift b/ios/SAPTracker/src/xcode/SAPTracker/RegattaViewController.swift index 8d7c50617f3..8d30292a170 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/RegattaViewController.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/RegattaViewController.swift @@ -7,262 +7,374 @@ // import Foundation -import CoreLocation -import Darwin -class RegattaViewController : UIViewController, UIActionSheetDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UIAlertViewDelegate { +class RegattaViewController : UIViewController, UINavigationControllerDelegate { - enum ActionSheet: Int { - case Menu + private struct Segue { + static let About = "About" + static let Leaderboard = "Leaderboard" + static let Settings = "Settings" + static let Tracking = "Tracking" } - enum AlertView: Int { - case CheckOut, Image, UploadFailed - } - - struct RegattaViewUserDefaults { - static let UploadDidFail = "UploadDidFail" - } - - var sourceTypes = [UIImagePickerControllerSourceType]() - var sourceTypeNames = [String]() - @IBOutlet weak var imageView: UIImageView! - @IBOutlet weak var yourTeamPhotoButton: UIButton! - @IBOutlet weak var editTeamPhotoButton: UIButton! - @IBOutlet weak var retryUploadTeamPhotoButton: UIButton! - @IBOutlet weak var nameLabel: UILabel! - @IBOutlet weak var flagImageView: UIImageView! - @IBOutlet weak var sailLabel: UILabel! + @IBOutlet weak var teamImageView: UIImageView! + @IBOutlet weak var teamImageAddButton: UIButton! + @IBOutlet weak var teamImageEditButton: UIButton! + @IBOutlet weak var teamImageRetryButton: UIButton! + @IBOutlet weak var competitorNameLabel: UILabel! + @IBOutlet weak var competitorFlagImageView: UIImageView! + @IBOutlet weak var competitorSailLabel: UILabel! @IBOutlet weak var regattaStartLabel: UILabel! - @IBOutlet weak var daysHeight: NSLayoutConstraint! - @IBOutlet weak var daysLabel: UILabel! - @IBOutlet weak var hoursHeight: NSLayoutConstraint! - @IBOutlet weak var hoursLabel: UILabel! - @IBOutlet weak var minutesHeight: NSLayoutConstraint! - @IBOutlet weak var minutesLabel: UILabel! - @IBOutlet weak var lastSyncLabel: UILabel! - @IBOutlet weak var leaderBoardButton: UIButton! - @IBOutlet weak var openEventButton: UIButton! + @IBOutlet weak var countdownView: UIView! + @IBOutlet weak var countdownViewHeight: NSLayoutConstraint! + @IBOutlet weak var countdownDaysLabel: UILabel! + @IBOutlet weak var countdownDaysTitleLabel: UILabel! + @IBOutlet weak var countdownHoursLabel: UILabel! + @IBOutlet weak var countdownHoursTitleLabel: UILabel! + @IBOutlet weak var countdownMinutesLabel: UILabel! + @IBOutlet weak var countdownMinutesTitleLabel: UILabel! + @IBOutlet weak var leaderboardButton: UIButton! + @IBOutlet weak var eventButton: UIButton! @IBOutlet weak var startTrackingButton: UIButton! - @IBOutlet weak var leaderBoardButtonHeight: NSLayoutConstraint! - @IBOutlet weak var announcementsLabel: PaddedLabel! + @IBOutlet weak var announcementLabel: UILabel! - var dateFormatter: NSDateFormatter + var regatta: Regatta! - var isFinished: Bool = false - let secondsInDay: Double = 60 * 60 * 24 - let secondsInHour: Double = 60 * 60 - var loop: NSTimer? - - /* Setup date formatter for last sync. */ - required init(coder aDecoder: NSCoder) { - dateFormatter = NSDateFormatter() - dateFormatter.dateFormat = "MMM d, yyyy, h:mm a" // As per request - see mail 19.02.2016 - super.init(coder: aDecoder)! - } - - var uploadKey: String { - return RegattaViewUserDefaults.UploadDidFail + "_" + DataManager.sharedManager.selectedCheckIn!.competitorId - } + var countdownTimer: NSTimer? override func viewDidLoad() { - - // set values - navigationItem.title = DataManager.sharedManager.selectedCheckIn!.leaderBoardName - - openEventButton.setTitle(NSLocalizedString("Show Event", comment: ""), forState: UIControlState.Normal) - - retryUploadTeamPhotoButton.hidden = !NSUserDefaults.standardUserDefaults().boolForKey(uploadKey) - - // set regatta image, either load it from server or load from core data - if DataManager.sharedManager.selectedCheckIn?.userImage != nil { - imageView.image = UIImage(data: DataManager.sharedManager.selectedCheckIn!.userImage!) - self.yourTeamPhotoButton.hidden = true - } else if DataManager.sharedManager.selectedCheckIn?.imageUrl != nil { - let imageUrl = NSURL(string: DataManager.sharedManager.selectedCheckIn!.imageUrl!) - let urlRequest = NSURLRequest(URL: imageUrl!) - imageView.setImageWithURLRequest(urlRequest, - placeholderImage: nil, - success: { (request:NSURLRequest!,response:NSHTTPURLResponse!, image:UIImage!) -> Void in - self.imageView.image = image - self.yourTeamPhotoButton.hidden = true - }, - failure: { (request:NSURLRequest!,response:NSHTTPURLResponse!, error:NSError!) -> Void in - self.editTeamPhotoButton.hidden = true - self.yourTeamPhotoButton.hidden = !self.retryUploadTeamPhotoButton.hidden - } - ) - } else { - self.editTeamPhotoButton.hidden = true - self.yourTeamPhotoButton.hidden = !self.retryUploadTeamPhotoButton.hidden - } - if (DataManager.sharedManager.selectedCheckIn?.competitor != nil) { - let competitor = DataManager.sharedManager.selectedCheckIn!.competitor! - nameLabel.text = competitor.name - flagImageView.image = UIImage(named: competitor.countryCode) - sailLabel.text = competitor.sailId - } - checkRegattaStatus() - - // get image sources - if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera) { - sourceTypes.append(UIImagePickerControllerSourceType.Camera) - sourceTypeNames.append(NSLocalizedString("Camera", comment: "")) - } - if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary) { - sourceTypes.append(UIImagePickerControllerSourceType.PhotoLibrary) - sourceTypeNames.append(NSLocalizedString("Photo Library", comment: "")) - } - - // point to events API server - APIManager.sharedManager.initManager(DataManager.sharedManager.selectedCheckIn!.serverUrl) - super.viewDidLoad() + setup() + update() } - override func viewDidAppear(animated: Bool) { - super.viewDidAppear(animated) + override func viewWillAppear(animated: Bool) { + super.viewWillAppear(animated) + refresh() } - override func viewWillDisappear(animated: Bool) { - super.viewWillDisappear(animated) - loop?.invalidate() + // MARK: - Setup + + private func setup() { + setupButtons() + setupCountdownTimer() + setupLocalization() + setupNavigationBar() } - override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) { - checkRegattaStatus() + private func setupButtons() { + eventButton.setBackgroundImage(Images.BlueHighlighted, forState: .Highlighted) + leaderboardButton.setBackgroundImage(Images.BlueHighlighted, forState: .Highlighted) + startTrackingButton.setBackgroundImage(Images.GreenHighlighted, forState: .Highlighted) } - // MARK: - - func checkRegattaStatus() { - if DataManager.sharedManager.selectedCheckIn == nil { - return + private func setupCountdownTimer() { + countdownTimer?.invalidate() + countdownTimer = NSTimer.scheduledTimerWithTimeInterval(1, + target: self, + selector: #selector(RegattaViewController.countdownTimerTick), + userInfo: nil, + repeats: true + ) + countdownTimerTick() + } + + private func setupLocalization() { + countdownDaysTitleLabel.text = Translation.RegattaView.CountdownDaysTitleLabel.Text.String + countdownHoursTitleLabel.text = Translation.RegattaView.CountdownHoursTitleLabel.Text.String + countdownMinutesTitleLabel.text = Translation.RegattaView.CountdownMinutesTitleLabel.Text.String + eventButton.setTitle(Translation.RegattaView.EventButton.Title.String, forState: .Normal) + leaderboardButton.setTitle(Translation.LeaderboardView.Title.String, forState: .Normal) + startTrackingButton.setTitle(Translation.RegattaView.StartTrackingButton.Title.String, forState: .Normal) + announcementLabel.text = Translation.RegattaView.AnnouncementLabel.Text.String + } + + private func setupNavigationBar() { + navigationItem.titleView = TitleView(title: regatta.event.name, subtitle: regatta.leaderboard.name) + navigationController?.navigationBar.setNeedsLayout() + } + + // MARK: - Update + + private func update() { + SVProgressHUD.show() + regattaController.update { + self.refresh() + SVProgressHUD.popActivity() } - - let now = NSDate() - - isFinished = false - - // reset views - lastSyncLabel.hidden = true - if DataManager.sharedManager.selectedCheckIn!.lastSyncDate != nil { - lastSyncLabel.text = NSLocalizedString("Last sync", comment: "") + " " + dateFormatter.stringFromDate(DataManager.sharedManager.selectedCheckIn!.lastSyncDate!) + } + + // MARK: - Refresh + + private func refresh() { + refreshCompetitor() + refreshTeamImage() + } + + private func refreshCompetitor() { + competitorNameLabel.text = regatta.competitor.name + competitorFlagImageView.image = UIImage(named: regatta.competitor.countryCode) + competitorSailLabel.text = regatta.competitor.sailID + } + + private func refreshTeamImage() { + if let imageData = regatta.teamImageData { + teamImageView.image = UIImage(data: imageData) + if regatta.teamImageRetry { + refreshTeamImageButtons(showAddButton: false, showEditButton: true, showRetryButton: true) + } else { + self.refreshTeamImageButtons(showAddButton: false, showEditButton: true, showRetryButton: false) + setTeamImageWithURLRequest(regatta.teamImageURL, completion: { (withSuccess) in + self.refreshTeamImageButtons(showAddButton: false, showEditButton: true, showRetryButton: false) + }) + } } else { - lastSyncLabel.text = nil - } - startTrackingButton.setTitle(NSLocalizedString("Start Tracking", comment: ""), forState: UIControlState.Normal) - announcementsLabel.text = NSLocalizedString("Please listen for announcements", comment: "") - - if DataManager.sharedManager.selectedCheckIn?.event != nil { - let event = DataManager.sharedManager.selectedCheckIn!.event! - -// // finished -// if now.timeIntervalSinceDate(event.endDate) > 0 { -// isFinished = true -// regattaStartLabel.text = NSLocalizedString("Thank you for participating!", comment: "") -// leaderBoardButtonHeight.constant = ButtonHeight.smallButtonPortrait -// daysHeight.constant = 0 -// hoursHeight.constant = 0 -// minutesHeight.constant = 0 -// startTrackingButton.setTitle(NSLocalizedString("Check-Out", comment: ""), forState: UIControlState.Normal) -// startTrackingButton.backgroundColor = UIColor(hex: 0xEFAD00) -// announcementsLabel.text = " " -// } -// else - - // before race - if now.timeIntervalSinceDate(event.startDate) < 0 { - regattaStartLabel.text = NSLocalizedString("Regatta will start in", comment: "") - lastSyncLabel.hidden = false - leaderBoardButtonHeight.constant = 0 - let delta = floor(now.timeIntervalSinceDate(event.startDate)) * -1 - let days = floor(delta / secondsInDay) - let hours = floor((delta - days * secondsInDay) / secondsInHour) - let minutes = floor((delta - days * secondsInDay - hours * secondsInHour) / 60.0) - daysLabel.text = String(format: "%.0f", arguments: [days]) - hoursLabel.text = String(format: "%.0f", arguments: [hours]) - minutesLabel.text = String(format: "%.0f", arguments: [minutes]) - loop?.invalidate() - loop = NSTimer(timeInterval: 60, target: self, selector: "checkRegattaStatus", userInfo: nil, repeats: false) - NSRunLoop.currentRunLoop().addTimer(loop!, forMode:NSRunLoopCommonModes) - } - // during race - else { - regattaStartLabel.text = NSLocalizedString("Regatta in progress", comment: "") - daysHeight.constant = 0 - hoursHeight.constant = 0 - minutesHeight.constant = 0 - leaderBoardButtonHeight.constant = ButtonHeight.smallButtonPortrait - lastSyncLabel.hidden = false - } + self.refreshTeamImageButtons(showAddButton: true, showEditButton: false, showRetryButton: false) + setTeamImageWithURLRequest(regatta.teamImageURL, completion: { (withSuccess) in + self.refreshTeamImageButtons(showAddButton: !withSuccess, showEditButton: withSuccess, showRetryButton: false) + }) } } - @IBAction func showEvent(sender: UIButton) { - let serverUrl = DataManager.sharedManager.selectedCheckIn!.serverUrl - let eventId = DataManager.sharedManager.selectedCheckIn!.eventId - - let url = "\(serverUrl)/gwt/Home.html?navigationTab=Regattas#EventPlace:eventId=\(eventId)" - UIApplication.sharedApplication().openURL(NSURL(string: url)!) - } - - - // MARK: - Menu - - @IBAction func showMenuActionSheet(sender: AnyObject) { - let actionSheet = UIActionSheet(title: nil, delegate: self, cancelButtonTitle: nil, destructiveButtonTitle: nil, otherButtonTitles: "Check-Out", "Settings", "Edit Photo", "Cancel") - actionSheet.tag = ActionSheet.Menu.rawValue - actionSheet.cancelButtonIndex = 3 - actionSheet.showInView(self.view) + private func refreshTeamImageButtons(showAddButton showAddButton: Bool, showEditButton: Bool, showRetryButton: Bool) { + teamImageAddButton.hidden = !showAddButton + teamImageEditButton.hidden = !showEditButton + teamImageRetryButton.hidden = !showRetryButton } - // MARK: - UIActionSheetDelegate - - func actionSheet(actionSheet: UIActionSheet, clickedButtonAtIndex buttonIndex: Int) { - if actionSheet.tag == ActionSheet.Menu.rawValue { - switch buttonIndex{ - case 0: - showCheckOutAlertView() - case 1: - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.6 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in - self.performSegueWithIdentifier("Settings", sender: actionSheet) - } - break - case 2: - showImageAlertView(actionSheet) - break - default: - break - } + // MARK: - TeamImage + + private func setTeamImageWithURLRequest(urlString: String?, completion: (withSuccess: Bool) -> Void) { + setTeamImageWithURLRequest(urlString, success: { () in + completion(withSuccess: true) + }) { + completion(withSuccess: false) } } - // MARK: - Start tracking + private func setTeamImageWithURLRequest(urlString: String?, success: () -> Void, failure: () -> Void) { + guard let string = urlString else { failure(); return } + guard let url = NSURL(string: string) else { failure(); return } + teamImageView.setImageWithURLRequest(NSURLRequest(URL: url), + placeholderImage: nil, + success: { (request, response, image) in self.setTeamImageWithURLSuccess(image, success: success) }, + failure: { (request, response, error) in self.setTeamImageWithURLFailure(failure) } + ) + } + + private func setTeamImageWithURLSuccess(image: UIImage, success: () -> Void) { + teamImageView.image = image + regatta.teamImageRetry = false + regatta.teamImageData = UIImageJPEGRepresentation(image, 0.8) + CoreDataManager.sharedManager.saveContext() + success() + } + + private func setTeamImageWithURLFailure(failure: () -> Void) { + failure() + } + + // MARK: - Timer + + @objc private func countdownTimerTick() { + if regatta.event.startDate - NSDate().timeIntervalSince1970 > 0 { + regattaStartLabel.text = Translation.RegattaView.RegattaStartLabel.Text.BeforeRegattaDidStart.String + let duration = regatta.event.startDate - NSDate().timeIntervalSince1970 + let days = Int(duration / (60 * 60 * 24)) + let hours = Int(duration / (60 * 60)) - (days * 24) + let minutes = Int(duration / 60) - (days * 24 * 60) - (hours * 60) + countdownDaysLabel.text = String(format: "%02d", days) + countdownHoursLabel.text = String(format: "%02d", hours) + countdownMinutesLabel.text = String(format: "%02d", minutes) + countdownView.hidden = false + countdownViewHeight.constant = 60 + } else { + regattaStartLabel.text = Translation.RegattaView.RegattaStartLabel.Text.AfterRegattaDidStart.String + countdownView.hidden = true + countdownViewHeight.constant = 0 + } + } + + // MARK: - Actions + + @IBAction func teamImageAddButtonTapped(sender: AnyObject) { + showSelectImageAlert() + } + + @IBAction func teamImageEditButtonTapped(sender: AnyObject) { + showSelectImageAlert() + } + + @IBAction func teamImageRetryButtonTapped(sender: AnyObject) { + uploadTeamImageData(regatta.teamImageData) + } + + @IBAction func eventButtonTapped(sender: UIButton) { + UIApplication.sharedApplication().openURL(regatta.eventURL() ?? NSURL()) + } + + @IBAction func optionButtonTapped(sender: AnyObject) { + let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet) + if let popoverController = alertController.popoverPresentationController { + popoverController.barButtonItem = sender as? UIBarButtonItem + } + let settingsAction = UIAlertAction(title: Translation.SettingsView.Title.String, style: .Default) { (action) in + self.performSegueWithIdentifier(Segue.Settings, sender: self) + } + let checkOutAction = UIAlertAction(title: Translation.RegattaView.OptionSheet.CheckOutAction.Title.String, style: .Default) { (action) in + self.showCheckOutAlert() + } + let replaceImageAction = UIAlertAction(title: Translation.RegattaView.OptionSheet.ReplaceImageAction.Title.String, style: .Default) { (action) in + self.showSelectImageAlert() + } + let updateAction = UIAlertAction(title: Translation.RegattaView.OptionSheet.UpdateAction.Title.String, style: .Default) { (action) -> Void in + self.update() + } + let aboutAction = UIAlertAction(title: Translation.Common.Info.String, style: .Default) { (action) -> Void in + self.performSegueWithIdentifier(Segue.About, sender: alertController) + } + let cancelAction = UIAlertAction(title: Translation.Common.Cancel.String, style: .Cancel, handler: nil) + alertController.addAction(settingsAction) + alertController.addAction(checkOutAction) + alertController.addAction(replaceImageAction) + alertController.addAction(updateAction) + alertController.addAction(aboutAction) + alertController.addAction(cancelAction) + presentViewController(alertController, animated: true, completion: nil) + } @IBAction func startTrackingButtonTapped(sender: AnyObject) { - let errorMessage = LocationManager.sharedManager.startTracking() - if errorMessage != nil { - let alertView = UIAlertView(title: errorMessage, message: nil, delegate: nil, cancelButtonTitle: NSLocalizedString("Cancel", comment: "")) - alertView.show() - } else { - performSegueWithIdentifier("Tracking", sender: sender) + // TODO: Add or add not WiFi Alert? + //if SMTWiFiStatus.wifiStatus() == WiFiStatus.On && !AFNetworkReachabilityManager.sharedManager().reachableViaWiFi { + // showStartTrackingWiFiAlert(sender) + //} else { + startTracking(sender) + //} + } + + private func startTracking(sender: AnyObject) { + do { + try regattaController.startTracking() + performSegueWithIdentifier(Segue.Tracking, sender: sender) + } catch let error as LocationManager.LocationManagerError { + showStartTrackingFailureAlert(error.description) + } catch { + logError("\(#function)", error: error) } } - // MARK: - Image picker + // MARK: - Alerts - @IBAction func showImageAlertView(sender: AnyObject) { - if sourceTypes.count == 1 { - imagePicker(sourceTypes[0]) + private func showCheckOutAlert() { + let alertController = UIAlertController(title: Translation.Common.Warning.String, + message: Translation.RegattaView.CheckOutAlert.Message.String, + preferredStyle: .Alert + ) + let yesAction = UIAlertAction(title: Translation.Common.Yes.String, style: .Default) { (action) in + self.performCheckOut() } - if sourceTypes.count == 2 { - let alertView = UIAlertView(title: NSLocalizedString("Select a photo for your team", comment: ""), message: "", delegate: self, cancelButtonTitle: NSLocalizedString("Cancel", comment: ""), otherButtonTitles: sourceTypeNames[0], sourceTypeNames[1]) - alertView.tag = AlertView.Image.rawValue; - alertView.show() + let noAction = UIAlertAction(title: Translation.Common.No.String, style: .Cancel, handler: nil) + alertController.addAction(yesAction) + alertController.addAction(noAction) + presentViewController(alertController, animated: true, completion: nil) + } + + private func performCheckOut() { + regattaController.checkOut { (withSuccess) in + self.performCheckOutCompleted(withSuccess) } } - func imagePicker(sourceType: UIImagePickerControllerSourceType) { + private func performCheckOutCompleted(withSuccess: Bool) { + CoreDataManager.sharedManager.deleteObject(self.regatta) + CoreDataManager.sharedManager.saveContext() + self.navigationController!.popViewControllerAnimated(true) + } + + private func showSelectImageAlert() { + if UIImagePickerController.isSourceTypeAvailable(.Camera) && UIImagePickerController.isSourceTypeAvailable(.PhotoLibrary) { + let alertController = UIAlertController(title: Translation.RegattaView.SelectImageAlert.Title.String, + message: Translation.RegattaView.SelectImageAlert.Message.String, + preferredStyle: .Alert + ) + let cameraAction = UIAlertAction(title: Translation.RegattaView.SelectImageAlert.CameraAction.Title.String, style: .Default) { (action) in + self.showImagePicker(.Camera) + } + let photoLibraryAction = UIAlertAction(title: Translation.RegattaView.SelectImageAlert.PhotoLibraryAction.Title.String, style: .Default) { (action) in + self.showImagePicker(.PhotoLibrary) + } + let cancelAction = UIAlertAction(title: Translation.Common.Cancel.String, style: .Cancel, handler: nil) + alertController.addAction(cameraAction) + alertController.addAction(photoLibraryAction) + alertController.addAction(cancelAction) + presentViewController(alertController, animated: true, completion: nil) + } else if UIImagePickerController.isSourceTypeAvailable(.Camera) { + showImagePicker(.Camera) + } else if UIImagePickerController.isSourceTypeAvailable(.PhotoLibrary) { + showImagePicker(.PhotoLibrary) + } + } + + private func showStartTrackingWiFiAlert(sender: AnyObject) { + let alertController = UIAlertController(title: "INFO", + message: "WIFI IS ON BUT NOT CONNECTED", + preferredStyle: .Alert + ) + let settingsAction = UIAlertAction(title: Translation.Common.Settings.String, style: .Default) { (action) in + UIApplication.sharedApplication().openURL(NSURL(string: "prefs:root=WIFI") ?? NSURL()) + } + let okAction = UIAlertAction(title: Translation.Common.OK.String, style: .Default) { (action) in + self.startTracking(sender) + } + let cancelAction = UIAlertAction(title: Translation.Common.Cancel.String, style: .Cancel, handler: nil) + alertController.addAction(settingsAction) + alertController.addAction(okAction) + alertController.addAction(cancelAction) + presentViewController(alertController, animated: true, completion: nil) + } + + private func showStartTrackingFailureAlert(message: String) { + let alertController = UIAlertController(title: Translation.Common.Warning.String, + message: message, + preferredStyle: .Alert + ) + let settingsAction = UIAlertAction(title: Translation.Common.Settings.String, style: .Default) { (action) in + UIApplication.sharedApplication().openURL(NSURL(string: "prefs:root=LOCATION_SERVICES") ?? NSURL()) + } + let cancelAction = UIAlertAction(title: Translation.Common.Cancel.String, style: .Default, handler: nil) + alertController.addAction(settingsAction) + alertController.addAction(cancelAction) + presentViewController(alertController, animated: true, completion: nil) + } + + // MARK: - Segue + + override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { + if (segue.identifier == Segue.Tracking) { + let trackingNC = segue.destinationViewController as! UINavigationController + let trackingVC = trackingNC.viewControllers[0] as! TrackingViewController + trackingVC.regatta = regatta + trackingVC.regattaController = regattaController + } else if (segue.identifier == Segue.Leaderboard) { + let leaderboardNC = segue.destinationViewController as! UINavigationController + let leaderboardVC = leaderboardNC.viewControllers[0] as! LeaderboardViewController + leaderboardVC.regatta = regatta + } + } + + // MARK: - Properties + + private lazy var regattaController: RegattaController = { + return RegattaController(regatta: self.regatta) + }() + +} + +// MARK: - UIImagePickerControllerDelegate + +extension RegattaViewController: UIImagePickerControllerDelegate { + + private func showImagePicker(sourceType: UIImagePickerControllerSourceType) { let imagePickerController = UIImagePickerController() imagePickerController.delegate = self imagePickerController.sourceType = sourceType; @@ -271,82 +383,61 @@ class RegattaViewController : UIViewController, UIActionSheetDelegate, UINavigat presentViewController(imagePickerController, animated: true, completion: nil) } - func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) { - dismissViewControllerAnimated(true, completion: nil) - imageView.image = image - yourTeamPhotoButton.hidden = true - editTeamPhotoButton.hidden = false - retryUploadTeamPhotoButton.hidden = true - let jpegData = UIImageJPEGRepresentation(image, 0.8) - DataManager.sharedManager.selectedCheckIn!.userImage = jpegData - APIManager.sharedManager.postTeamImage(DataManager.sharedManager.selectedCheckIn!.competitorId, - imageData: jpegData, - success: { (responseObject) -> Void in - // https://wiki.sapsailing.com/wiki/info/api/api-v1#tracking-app-api-v1_check-in-information_competitor-information-in-general - // "Additional Notes: Competitor profile image left out for now." - let responseDictionary = responseObject as![String: AnyObject] - let imageUrl = (responseDictionary["teamImageUri"]) as! String; - DataManager.sharedManager.selectedCheckIn!.imageUrl = imageUrl; - - NSUserDefaults.standardUserDefaults().setBool(false, forKey: self.uploadKey) - NSUserDefaults.standardUserDefaults().synchronize() - }, - failure: { (error) -> Void in - let alertView = UIAlertView(title: NSLocalizedString("Failed to upload image", comment: ""), message: error.localizedDescription, delegate: self, cancelButtonTitle: NSLocalizedString("Cancel", comment: "")) - alertView.tag = AlertView.UploadFailed.rawValue; - alertView.show() - - NSUserDefaults.standardUserDefaults().setBool(true, forKey: self.uploadKey) - NSUserDefaults.standardUserDefaults().synchronize() - self.retryUploadTeamPhotoButton.hidden = false - }) - } - - // MARK: - Check-out - func showCheckOutAlertView() { - let alertView = UIAlertView(title: NSLocalizedString("Check-out of Regatta?", comment: ""), message: "", delegate: self, cancelButtonTitle: NSLocalizedString("Cancel", comment: ""), otherButtonTitles: NSLocalizedString("OK", comment: "")) - alertView.tag = AlertView.CheckOut.rawValue; - alertView.show() - } - - // MARK: - UIAlertViewDelegate - - func alertView(alertView: UIAlertView, clickedButtonAtIndex buttonIndex: Int) { - switch alertView.tag { - // Check-out - case AlertView.CheckOut.rawValue: - switch buttonIndex { - case alertView.cancelButtonIndex: - break - default: - let now = NSDate() - let toMillis = Int64(now.timeIntervalSince1970 * 1000) - APIManager.sharedManager.checkOut(DataManager.sharedManager.selectedCheckIn!.leaderBoardName, - competitorId: DataManager.sharedManager.selectedCheckIn!.competitorId, - deviceUuid: DeviceUDIDManager.UDID, - toMillis: toMillis, - success: { (operation, competitorResponseObject) -> Void in - }, - failure: { (operation, error) -> Void in - } - ) - DataManager.sharedManager.deleteCheckIn(DataManager.sharedManager.selectedCheckIn!) - DataManager.sharedManager.saveContext() - self.navigationController!.popViewControllerAnimated(true) - break - } - break - case AlertView.Image.rawValue: - if buttonIndex != alertView.cancelButtonIndex { - imagePicker(sourceTypes[buttonIndex - 1]) - } - break - default: - break + func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) { + if let image = info[UIImagePickerControllerOriginalImage] as? UIImage { + dismissViewControllerAnimated(true) { self.pickedImage(image) } + } else { + dismissViewControllerAnimated(true, completion: nil) } } - func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) { - UIApplication.sharedApplication().statusBarStyle = UIStatusBarStyle.LightContent + private func pickedImage(image: UIImage) { + teamImageView.image = image + regatta.teamImageData = UIImageJPEGRepresentation(image, 0.8) + CoreDataManager.sharedManager.saveContext() + uploadTeamImageData(regatta.teamImageData) } -} \ No newline at end of file + + // MARK: - Upload + + private func uploadTeamImageData(imageData: NSData!) { + SVProgressHUD.show() + regattaController.postTeamImageData(imageData, + success: { (teamImageURL) in + SVProgressHUD.popActivity() + self.uploadTeamImageDataSuccess(teamImageURL) + }, + failure: { (error) in + SVProgressHUD.popActivity() + self.uploadTeamImageDataFailure(error) + } + ) + } + + private func uploadTeamImageDataSuccess(teamImageURL: String) { + regatta.teamImageRetry = false + regatta.teamImageURL = teamImageURL + CoreDataManager.sharedManager.saveContext() + refreshTeamImage() + } + + private func uploadTeamImageDataFailure(error: RequestManager.Error) { + regatta.teamImageRetry = true + CoreDataManager.sharedManager.saveContext() + showUploadTeamImageFailureAlert(error) + refreshTeamImage() + } + + // MARK: - Alert + + private func showUploadTeamImageFailureAlert(error: RequestManager.Error) { + let alertController = UIAlertController(title: error.title, + message: error.message, + preferredStyle: .Alert + ) + let okAction = UIAlertAction(title: Translation.Common.OK.String, style: .Default, handler: nil) + alertController.addAction(okAction) + presentViewController(alertController, animated: true, completion: nil) + } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/RequestManager.swift b/ios/SAPTracker/src/xcode/SAPTracker/RequestManager.swift new file mode 100644 index 00000000000..28b6e9822aa --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/RequestManager.swift @@ -0,0 +1,391 @@ +// +// RequestManager.swift +// SAPTracker +// +// Created by Raimund Wege on 25.05.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// +// See: http://wiki.sapsailing.com/wiki/tracking-app/api-v1#Competitor-Information-%28in-general%29 + +import UIKit + +class RequestManager: NSObject { + + struct Error { + + let title, message: String + + init(title: String, message: String) { + self.title = title + self.message = message + } + + init(message: String) { + self.init(title: Translation.Common.Error.String, message: message) + } + + init() { + self.init(message: Translation.RequestManager.Failure.Message.String) + } + + } + + private let basePathString = "/sailingserver/api/v1" + + private enum BodyKeys { + static let CompetitorID = "competitorId" + static let DeviceType = "deviceType" + static let DeviceUUID = "deviceUuid" + static let Fixes = "fixes" + static let FixesCourse = "course" + static let FixesLatitude = "latitude" + static let FixesLongitude = "longitude" + static let FixesSpeed = "speed" + static let FixesTimestamp = "timestamp" + static let FromMillis = "fromMillis" + static let PushDeviceID = "pushDeviceId" + static let ToMillis = "toMillis" + } + + private struct TeamImageKeys { + static let TeamImageURL = "teamImageUri" + } + + private enum DeviceType { + static let IOS = "iOS" + } + + let baseURLString: String + let manager: AFHTTPRequestOperationManager + let sessionManager: AFURLSessionManager + + init(baseURLString: String = "") { + self.baseURLString = baseURLString + manager = AFHTTPRequestOperationManager(baseURL: NSURL(string: baseURLString)) + manager.requestSerializer = AFJSONRequestSerializer() as AFHTTPRequestSerializer + manager.responseSerializer = AFJSONResponseSerializer() as AFHTTPResponseSerializer + sessionManager = AFURLSessionManager(sessionConfiguration: NSURLSessionConfiguration.defaultSessionConfiguration()) + sessionManager.responseSerializer = AFJSONResponseSerializer() as AFHTTPResponseSerializer + super.init() + } + + // MARK: - Regatta + + func getRegattaData(regattaData: RegattaData, + success: (regattaData: RegattaData) -> Void, + failure: (error: Error) -> Void) + { + getEventData(regattaData, success: success, failure: failure) + } + + private func getEventData(regattaData: RegattaData, + success: (regattaData: RegattaData) -> Void, + failure: (error: Error) -> Void) + { + getEvent(regattaData.eventID, + success: { (data) in self.getEventDataSuccess(data, regattaData: regattaData, success: success, failure: failure) }, + failure: { (error) in failure(error: error) } + ) + } + + private func getEventDataSuccess(eventData: EventData, + regattaData: RegattaData, + success: (regattaData: RegattaData) -> Void, + failure: (error: Error) -> Void) + { + regattaData.eventData = eventData + getLeaderboardData(regattaData, success: success, failure: failure) + } + + private func getLeaderboardData(regattaData: RegattaData, + success: (regattaData: RegattaData) -> Void, + failure: (error: Error) -> Void) + { + getLeaderboard(regattaData.leaderboardName, + success: { (data) in self.getLeaderboardDataSuccess(data, regattaData: regattaData, success: success, failure: failure) }, + failure: { (error) in failure(error: error) } + ) + } + + private func getLeaderboardDataSuccess(leaderboardData: LeaderboardData, + regattaData: RegattaData, + success: (regattaData: RegattaData) -> Void, + failure: (error: Error) -> Void) + { + regattaData.leaderboardData = leaderboardData + getCompetitorData(regattaData, success: success, failure: failure) + } + + private func getCompetitorData(regattaData: RegattaData, + success: (regattaData: RegattaData) -> Void, + failure: (error: Error) -> Void) + { + getCompetitor(regattaData.competitorID, + success: { (data) in self.getCompetitorDataSuccess(data, regattaData: regattaData, success: success, failure: failure) }, + failure: { (error) in failure(error: error) } + ) + } + + private func getCompetitorDataSuccess(competitorData: CompetitorData, + regattaData: RegattaData, + success: (regattaData: RegattaData) -> Void, + failure: (error: Error) -> Void) + { + regattaData.competitorData = competitorData + getTeamImageURL(regattaData.competitorID, result: { (imageURL) in + regattaData.teamImageURL = imageURL + success(regattaData: regattaData) + }) + } + + // MARK: - Event + + private func getEvent(eventID: String, + success: (eventData: EventData) -> Void, + failure: (error: Error) -> Void) + { + let encodedEventID = eventID.stringByAddingPercentEncodingWithAllowedCharacters(.URLPathAllowedCharacterSet()) ?? "" + let urlString = "\(basePathString)/events/\(encodedEventID)" + manager.GET(urlString, + parameters: nil, + success: { (requestOperation, responseObject) in self.getEventSuccess(responseObject, success: success) }, + failure: { (requestOperation, error) in self.getEventFailure(eventID, failure: failure) } + ) + } + + private func getEventSuccess(responseObject: AnyObject, success: (eventData: EventData) -> Void) { + success(eventData: EventData(dictionary: responseObject as? [String: AnyObject])) + } + + private func getEventFailure(eventID: String, failure: (error: Error) -> Void) -> Void { + let message = String(format: Translation.RequestManager.EventLoadingFailure.Message.String, eventID) + failure(error: Error(message: message)) + } + + // MARK: - Leaderboard + + private func getLeaderboard(leaderboardName: String, + success: (leaderboardData: LeaderboardData) -> Void, + failure: (error: Error) -> Void) + { + let encodedLeaderboardName = leaderboardName.stringByAddingPercentEncodingWithAllowedCharacters(.URLPathAllowedCharacterSet()) ?? "" + let urlString = "\(basePathString)/leaderboards/\(encodedLeaderboardName)" + manager.GET(urlString, + parameters: nil, + success: { (requestOperation, responseObject) in self.getLeaderboardSuccess(responseObject, success: success) }, + failure: { (requestOperation, error) in self.getLeaderboardFailure(leaderboardName, failure: failure) } + ) + } + + private func getLeaderboardSuccess(responseObject: AnyObject, success: (leaderboardData: LeaderboardData) -> Void) { + success(leaderboardData: LeaderboardData(dictionary: responseObject as? [String: AnyObject])) + } + + private func getLeaderboardFailure(leaderboardName: String, failure: (error: Error) -> Void) { + let message = String(format: Translation.RequestManager.LeaderboardLoadingFailure.Message.String, leaderboardName) + failure(error: Error(message: message)) + } + + // MARK: - Competitor + + private func getCompetitor(competitorID: String, + success: (competitorData: CompetitorData) -> Void, + failure: (error: Error) -> Void) + { + let encodedCompetitorID = competitorID.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLPathAllowedCharacterSet()) ?? "" + let urlString = "\(basePathString)/competitors/\(encodedCompetitorID)" + manager.GET(urlString, + parameters: nil, + success: { (requestOperation, responseObject) in self.getCompetitorSuccess(responseObject, success: success) }, + failure: { (requestOperation, error) in self.getCompetitorFailure(competitorID, failure: failure) } + ) + } + + private func getCompetitorSuccess(responseObject: AnyObject, success: (competitorData: CompetitorData) -> Void) { + success(competitorData: CompetitorData(dictionary: responseObject as? [String: AnyObject])) + } + + private func getCompetitorFailure(competitorID: String, failure: (error: Error) -> Void) { + let message = String(format: Translation.RequestManager.CompetitorLoadingFailure.Message.String, competitorID) + failure(error: Error(message: message)) + } + + // MARK: - Team + + private func getTeam(competitorID: String, + success: (teamData: TeamData) -> Void, + failure: (error: Error) -> Void) + { + let encodedCompetitorID = competitorID.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLPathAllowedCharacterSet()) ?? "" + let urlString = "\(basePathString)/competitors/\(encodedCompetitorID)/team" + manager.GET(urlString, + parameters: nil, + success: { (requestOperation, responseObject) in self.getTeamSuccess(responseObject, success: success) }, + failure: { (requestOperation, error) in self.getTeamFailure(failure) } + ) + } + + private func getTeamSuccess(responseObject: AnyObject, success: (teamData: TeamData) -> Void) { + success(teamData: TeamData(dictionary: responseObject as? [String: AnyObject])) + } + + private func getTeamFailure(failure: (error: Error) -> Void) { + failure(error: Error()) + } + + private func getTeamImageURL(competitorID: String, result: (imageURL: String?) -> Void) { + getTeam(competitorID, + success: { (teamData) in result(imageURL: teamData.imageURL) }, + failure: { (error) in result(imageURL: nil) } // No image but that's ok + ) + } + + // MARK: CheckIn + + func postCheckIn(leaderboardName: String!, + competitorID: String!, + success: () -> Void, + failure: (error: Error) -> Void) + { + // Setup body + var body = [String: AnyObject]() + body[BodyKeys.CompetitorID] = competitorID + body[BodyKeys.DeviceType] = DeviceType.IOS + body[BodyKeys.DeviceUUID] = Preferences.uuid + body[BodyKeys.PushDeviceID] = "" + body[BodyKeys.FromMillis] = millisSince1970() + + // Post body + let urlString = "\(basePathString)/leaderboards/\(leaderboardName.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())!)/device_mappings/start" + manager.POST(urlString, + parameters: body, + success: { (requestOperation, responseObject) in self.postCheckInSuccess(success) }, + failure: { (requestOperation, error) in self.postCheckInFailure(failure) } + ) + } + + private func postCheckInSuccess(success: () -> Void) { + success() + } + + private func postCheckInFailure(failure: (error: Error) -> Void) { + failure(error: Error()) + } + + // MARK: - CheckOut + + func postCheckOut(leaderboardName: String!, + competitorId: String!, + success:() -> Void, + failure: (error: Error) -> Void) + { + // Setup body + var body = [String: AnyObject]() + body[BodyKeys.CompetitorID] = competitorId + body[BodyKeys.DeviceUUID] = Preferences.uuid + body[BodyKeys.ToMillis] = millisSince1970() + + // Post body + let urlString = "\(basePathString)/leaderboards/\(leaderboardName.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())!)/device_mappings/end" + manager.POST(urlString, + parameters: body, + success: { (requestOperation, responseObject) in self.postCheckOutSuccess(success) }, + failure: { (requestOperation, error) in self.postCheckOutFailure(error, failure: failure) } + ) + } + + private func postCheckOutSuccess(success: () -> Void) { + success() + } + + private func postCheckOutFailure(error: NSError, failure: (error: Error) -> Void) { + failure(error: Error(message: error.localizedDescription)) + } + + // MARK: - GPSFixes + + func postGPSFixes(gpsFixes: Array, + success: () -> Void, + failure: (error: Error) -> Void) + { + // Setup fixes + let fixes = gpsFixes.map { (gpsFix) -> [String: AnyObject] in [ + BodyKeys.FixesCourse: gpsFix.course, + BodyKeys.FixesLatitude: gpsFix.latitude, + BodyKeys.FixesLongitude: gpsFix.longitude, + BodyKeys.FixesSpeed: gpsFix.speed, + BodyKeys.FixesTimestamp: gpsFix.timestamp] + } + + // Setup body + var body = [String: AnyObject]() + body[BodyKeys.DeviceUUID] = Preferences.uuid + body[BodyKeys.Fixes] = fixes + + // Post body + let urlString = "\(basePathString)/gps_fixes" + manager.POST(urlString, + parameters: body, + success: { (requestOperation, responseObject) in self.postGPSFixesSuccess(success) }, + failure: { (requestOperation, error) in self.postGPSFixesFailure(error, failure: failure) } + ) + } + + private func postGPSFixesSuccess(success: () -> Void) { + success() + } + + private func postGPSFixesFailure(error: NSError, failure: (error: Error) -> Void) { + failure(error: Error(message: error.localizedDescription)) + } + + // MARK: - TeamImage + + func postTeamImageData(imageData: NSData, + competitorID: String, + success: (teamImageURL: String) -> Void, + failure: (error: Error) -> Void) + { + let urlString = "\(baseURLString)\(basePathString)/competitors/\(competitorID)/team/image" + let url = NSURL(string: urlString) ?? NSURL() + let request = NSMutableURLRequest(URL: url) + request.setValue("image/jpeg", forHTTPHeaderField: "Content-Type") + request.HTTPBody = imageData + request.HTTPMethod = "POST" + let dataTask = sessionManager.dataTaskWithRequest(request, completionHandler:{ (response, responseObject, error) in + if (error != nil) { + self.postTeamImageDataFailure(error!.localizedDescription, failure: failure) + } else { + self.postTeamImageDataSuccess(responseObject, success: success, failure: failure) + } + }) + dataTask.resume(); + } + + private func postTeamImageDataSuccess(responseObject: AnyObject?, + success: (teamImageURL: String) -> Void, + failure: (error: Error) -> Void) + { + guard let teamImageDictionary = responseObject as? [String: AnyObject] else { + postTeamImageDataFailure(Translation.RequestManager.Failure.Message.String, failure: failure) + return + } + guard let teamImageURL = teamImageDictionary[TeamImageKeys.TeamImageURL] as? String else { + postTeamImageDataFailure(Translation.RequestManager.Failure.Message.String, failure: failure) + return + } + success(teamImageURL: teamImageURL) + } + + private func postTeamImageDataFailure(message: String, failure: (error: Error) -> Void) { + let title = Translation.RequestManager.TeamImageUploadFailure.Title.String + failure(error: Error(title: title, message: message)) + } + + // MARK: - Helper + + private func millisSince1970() -> NSNumber { + return NSNumber(longLong: Int64(NSDate().timeIntervalSince1970 * 1000)) + } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/ScanViewController.swift b/ios/SAPTracker/src/xcode/SAPTracker/ScanViewController.swift index 574f320a5ce..13fe97ed188 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/ScanViewController.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/ScanViewController.swift @@ -1,86 +1,212 @@ // -// QRCodeViewController.swift +// ScanViewController.swift // SAPTracker // -// Created by computing on 22/10/14. +// Created by Raimund Wege on 22/10/14. // Copyright (c) 2014 com.sap.sailing. All rights reserved. // import UIKit import AVFoundation -class ScanViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate, QRCodeManagerDelegate { +class ScanViewController: UIViewController { + + weak var homeViewController: HomeViewController? @IBOutlet weak var previewView: UIView! @IBOutlet weak var targetImageView: UIImageView! - var activityIndicatorView: UIActivityIndicatorView! - private var session: AVCaptureSession! - private var previewLayer: AVCaptureVideoPreviewLayer! - private var qrCodeManager: QRCodeManager? + private var scanSession: AVCaptureSession? + private var scanOutput: AVCaptureMetadataOutput? + private var scanPreviewLayer: AVCaptureVideoPreviewLayer? + private var scanError: NSError? override func viewDidLoad() { super.viewDidLoad() - - activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.White) - activityIndicatorView.hidesWhenStopped = true - let barButton = UIBarButtonItem(customView: activityIndicatorView) - self.navigationItem.rightBarButtonItem = barButton - - qrCodeManager = QRCodeManager(delegate: self) + setup() + } + + override func viewDidAppear(animated: Bool) { + super.viewDidAppear(animated) startScanning() } - /* Set up camera and QR code scanner */ - @IBAction func startScanning() { - var output: AVCaptureMetadataOutput! - (session, output) = QRCodeManager.setUpCaptureSession(self) - output.metadataObjectTypes = [AVMetadataObjectTypeQRCode] - - previewLayer = AVCaptureVideoPreviewLayer(session: session) - previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + layout() + } + + // MARK: - Layout + + private func layout() { + layoutPreviewLayer() + } + + private func layoutPreviewLayer() { + guard let previewLayer = scanPreviewLayer else { return } previewLayer.frame = previewView.bounds previewLayer.position = CGPointMake(CGRectGetMidX(previewView.bounds), CGRectGetMidY(previewView.bounds)) - previewView.layer.addSublayer(previewLayer) - - session.startRunning() - - targetImageView.image = UIImage(named: "scan_white") } - /* AVCaptureMetadataOutputObjectsDelegate. Parse scanned QR code */ - func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) - { - if metadataObjects.count > 0 { - targetImageView.image = UIImage(named: "scan_green") - session.stopRunning() - activityIndicatorView.startAnimating() - let metadataObject: AVMetadataMachineReadableCodeObject = metadataObjects[0] as! AVMetadataMachineReadableCodeObject - qrCodeManager!.parseUrl(metadataObject.stringValue) + // MARK: - Setup + + private func setup() { + setupLocalization() + setupScanning() + } + + private func setupLocalization() { + navigationItem.title = Translation.ScanView.Title.String + } + + private func setupScanning() { + do { + let session = AVCaptureSession() + let output = AVCaptureMetadataOutput() + let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo) + let input = try AVCaptureDeviceInput(device: device); + output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue()) + session.canSetSessionPreset(AVCaptureSessionPresetHigh) + if session.canAddInput(input) { + session.addInput(input) + } + if session.canAddOutput(output) { + session.addOutput(output) + } + output.metadataObjectTypes = [AVMetadataObjectTypeQRCode] + let previewLayer = AVCaptureVideoPreviewLayer(session: session) + previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill + previewLayer.connection.videoOrientation = videoOrientation(forInterfaceOrientation: UIApplication.sharedApplication().statusBarOrientation) + previewLayer.frame = previewView.bounds + previewLayer.position = CGPointMake(CGRectGetMidX(previewView.bounds), CGRectGetMidY(previewView.bounds)) + previewView.layer.addSublayer(previewLayer) + scanSession = session + scanOutput = output + scanPreviewLayer = previewLayer + } catch let error as NSError { + scanError = error } } + // MARK: - Scanning + + private func startScanning() { + targetImageView.image = UIImage(named: "scan_white") + if let error = scanError { + let alertController = UIAlertController(title: error.localizedDescription, + message: error.localizedFailureReason, + preferredStyle: .Alert + ) + let settingsAction = UIAlertAction(title: Translation.Common.Settings.String, style: .Default) { (action) in + UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString) ?? NSURL()) + self.navigationController?.popViewControllerAnimated(true) + } + let cancelAction = UIAlertAction(title: Translation.Common.Cancel.String, style: .Cancel) { (action) in + self.navigationController?.popViewControllerAnimated(true) + } + alertController.addAction(settingsAction) + alertController.addAction(cancelAction) + presentViewController(alertController, animated: true, completion: nil) + } else { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { + self.scanSession?.startRunning() + }) + } + } + + private func stopScanning() { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { + self.scanSession?.stopRunning() + }) + targetImageView.image = UIImage(named: "scan_green") + } + + // MARK: - UIViewControllerDelegate + override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) { - if UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft { - previewLayer!.connection.videoOrientation = AVCaptureVideoOrientation.LandscapeRight - } else if UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeRight { - previewLayer!.connection.videoOrientation = AVCaptureVideoOrientation.LandscapeLeft - } else { - previewLayer!.connection.videoOrientation = AVCaptureVideoOrientation.Portrait + scanPreviewLayer?.connection.videoOrientation = videoOrientation(forInterfaceOrientation: toInterfaceOrientation) + } + + // MARK: - Properties + + private lazy var checkInController: CheckInController = { + let checkInController = CheckInController() + checkInController.delegate = self + return checkInController + }() + + // MARK: - Helper + + private func videoOrientation(forInterfaceOrientation orientation: UIInterfaceOrientation) -> AVCaptureVideoOrientation { + switch orientation { + case .LandscapeLeft: return .LandscapeLeft + case .LandscapeRight: return .LandscapeRight + case .Portrait: return .Portrait + case .PortraitUpsideDown: return .PortraitUpsideDown + case .Unknown: return .Portrait } } - // MARK: - QRCodeManagerDelegate +} + +// MARK: - CheckInControllerDelegate + +extension ScanViewController: CheckInControllerDelegate { - func qrCodeOK() { - // pop back to home view - navigationController!.popViewControllerAnimated(true) + func showCheckInAlert(sender: CheckInController, alertController: UIAlertController) { + presentViewController(alertController, animated: true, completion: nil) } - func qrCodeCancel() { - self.session.startRunning() - activityIndicatorView.stopAnimating() - targetImageView.image = UIImage(named: "scan_white") +} + +// MARK: - AVCaptureMetadataOutputObjectsDelegate + +extension ScanViewController: AVCaptureMetadataOutputObjectsDelegate { + + func captureOutput(captureOutput: AVCaptureOutput!, + didOutputMetadataObjects metadataObjects: [AnyObject]!, + fromConnection connection: AVCaptureConnection!) + { + if metadataObjects.count > 0 { + let metadataObject = metadataObjects[0] as! AVMetadataMachineReadableCodeObject + if let regattaData = RegattaData(urlString: metadataObject.stringValue) { + stopScanning() + dispatch_async(dispatch_get_main_queue(), { + self.captureOutputSuccess(regattaData) + }) + } else { + dispatch_async(dispatch_get_main_queue(), { + self.captureOutputFailure() + }) + } + } + } + + private func captureOutputSuccess(regattaData: RegattaData) { + checkInController.checkIn(regattaData, completion: { (withSuccess) in + if withSuccess { + self.homeViewController?.selectedRegatta = CoreDataManager.sharedManager.fetchRegatta(regattaData) + self.navigationController?.popViewControllerAnimated(true) + } else { + self.startScanning() + } + }) + } + + private func captureOutputFailure() { + showIncorrectCodeAlert() + } + + // MARK: - Alerts + + private func showIncorrectCodeAlert() { + let alertController = UIAlertController(title: Translation.Common.Error.String, + message: Translation.ScanView.IncorrectCodeAlert.Message.String, + preferredStyle: .Alert + ) + let okAction = UIAlertAction(title: Translation.Common.OK.String, style: .Default, handler: nil) + alertController.addAction(okAction) + presentViewController(alertController, animated: true, completion: nil) } } \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker/SendGPSFixController.swift b/ios/SAPTracker/src/xcode/SAPTracker/SendGPSFixController.swift deleted file mode 100644 index 44ff44974a9..00000000000 --- a/ios/SAPTracker/src/xcode/SAPTracker/SendGPSFixController.swift +++ /dev/null @@ -1,97 +0,0 @@ -// -// UploadLocationController.swift -// SAPTracker -// -// Created by computing on 19/11/14. -// Copyright (c) 2014 com.sap.sailing. All rights reserved. -// - -import Foundation - -class SendGPSFixController: NSObject { - - struct NotificationType { - static let gpsFixesSynced = "gpsFixesSynced" - } - - private struct SyncPeriod { - /* Normal rate of upload is every 3s */ - static let Normal: NSTimeInterval = 3 - - /* To save battery, upload rate is lowered to every 30s */ - static let BatterySaving: NSTimeInterval = 30 - } - - /* Number of seconds between syncs */ - private var syncPeriod: NSTimeInterval { - get { - return BatteryManager.sharedManager.batterySaving ? SyncPeriod.BatterySaving : SyncPeriod.Normal - } - } - - var checkIn: CheckIn? - - /* Singleton */ - class var sharedManager: SendGPSFixController { - struct Singleton { - static let sharedManager = SendGPSFixController() - } - return Singleton.sharedManager - } - - // MARK: - Timer - - /* See if any rows need to be uploaded. Schedule timer again. */ - func timer() { - let loop = NSTimer.scheduledTimerWithTimeInterval(syncPeriod, target:self, selector:"timer", userInfo:nil, repeats:false) - NSRunLoop.currentRunLoop().addTimer(loop, forMode:NSRunLoopCommonModes) - - // get last 100 locations - let lastestGPSFixes = DataManager.sharedManager.latestLocations() - - // build a list of locations going to one server - var gpsFixesForServer = [GPSFix]() - - // server URL - var serverUrl: String? - - for gpsFix in lastestGPSFixes { - - // If currently tracking, don't upload locations for another (previous) event - if checkIn != nil && gpsFix.checkIn != checkIn { - break - } - - // location for another server - if serverUrl != nil && serverUrl != gpsFix.checkIn!.serverUrl { - sendGPSFixes(serverUrl!, gpsFixes: gpsFixesForServer) - gpsFixesForServer = [] - } - serverUrl = gpsFix.checkIn!.serverUrl - gpsFixesForServer.append(gpsFix) - } - if gpsFixesForServer.count > 0 { - sendGPSFixes(serverUrl!, gpsFixes:gpsFixesForServer) - } - } - - /* Send GPS fixes to specified server. */ - func sendGPSFixes(serverUrl: String, gpsFixes:[GPSFix]) { - APIManager.sharedManager.initManager(serverUrl) - if APIManager.sharedManager.networkAvailable { - APIManager.sharedManager.postGPSFixes(DeviceUDIDManager.UDID, gpsFixes: gpsFixes, - success: { (operation, competitorResponseObject) -> Void in - print("sent GPS fixes") - for gpsFix in gpsFixes { - DataManager.sharedManager.managedObjectContext!.deleteObject(gpsFix) - } - let notification = NSNotification(name: NotificationType.gpsFixesSynced, object: self) - NSNotificationQueue.defaultQueue().enqueueNotification(notification, postingStyle: NSPostingStyle.PostASAP) - }, - failure: { (operation, error) -> Void in - print("error sending GPS fixes") - }) - } - } - -} \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Settings.bundle/Acknowledgements.plist b/ios/SAPTracker/src/xcode/SAPTracker/Settings.bundle/Acknowledgements.plist index c8cc5a5f681..06438f47cb9 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/Settings.bundle/Acknowledgements.plist +++ b/ios/SAPTracker/src/xcode/SAPTracker/Settings.bundle/Acknowledgements.plist @@ -14,55 +14,33 @@ FooterText - Copyright (c) 2013 AFNetworking (http://afnetworking.com/) + Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com/) -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + Title - AFNetworkActivityLogger + AFNetworking Type PSGroupSpecifier FooterText - Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com/) + Copyright (c) 2011-2016 Sam Vermette, Tobias Tiemerding and contributors. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +A different license may apply to other resources included in this package, including Freepik Icons. Please consult their respective headers for the terms of their individual licenses. + Title - AFNetworking + SVProgressHUD Type PSGroupSpecifier @@ -72,36 +50,17 @@ THE SOFTWARE. Copyright (c) 2014 Tobias Sundstrand -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + Title TSMarkdownParser Type PSGroupSpecifier - - FooterText - Generated by CocoaPods - http://cocoapods.org - Title - - Type - PSGroupSpecifier - StringsTable Acknowledgements diff --git a/ios/SAPTracker/src/xcode/SAPTracker/SettingsViewController.swift b/ios/SAPTracker/src/xcode/SAPTracker/SettingsViewController.swift index ab6604325db..b503f51c8b3 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/SettingsViewController.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/SettingsViewController.swift @@ -2,32 +2,93 @@ // SettingsViewController.swift // SAPTracker // -// Created by computing on 10/11/14. -// Copyright (c) 2014 com.sap.sailing. All rights reserved. +// Created by Raimund Wege on 04.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. // import Foundation class SettingsViewController: UITableViewController { + @IBOutlet weak var batterySavingTitleLabel: UILabel! + @IBOutlet weak var batterySavingDescriptionLabel: UILabel! @IBOutlet weak var batterySavingSwitch: UISwitch! + @IBOutlet weak var deviceIdentifierTitleLabel: UILabel! + @IBOutlet weak var deviceIdentifierLabel: UILabel! override func viewDidLoad() { super.viewDidLoad() - batterySavingSwitch.setOn(BatteryManager.sharedManager.batterySavingPreference, animated: true) - - // add logo to top left - let imageView = UIImageView(image: UIImage(named: "sap_logo")) - let barButtonItem = UIBarButtonItem(customView: imageView) - navigationItem.leftBarButtonItem = barButtonItem - } - - @IBAction func batterySavingChanged(sender: UISwitch) { - BatteryManager.sharedManager.batterySavingPreference = sender.on + setup() } - @IBAction func done(sender: AnyObject) { + // MARK: - Setup + + private func setup() { + setupBatterySavingSwitch() + setupBatterySavingDescriptionLabel() + setupDeviceIdentifierLabel() + setupLocalization() + setupNavigationBar() + setupTableView() + } + + private func setupBatterySavingSwitch() { + batterySavingSwitch.setOn(Preferences.batterySaving, animated: true) + } + + private func setupBatterySavingDescriptionLabel() { + batterySavingDescriptionLabel.text = String(format: Translation.SettingsView.BatterySavingDescriptionLabel.Text.String, + Preferences.batterySaving ? + BatteryManager.SendingInterval.BatterySaving : + BatteryManager.SendingInterval.Normal) + } + + private func setupDeviceIdentifierLabel() { + deviceIdentifierLabel.text = Preferences.uuid + } + + private func setupLocalization() { + navigationItem.title = Translation.SettingsView.Title.String + batterySavingTitleLabel.text = Translation.SettingsView.BatterySavingTitleLabel.Text.String + deviceIdentifierTitleLabel.text = Translation.SettingsView.DeviceIdentifierTitleLabel.Text.String + } + + private func setupNavigationBar() { + navigationItem.leftBarButtonItem = UIBarButtonItem(customView: UIImageView(image: UIImage(named: "sap_logo"))) + } + + private func setupTableView() { + tableView.rowHeight = UITableViewAutomaticDimension + tableView.estimatedRowHeight = 140 + } + + // MARK: - Actions + + @IBAction func batterySavingChanged(sender: UISwitch) { + Preferences.batterySaving = sender.on + tableView.beginUpdates() + setupBatterySavingDescriptionLabel() + tableView.endUpdates() + } + + @IBAction func doneButtonTapped(sender: AnyObject) { presentingViewController!.dismissViewControllerAnimated(true, completion: nil) } + // MARK: - UITableViewDataSource + + override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + switch section { + case 0: return Translation.SettingsView.TableView.BatterySavingSection.Title.String + case 1: return Translation.SettingsView.TableView.OtherSettingsSection.Title.String + default: return "" + } + } + + // MARK: - UITableViewDelegate + + override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { + return UITableViewAutomaticDimension + } + } \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker/SpeedViewController.swift b/ios/SAPTracker/src/xcode/SAPTracker/SpeedViewController.swift index 825bf666d5f..54067ee5877 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/SpeedViewController.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/SpeedViewController.swift @@ -9,28 +9,72 @@ import Foundation class SpeedViewController: UIViewController { - - let knPerMs = 1.94552529182879 + private let mpsToKn = 1.94552529182879 + + @IBOutlet weak var titleLabel: UILabel! @IBOutlet weak var speedLabel: UILabel! override func viewDidLoad() { super.viewDidLoad() - NSNotificationCenter.defaultCenter().addObserver(self, selector:"newLocation:", name:LocationManager.NotificationType.newLocation, object: nil) + setup() + subscribeForNotifications() } deinit { - NSNotificationCenter.defaultCenter().removeObserver(self) + unsubscribeFromNotifications() } - func newLocation(notification: NSNotification) { - let ms = notification.userInfo!["speed"] as! Double - if(ms >= 0) { - let kn = ms * knPerMs + // MARK: - Setup + + private func setup() { + setupLocalization() + setupSpeedLabel(-1.0) + } + + private func setupLocalization() { + titleLabel.text = Translation.SpeedView.TitleLabel.Text.String + } + + private func setupSpeedLabel(mps: Double) { + if mps >= 0 { + let kn = mps * mpsToKn speedLabel.text = String(format: "%0.1f kn", kn) } else { speedLabel.text = "– kn" } } - + + // MARK: - Notifications + + private func subscribeForNotifications() { + NSNotificationCenter.defaultCenter().addObserver(self, + selector:#selector(locationManagerUpdated(_:)), + name:LocationManager.NotificationType.Updated, + object: nil + ) + NSNotificationCenter.defaultCenter().addObserver(self, + selector:#selector(locationManagerFailed(_:)), + name:LocationManager.NotificationType.Failed, + object: nil + ) + } + + private func unsubscribeFromNotifications() { + NSNotificationCenter.defaultCenter().removeObserver(self) + } + + @objc private func locationManagerUpdated(notification: NSNotification) { + dispatch_async(dispatch_get_main_queue(), { + guard let locationData = notification.userInfo?[LocationManager.UserInfo.LocationData] as? LocationData else { return } + self.setupSpeedLabel(locationData.location.speed) + }) + } + + @objc private func locationManagerFailed(notification: NSNotification) { + dispatch_async(dispatch_get_main_queue(), { + self.setupSpeedLabel(-1.0) + }) + } + } \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker/TeamData.swift b/ios/SAPTracker/src/xcode/SAPTracker/TeamData.swift new file mode 100644 index 00000000000..1414023962e --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/TeamData.swift @@ -0,0 +1,19 @@ +// +// TeamData.swift +// SAPTracker +// +// Created by Raimund Wege on 03.08.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import UIKit + +class TeamData: BaseData { + + private enum Keys { + static let ImageURL = "imageUri" + } + + var imageURL: String { get { return stringValue(forKey: Keys.ImageURL) } } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/TimerViewController.swift b/ios/SAPTracker/src/xcode/SAPTracker/TimerViewController.swift index ac5da4f77ff..e6b47f37c78 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/TimerViewController.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/TimerViewController.swift @@ -10,28 +10,53 @@ import Foundation class TimerViewController: UIViewController { - @IBOutlet weak var trackingTimeLabel: UILabel! + private let startDate = NSDate() - let startDate = NSDate() - let dateFormatter = NSDateFormatter() + @IBOutlet weak var titleLabel: UILabel! + @IBOutlet weak var timeLabel: UILabel! override func viewDidLoad() { super.viewDidLoad() - - // start tracking timer - let timer = NSTimer(timeInterval: 0.1, target: self, selector: "timer:", userInfo: nil, repeats: true) - NSRunLoop.currentRunLoop().addTimer(timer, forMode:NSRunLoopCommonModes) - dateFormatter.dateFormat = "HH:mm:ss" - dateFormatter.timeZone = NSTimeZone(forSecondsFromGMT: 0) - + setup() } - // MARK:- Timer + // MARK: - Setup - func timer(timer: NSTimer) { + private func setup() { + setupLocalization() + setupTimer() + } + + private func setupLocalization() { + titleLabel.text = Translation.TimerView.TitleLabel.Text.String + } + + private func setupTimer() { + let timer = NSTimer(timeInterval: 0.1, + target: self, + selector: #selector(tick), + userInfo: nil, + repeats: true + ) + NSRunLoop.currentRunLoop().addTimer(timer, forMode:NSRunLoopCommonModes) + } + + // MARK: - Timer + + @objc private func tick(timer: NSTimer) { let currentDate = NSDate() let timeInterval = currentDate.timeIntervalSinceDate(startDate) let timerDate = NSDate(timeIntervalSince1970: timeInterval) - trackingTimeLabel.text = dateFormatter.stringFromDate(timerDate) + timeLabel.text = dateFormatter.stringFromDate(timerDate) } + + // MARK: - Properties + + private lazy var dateFormatter: NSDateFormatter = { + let dateFormatter = NSDateFormatter() + dateFormatter.dateFormat = "HH:mm:ss" + dateFormatter.timeZone = NSTimeZone(forSecondsFromGMT: 0) + return dateFormatter + }() + } \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker/TitleView.swift b/ios/SAPTracker/src/xcode/SAPTracker/TitleView.swift new file mode 100644 index 00000000000..34e219213be --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/TitleView.swift @@ -0,0 +1,102 @@ +// +// TitleView.swift +// SAPTracker +// +// Created by Raimund Wege on 03.08.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import UIKit + +class TitleView: UIView { + + private struct View { + static let TitleLabel = "titleLabel" + static let SubtitleLabel = "subtitleLabel" + } + + private var titleLabel: UILabel + private var subtitleLabel: UILabel + + // MARK: - Life cycle + + override init(frame: CGRect) { + titleLabel = UILabel(frame: CGRectZero) + titleLabel.translatesAutoresizingMaskIntoConstraints = false + titleLabel.backgroundColor = .clearColor() + titleLabel.textAlignment = .Center + titleLabel.textColor = Colors.NavigationBarTitleColor + titleLabel.font = Fonts.OpenSansBold13 + subtitleLabel = UILabel(frame: CGRectZero) + subtitleLabel.translatesAutoresizingMaskIntoConstraints = false + subtitleLabel.backgroundColor = .clearColor() + subtitleLabel.textAlignment = .Center + subtitleLabel.textColor = Colors.NavigationBarTitleColor + subtitleLabel.font = Fonts.OpenSans10 + super.init(frame: frame) + translatesAutoresizingMaskIntoConstraints = true + addSubviews() + } + + convenience init() { + self.init(frame: CGRectZero) + } + + convenience init(title: String, subtitle: String) { + self.init(frame: CGRectZero) + setTitle(title) + setSubtitle(subtitle) + } + + required init(coder aDecoder: NSCoder) { + fatalError("TitleView does not support NSCoding") + } + + private func addSubviews() { + addSubview(titleLabel) + addSubview(subtitleLabel) + } + + // MARK: - Methods + + func setTitle(title: String) { + titleLabel.text = title + titleLabel.sizeToFit() + sizeToFit() + setNeedsUpdateConstraints() + } + + func setSubtitle(subtitle: String) { + subtitleLabel.text = subtitle + subtitleLabel.sizeToFit() + sizeToFit() + setNeedsUpdateConstraints() + } + + // MARK: - Layout + + override func updateConstraints() { + removeConstraints(self.constraints) + let views = [View.TitleLabel: titleLabel, View.SubtitleLabel: subtitleLabel] + addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[\(View.TitleLabel)]|", + options: [], + metrics: nil, + views: views)) + addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[\(View.SubtitleLabel)]|", + options: [], + metrics: nil, + views: views)) + addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[\(View.TitleLabel)][\(View.SubtitleLabel)]|", + options: [], + metrics: nil, + views: views)) + super.updateConstraints() + } + + override func sizeThatFits(size: CGSize) -> CGSize { + let width = max(CGRectGetWidth(titleLabel.bounds), CGRectGetWidth(subtitleLabel.bounds)) + let height = CGRectGetHeight(titleLabel.bounds) + CGRectGetHeight(subtitleLabel.bounds) + return CGSizeMake(width, height) + } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/TrackingPageViewController.swift b/ios/SAPTracker/src/xcode/SAPTracker/TrackingPageViewController.swift index b0e729bb597..e84acf86f3d 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/TrackingPageViewController.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/TrackingPageViewController.swift @@ -17,8 +17,8 @@ class TrackingPageViewController : UIPageViewController, UIPageViewControllerDat override func viewDidLoad() { dataSource = self page1 = storyboard!.instantiateViewControllerWithIdentifier("Timer") as? TimerViewController - page2 = storyboard!.instantiateViewControllerWithIdentifier("Speed") - page3 = storyboard!.instantiateViewControllerWithIdentifier("Heading") + page2 = storyboard!.instantiateViewControllerWithIdentifier("Course") + page3 = storyboard!.instantiateViewControllerWithIdentifier("Speed") setViewControllers([page1!], direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil) } diff --git a/ios/SAPTracker/src/xcode/SAPTracker/TrackingViewController.swift b/ios/SAPTracker/src/xcode/SAPTracker/TrackingViewController.swift index 03313898920..33d6c9d6523 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/TrackingViewController.swift +++ b/ios/SAPTracker/src/xcode/SAPTracker/TrackingViewController.swift @@ -10,86 +10,114 @@ import Foundation class TrackingViewController : UIViewController { - struct Color { - static let GpsActive = UIColor(hex: 0x8AB54D) - static let GpsInactive = UIColor(hex: 0x445A2F) - static let Green = UIColor(hex: 0x408000) - static let Red = UIColor(hex: 0xFF0000) - static let Orange = UIColor(hex: 0xFF8000) - } + var regatta: Regatta! + var regattaController: RegattaController! - @IBOutlet weak var gpsAccuracy: UILabel! - @IBOutlet weak var trackingStatusLabel: UILabel! - @IBOutlet weak var cachedFixesLabel: UILabel! - @IBOutlet weak var onlineModeLabel: UILabel! + @IBOutlet weak var tableView: UITableView! + @IBOutlet weak var tableViewHeight: NSLayoutConstraint! + @IBOutlet weak var stopTrackingButton: UIButton! - /* Register for notifications. Set up timer */ override func viewDidLoad() { super.viewDidLoad() - - // set values - navigationItem.title = DataManager.sharedManager.selectedCheckIn!.leaderBoardName - cachedFixesLabel.text = String(format: "%d", DataManager.sharedManager.countCachedFixes()) - - // set online/buffering label - networkAvailabilityChanged() - - // register for notifications - NSNotificationCenter.defaultCenter().addObserver(self, selector:"networkAvailabilityChanged", name:APIManager.NotificationType.networkAvailabilityChanged, object: nil) - NSNotificationCenter.defaultCenter().addObserver(self, selector:"newLocation:", name:LocationManager.NotificationType.newLocation, object: nil) - NSNotificationCenter.defaultCenter().addObserver(self, selector:"locationManagerFailed:", name:LocationManager.NotificationType.locationManagerFailed, object: nil) - } - - // MARK:- Buttons - - /* Stop tracking, go back to regattas view */ - @IBAction func stopTrackingButtonTapped(sender: AnyObject) { - - let alertController = UIAlertController(title: NSLocalizedString("Stop tracking?", comment: ""), message: "", preferredStyle: .Alert) - let aCancel = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel, handler: nil) - alertController.addAction(aCancel) - let aStop = UIAlertAction(title: NSLocalizedString("Stop", comment: ""), style: .Default) { action in - LocationManager.sharedManager.stopTracking() - SendGPSFixController.sharedManager.checkIn = nil - self.dismissViewControllerAnimated(true, completion: nil) - } - alertController.addAction(aStop) - presentViewController(alertController, animated: true, completion: nil) - } - - // MARK:- Notifications - - deinit { - NSNotificationCenter.defaultCenter().removeObserver(self) + setup() } - func networkAvailabilityChanged() { - if (APIManager.sharedManager.networkAvailable) { - if !BatteryManager.sharedManager.batterySaving { - onlineModeLabel.text = NSLocalizedString("Online", comment: "") - onlineModeLabel.textColor = Color.Green - } else { - onlineModeLabel.text = NSLocalizedString("Battery Saving", comment: "") - onlineModeLabel.textColor = Color.Orange - } - } else { - onlineModeLabel.text = NSLocalizedString("Offline", comment: "") - onlineModeLabel.textColor = Color.Red + override func updateViewConstraints() { + super.updateViewConstraints() + tableViewHeight.constant = tableView.contentSize.height + } + + // MARK: - Setup + + private func setup() { + setupButtons() + setupLocalization() + setupNavigationBar() + } + + private func setupButtons() { + stopTrackingButton.setBackgroundImage(Images.RedHighlighted, forState: .Highlighted) + } + + private func setupLocalization() { + stopTrackingButton.setTitle(Translation.TrackingView.StopTrackingButton.Title.String, forState: .Normal) + } + + private func setupNavigationBar() { + navigationItem.leftBarButtonItem = UIBarButtonItem(customView: UIImageView(image: UIImage(named: "sap_logo"))) + navigationItem.titleView = TitleView(title: regatta.event.name, subtitle: regatta.leaderboard.name) + navigationController?.navigationBar.setNeedsLayout() + } + + // MARK: - Actions + + @IBAction func stopTrackingButtonTapped(sender: AnyObject) { + let alertController = UIAlertController(title: Translation.TrackingView.StopTrackingAlert.Title.String, + message: Translation.TrackingView.StopTrackingAlert.Message.String, + preferredStyle: .Alert + ) + let okAction = UIAlertAction(title: Translation.Common.OK.String, style: .Default) { action in + LocationManager.sharedManager.stopTracking() + SVProgressHUD.show() + self.regattaController.gpsFixController.sendAll({ (withSuccess) in + SVProgressHUD.popActivity() + self.dismissViewControllerAnimated(true, completion: nil) + }) } + let cancelAction = UIAlertAction(title: Translation.Common.Cancel.String, style: .Cancel, handler: nil) + alertController.addAction(okAction) + alertController.addAction(cancelAction) + presentViewController(alertController, animated: true, completion: nil) } - func newLocation(notification: NSNotification) { - let horizontalAccuracy = notification.userInfo!["horizontalAccuracy"] as! Double - gpsAccuracy.text = "~ " + String(format: "%.0f", horizontalAccuracy) + " m" - trackingStatusLabel.text = NSLocalizedString("Tracking", comment: "") - trackingStatusLabel.textColor = Color.Green - cachedFixesLabel.text = String(format: "%d", DataManager.sharedManager.countCachedFixes()) - } - - func locationManagerFailed(notification: NSNotification) { - gpsAccuracy.text = NSLocalizedString("No GPS", comment: "") - trackingStatusLabel.text = NSLocalizedString("Not Tracking", comment: "") - trackingStatusLabel.textColor = Color.Red - } +} +// MARK: - UITableViewDataSourceDelegate + +extension TrackingViewController: UITableViewDataSource { + + struct CellIdentifier { + static let StatusCell = "StatusCell" + static let ModeCell = "ModeCell" + static let ChachedFixesCell = "CachedFixesCell" + static let GPSAccuracyCell = "GPSAccuracyCell" + } + + @nonobjc static let Rows = [ + CellIdentifier.StatusCell, + CellIdentifier.ModeCell, + CellIdentifier.ChachedFixesCell, + CellIdentifier.GPSAccuracyCell + ] + + func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return TrackingViewController.Rows.count + } + + func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCellWithIdentifier(TrackingViewController.Rows[indexPath.row]) ?? UITableViewCell() + if let gpsFixesCell = cell as? TrackingViewGPSFixesCell { + gpsFixesCell.regatta = regatta + } + return cell + } + +} + +// MARK: - UITableViewDelegate + +extension TrackingViewController: UITableViewDelegate { + + func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { + return 52 + } + + func tableView(tableView: UITableView, estimatedHeightForFooterInSection section: Int) -> CGFloat { + return 0 + } + + func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { + cell.removeSeparatorInset() + } + } \ No newline at end of file diff --git a/ios/SAPTracker/src/xcode/SAPTracker/TrackingViewGPSAccuracyCell.swift b/ios/SAPTracker/src/xcode/SAPTracker/TrackingViewGPSAccuracyCell.swift new file mode 100644 index 00000000000..2e58f4c4771 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/TrackingViewGPSAccuracyCell.swift @@ -0,0 +1,78 @@ +// +// GPSAccuracyTrackingTableViewCell.swift +// SAPTracker +// +// Created by Raimund Wege on 07.06.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import UIKit + +class TrackingViewGPSAccuracyCell: UITableViewCell { + + @IBOutlet weak var gpsAccuracyTitleLabel: UILabel! + @IBOutlet weak var gpsAccuracyLabel: UILabel! + @IBOutlet weak var gpsAccuracyView: GPSAccuracyView! + + override func awakeFromNib() { + super.awakeFromNib() + setup() + subscribeForNotifications() + } + + deinit { + unsubscribeFromNotifications() + } + + // MARK: - Setup + + private func setup() { + setupGPSAccuracyLabel() + setupLocalization() + } + + private func setupGPSAccuracyLabel() { + gpsAccuracyLabel.text = Translation.TrackingView.TableView.GPSAccuracyCell.GPSAccuracyLabel.Text.NoGPS.String + } + + private func setupGPSAccuracyLabel(horizontalAccuracy: Double!) { + gpsAccuracyLabel.text = "~ " + String(format: "%.0f", horizontalAccuracy) + " m" + } + + private func setupLocalization() { + gpsAccuracyTitleLabel.text = Translation.TrackingView.TableView.GPSAccuracyCell.GPSAccuracyTitleLabel.Text.String + } + + // MARK: - Notifications + + private func subscribeForNotifications() { + NSNotificationCenter.defaultCenter().addObserver(self, + selector:#selector(locationManagerUpdated(_:)), + name:LocationManager.NotificationType.Updated, + object: nil + ) + NSNotificationCenter.defaultCenter().addObserver(self, + selector:#selector(locationManagerFailed(_:)), + name:LocationManager.NotificationType.Failed, + object: nil + ) + } + + private func unsubscribeFromNotifications() { + NSNotificationCenter.defaultCenter().removeObserver(self) + } + + @objc private func locationManagerUpdated(notification: NSNotification) { + dispatch_async(dispatch_get_main_queue(), { + guard let locationData = notification.userInfo?[LocationManager.UserInfo.LocationData] as? LocationData else { return } + self.setupGPSAccuracyLabel(locationData.location.horizontalAccuracy) + }) + } + + @objc private func locationManagerFailed(notification: NSNotification) { + dispatch_async(dispatch_get_main_queue(), { + self.setupGPSAccuracyLabel() + }) + } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/TrackingViewGPSFixesCell.swift b/ios/SAPTracker/src/xcode/SAPTracker/TrackingViewGPSFixesCell.swift new file mode 100644 index 00000000000..90eab9a97e3 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/TrackingViewGPSFixesCell.swift @@ -0,0 +1,63 @@ +// +// TrackingViewGPSFixesCell.swift +// SAPTracker +// +// Created by Raimund Wege on 07.06.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import UIKit + +class TrackingViewGPSFixesCell: UITableViewCell { + + var regatta: Regatta? + + @IBOutlet weak var gpsFixesTitleLabel: UILabel! + @IBOutlet weak var gpsFixesLabel: UILabel! + + override func awakeFromNib() { + super.awakeFromNib() + setup() + subscribeForNotifications() + } + + deinit { + unsubscribeFromNotifications() + } + + // MARK: - Setup + + private func setup() { + setupLocalization() + setupGPSFixesLabel() + } + + private func setupLocalization() { + gpsFixesTitleLabel.text = Translation.TrackingView.TableView.GPSFixesCell.GPSFixesTitleLabel.Text.String + } + + private func setupGPSFixesLabel() { + gpsFixesLabel.text = String(format: "%d", regatta?.gpsFixes?.count ?? 0) + } + + // MARK: - Notifications + + private func subscribeForNotifications() { + NSNotificationCenter.defaultCenter().addObserver(self, + selector:#selector(locationManagerUpdated(_:)), + name:LocationManager.NotificationType.Updated, + object: nil + ) + } + + private func unsubscribeFromNotifications() { + NSNotificationCenter.defaultCenter().removeObserver(self) + } + + @objc private func locationManagerUpdated(notification: NSNotification) { + dispatch_async(dispatch_get_main_queue(), { + self.setupGPSFixesLabel() + }) + } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/TrackingViewModeCell.swift b/ios/SAPTracker/src/xcode/SAPTracker/TrackingViewModeCell.swift new file mode 100644 index 00000000000..5887cd3a258 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/TrackingViewModeCell.swift @@ -0,0 +1,63 @@ +// +// TrackingViewModeCell.swift +// SAPTracker +// +// Created by Raimund Wege on 07.06.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import UIKit + +class TrackingViewModeCell: UITableViewCell { + + @IBOutlet weak var modeTitleLabel: UILabel! + @IBOutlet weak var modeLabel: UILabel! + + override func awakeFromNib() { + super.awakeFromNib() + setup() + subscribeForNotifications() + } + + deinit { + self.unsubscribeFromNotifications() + } + + // MARK: - Setup + + private func setup() { + setupLocalization() + setupModeLabel(GPSFixController.Mode.None) + } + + private func setupLocalization() { + modeTitleLabel.text = Translation.GPSFixController.Mode.String + } + + private func setupModeLabel(mode: GPSFixController.Mode) { + modeLabel.text = mode.description + } + + // MARK: - Notifications + + private func subscribeForNotifications() { + NSNotificationCenter.defaultCenter().addObserver(self, + selector:#selector(regattaControllerModeChanged), + name:GPSFixController.NotificationType.ModeChanged, + object: nil + ) + } + + private func unsubscribeFromNotifications() { + NSNotificationCenter.defaultCenter().removeObserver(self) + } + + @objc private func regattaControllerModeChanged(notification: NSNotification) { + dispatch_async(dispatch_get_main_queue(), { + guard let rawValue = notification.userInfo?[GPSFixController.UserInfo.Mode] as? String else { return } + guard let mode = GPSFixController.Mode(rawValue: rawValue) else { return } + self.setupModeLabel(mode) + }) + } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/TrackingViewStatusCell.swift b/ios/SAPTracker/src/xcode/SAPTracker/TrackingViewStatusCell.swift new file mode 100644 index 00000000000..c6948994cd2 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/TrackingViewStatusCell.swift @@ -0,0 +1,73 @@ +// +// TrackingViewStatusCell.swift +// SAPTracker +// +// Created by Raimund Wege on 07.06.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import UIKit + +class TrackingViewStatusCell: UITableViewCell { + + @IBOutlet weak var statusTitleLabel: UILabel! + @IBOutlet weak var statusLabel: UILabel! + + override func awakeFromNib() { + super.awakeFromNib() + setup() + subscribeForNotifications() + } + + deinit { + unsubscribeFromNotifications() + } + + // MARK: - Setup + + private func setup() { + setupLocalization() + setupStatusLabel(LocationManager.Status.NotTracking) + } + + private func setupLocalization() { + statusTitleLabel.text = Translation.LocationManager.Status.String + } + + private func setupStatusLabel(status: LocationManager.Status) { + statusLabel.text = status.description + statusLabel.textColor = (status == .NotTracking ? UIColor.redColor() : UIColor.blackColor()) + } + + // MARK: - Notifications + + private func subscribeForNotifications() { + NSNotificationCenter.defaultCenter().addObserver(self, + selector:#selector(locationManagerUpdated(_:)), + name:LocationManager.NotificationType.Updated, + object: nil + ) + NSNotificationCenter.defaultCenter().addObserver(self, + selector:#selector(locationManagerFailed(_:)), + name:LocationManager.NotificationType.Failed, + object: nil + ) + } + + private func unsubscribeFromNotifications() { + NSNotificationCenter.defaultCenter().removeObserver(self) + } + + @objc private func locationManagerUpdated(notification: NSNotification) { + dispatch_async(dispatch_get_main_queue(), { + self.setupStatusLabel(LocationManager.Status.Tracking) + }) + } + + @objc private func locationManagerFailed(notification: NSNotification) { + dispatch_async(dispatch_get_main_queue(), { + self.setupStatusLabel(LocationManager.Status.NotTracking) + }) + } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/Translation.swift b/ios/SAPTracker/src/xcode/SAPTracker/Translation.swift new file mode 100644 index 00000000000..e0e3d96d499 --- /dev/null +++ b/ios/SAPTracker/src/xcode/SAPTracker/Translation.swift @@ -0,0 +1,425 @@ +// +// Translation.swift +// SAPTracker +// +// Created by Raimund Wege on 27.07.16. +// Copyright © 2016 com.sap.sailing. All rights reserved. +// + +import UIKit + +class Translation: NSObject { + + struct Common { static let Key = "\(Common.self)" + struct Cancel { static let Key = "\(Common.Key).\(Cancel.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct OK { static let Key = "\(Common.Key).\(OK.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct Info { static let Key = "\(Common.Key).\(Info.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct Settings { static let Key = "\(Common.Key).\(Settings.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct Warning { static let Key = "\(Common.Key).\(Warning.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct Error { static let Key = "\(Common.Key).\(Error.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct Yes { static let Key = "\(Common.Key).\(Yes.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct No { static let Key = "\(Common.Key).\(No.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + + // MARK: - CheckInController + + struct CheckInController { static let Key = "\(CheckInController.self)" + struct WelcomeAlert { static let Key = "\(CheckInController.Key).\(WelcomeAlert.self)" + struct Title { static let Key = "\(WelcomeAlert.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct Message { static let Key = "\(WelcomeAlert.Key).\(Message.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct CancelAction { static let Key = "\(WelcomeAlert.Key).\(CancelAction.self)" + struct Title { static let Key = "\(CancelAction.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + } + } + + // MARK: - GPSFixController + + struct GPSFixController { static let Key = "\(GPSFixController.self)" + struct Mode { static let Key = "\(GPSFixController.Key).\(Mode.self)" + static let String = NSLocalizedString(Key, comment: "") + struct Error { static let Key = "\(Mode.Key).\(Error.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct BatterySaving { static let Key = "\(Mode.Key).\(BatterySaving.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct None { static let Key = "\(Mode.Key).\(None.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct Online { static let Key = "\(Mode.Key).\(Online.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct Offline { static let Key = "\(Mode.Key).\(Offline.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + } + + // MARK: - LocationManager + + struct LocationManager { static let Key = "\(LocationManager.self)" + struct LocationServicesDeniedError { static let Key = "\(LocationManager.Key).\(LocationServicesDeniedError.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct LocationServicesDisabledError { static let Key = "\(LocationManager.Key).\(LocationServicesDisabledError.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct Status { static let Key = "\(LocationManager.Key).\(Status.self)" + static let String = NSLocalizedString(Key, comment: "") + struct Tracking { static let Key = "\(Status.Key).\(Tracking.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct NotTracking { static let Key = "\(Status.Key).\(NotTracking.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + } + + // MARK: - RequestManager + + struct RequestManager { static let Key = "\(RequestManager.self)" + struct Failure { static let Key = "\(RequestManager.Key).\(Failure.self)" + struct Message { static let Key = "\(Failure.Key).\(Message.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct EventLoadingFailure { static let Key = "\(RequestManager.Key).\(EventLoadingFailure.self)" + struct Message { static let Key = "\(EventLoadingFailure.Key).\(Message.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct LeaderboardLoadingFailure { static let Key = "\(RequestManager.Key).\(LeaderboardLoadingFailure.self)" + struct Message { static let Key = "\(LeaderboardLoadingFailure.Key).\(Message.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct CompetitorLoadingFailure { static let Key = "\(RequestManager.Key).\(CompetitorLoadingFailure.self)" + struct Message { static let Key = "\(CompetitorLoadingFailure.Key).\(Message.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct TeamImageUploadFailure { static let Key = "\(RequestManager.Key).\(TeamImageUploadFailure.self)" + struct Title { static let Key = "\(TeamImageUploadFailure.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + } + + // MARK: - AboutView + + struct AboutView { static let Key = "\(AboutView.self)" + struct Title { static let Key = "\(AboutView.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct PartnershipTextView { static let Key = "\(AboutView.Key).\(PartnershipTextView.self)" + struct Text { static let Key = "\(PartnershipTextView.Key).\(Text.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct TermsButton { static let Key = "\(AboutView.Key).\(TermsButton.self)" + struct Title { static let Key = "\(TermsButton.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct VersionTitleLabel { static let Key = "\(AboutView.Key).\(VersionTitleLabel.self)" + struct Text { static let Key = "\(VersionTitleLabel.Key).\(Text.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + } + + // MARK: - CourseView + + struct CourseView { static let Key = "\(CourseView.self)" + struct TitleLabel { static let Key = "\(CourseView.Key).\(TitleLabel.self)" + struct Text { static let Key = "\(TitleLabel.Key).\(Text.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + } + + // MARK: - HomeView + + struct HomeView { static let Key = "\(HomeView.self)" + struct HeaderTitleLabel { static let Key = "\(HomeView.Key).\(HeaderTitleLabel.self)" + struct Text { static let Key = "\(HeaderTitleLabel.Key).\(Text.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct FooterTextView { static let Key = "\(HomeView.Key).\(FooterTextView.self)" + struct Text { static let Key = "\(FooterTextView.Key).\(Text.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct InfoCodeLabel { static let Key = "\(HomeView.Key).\(InfoCodeLabel.self)" + struct Text { static let Key = "\(InfoCodeLabel.Key).\(Text.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct TermsAlert { static let Key = "\(HomeView.Key).\(TermsAlert.self)" + struct Title { static let Key = "\(TermsAlert.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct Message { static let Key = "\(TermsAlert.Key).\(Message.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct ShowTermsAction { static let Key = "\(TermsAlert.Key).\(ShowTermsAction.self)" + struct Title { static let Key = "\(ShowTermsAction.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct AcceptTermsAction { static let Key = "\(TermsAlert.Key).\(AcceptTermsAction.self)" + struct Title { static let Key = "\(AcceptTermsAction.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + } + struct NoCameraAlert { static let Key = "\(HomeView.Key).\(NoCameraAlert.self)" + struct Message { static let Key = "\(NoCameraAlert.Key).\(Message.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct NoCodeAlert { static let Key = "\(HomeView.Key).\(NoCodeAlert.self)" + struct Title { static let Key = "\(NoCodeAlert.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct Message { static let Key = "\(NoCodeAlert.Key).\(Message.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + } + + // MARK: - LeaderboardView + + struct LeaderboardView { static let Key = "\(LeaderboardView.self)" + struct Title { static let Key = "\(LeaderboardView.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + + // MARK: - LicenseView + + struct LicenseView { static let Key = "\(LicenseView.self)" + struct Title { static let Key = "\(LicenseView.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + + // MARK: - RegattaView + + struct RegattaView { static let Key = "\(RegattaView.self)" + struct CountdownDaysTitleLabel { static let Key = "\(RegattaView.Key).\(CountdownDaysTitleLabel.self)" + struct Text { static let Key = "\(CountdownDaysTitleLabel.Key).\(Text.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct CountdownHoursTitleLabel { static let Key = "\(RegattaView.Key).\(CountdownHoursTitleLabel.self)" + struct Text { static let Key = "\(CountdownHoursTitleLabel.Key).\(Text.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct CountdownMinutesTitleLabel { static let Key = "\(RegattaView.Key).\(CountdownMinutesTitleLabel.self)" + struct Text { static let Key = "\(CountdownMinutesTitleLabel.Key).\(Text.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct RegattaStartLabel { static let Key = "\(RegattaView.Key).\(RegattaStartLabel.self)" + struct Text { static let Key = "\(RegattaStartLabel.Key).\(Text.self)" + struct BeforeRegattaDidStart { static let Key = "\(Text.Key).\(BeforeRegattaDidStart.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct AfterRegattaDidStart { static let Key = "\(Text.Key).\(AfterRegattaDidStart.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + } + struct AnnouncementLabel { static let Key = "\(RegattaView.Key).\(AnnouncementLabel.self)" + struct Text { static let Key = "\(AnnouncementLabel.Key).\(Text.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct EventButton { static let Key = "\(RegattaView.Key).\(EventButton.self)" + struct Title { static let Key = "\(EventButton.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct StartTrackingButton { static let Key = "\(RegattaView.Key).\(StartTrackingButton.self)" + struct Title { static let Key = "\(StartTrackingButton.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct OptionSheet { static let Key = "\(RegattaView.Key).\(OptionSheet.self)" + struct CheckOutAction { static let Key = "\(OptionSheet.Key).\(CheckOutAction.self)" + struct Title { static let Key = "\(CheckOutAction.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct ReplaceImageAction { static let Key = "\(OptionSheet.Key).\(ReplaceImageAction.self)" + struct Title { static let Key = "\(ReplaceImageAction.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct UpdateAction { static let Key = "\(OptionSheet.Key).\(UpdateAction.self)" + struct Title { static let Key = "\(UpdateAction.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + } + struct CheckOutAlert { static let Key = "\(RegattaView.Key).\(CheckOutAlert.self)" + struct Message { static let Key = "\(CheckOutAlert.Key).\(Message.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct SelectImageAlert { static let Key = "\(RegattaView.Key).\(SelectImageAlert.self)" + struct Title { static let Key = "\(SelectImageAlert.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct Message { static let Key = "\(SelectImageAlert.Key).\(Message.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct CameraAction { static let Key = "\(SelectImageAlert.Key).\(CameraAction.self)" + struct Title { static let Key = "\(CameraAction.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct PhotoLibraryAction { static let Key = "\(SelectImageAlert.Key).\(PhotoLibraryAction.self)" + struct Title { static let Key = "\(PhotoLibraryAction.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + } + } + + // MARK: - ScanView + + struct ScanView { static let Key = "\(ScanView.self)" + struct Title { static let Key = "\(ScanView.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct IncorrectCodeAlert { static let Key = "\(ScanView.Key).\(IncorrectCodeAlert.self)" + struct Message { static let Key = "\(IncorrectCodeAlert.Key).\(Message.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + } + + // MARK: - SettingsView + + struct SettingsView { static let Key = "\(SettingsView.self)" + struct Title { static let Key = "\(SettingsView.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct TableView { static let Key = "\(SettingsView.Key).\(TableView.self)" + struct BatterySavingSection { static let Key = "\(TableView.Key).\(BatterySavingSection.self)" + struct Title { static let Key = "\(BatterySavingSection.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct OtherSettingsSection { static let Key = "\(TableView.Key).\(OtherSettingsSection.self)" + struct Title { static let Key = "\(OtherSettingsSection.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + } + struct BatterySavingTitleLabel { static let Key = "\(SettingsView.Key).\(BatterySavingTitleLabel.self)" + struct Text { static let Key = "\(BatterySavingTitleLabel.Key).\(Text.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct BatterySavingDescriptionLabel { static let Key = "\(SettingsView.Key).\(BatterySavingDescriptionLabel.self)" + struct Text { static let Key = "\(BatterySavingDescriptionLabel.Key).\(Text.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct DeviceIdentifierTitleLabel { static let Key = "\(SettingsView.Key).\(DeviceIdentifierTitleLabel.self)" + struct Text { static let Key = "\(DeviceIdentifierTitleLabel.Key).\(Text.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + } + + // MARK: - SpeedView + + struct SpeedView { static let Key = "\(SpeedView.self)" + struct TitleLabel { static let Key = "\(SpeedView.Key).\(TitleLabel.self)" + struct Text { static let Key = "\(TitleLabel.Key).\(Text.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + } + + // MARK: - TimerView + + struct TimerView { static let Key = "\(TimerView.self)" + struct TitleLabel { static let Key = "\(TimerView.Key).\(TitleLabel.self)" + struct Text { static let Key = "\(TitleLabel.Key).\(Text.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + } + + // MARK: - TrackingView + + struct TrackingView { static let Key = "\(TrackingView.self)" + struct TableView { static let Key = "\(TrackingView.Key).\(TableView.self)" + struct GPSAccuracyCell { static let Key = "\(TableView.Key).\(GPSAccuracyCell.self)" + struct GPSAccuracyTitleLabel { static let Key = "\(GPSAccuracyCell.Key).\(GPSAccuracyTitleLabel.self)" + struct Text { static let Key = "\(GPSAccuracyTitleLabel.Key).\(Text.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct GPSAccuracyLabel { static let Key = "\(GPSAccuracyCell.Key).\(GPSAccuracyLabel.self)" + struct Text { static let Key = "\(GPSAccuracyLabel.Key).\(Text.self)" + struct NoGPS { static let Key = "\(Text.Key).\(NoGPS.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + } + } + struct GPSFixesCell { static let Key = "\(TableView.Key).\(GPSFixesCell.self)" + struct GPSFixesTitleLabel { static let Key = "\(GPSFixesCell.Key).\(GPSFixesTitleLabel.self)" + struct Text { static let Key = "\(GPSFixesTitleLabel.Key).\(Text.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + } + } + struct StopTrackingButton { static let Key = "\(TrackingView.Key).\(StopTrackingButton.self)" + struct Title { static let Key = "\(StopTrackingButton.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + struct StopTrackingAlert { static let Key = "\(TrackingView.Key).\(StopTrackingAlert.self)" + struct Title { static let Key = "\(StopTrackingAlert.Key).\(Title.self)" + static let String = NSLocalizedString(Key, comment: "") + } + struct Message { static let Key = "\(StopTrackingAlert.Key).\(Message.self)" + static let String = NSLocalizedString(Key, comment: "") + } + } + } + +} diff --git a/ios/SAPTracker/src/xcode/SAPTracker/bridge.h b/ios/SAPTracker/src/xcode/SAPTracker/bridge.h index 745a83245df..979389a8d38 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/bridge.h +++ b/ios/SAPTracker/src/xcode/SAPTracker/bridge.h @@ -9,13 +9,11 @@ #ifndef SAPTracker_bridge_h #define SAPTracker_bridge_h -#import -#import -#import "UIImageView+AFNetworking.h" -#import "Appearance.h" - -#if DEBUG -#import "AFNetworkActivityLogger.h" -#endif +#import "Libraries/AFNetworking/AFNetworking.h" +#import "Libraries/TSMarkdownParser/TSMarkdownParser.h" +#import "Libraries/SVProgressHUD/SVProgressHUD.h" +#import "Libraries/UIKit+AFNetworking/UIImageView+AFNetworking.h" +#import "Libraries/UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h" +#import "Libraries/SMTWiFiStatus/SMTWiFiStatus.h" #endif diff --git a/ios/SAPTracker/src/xcode/SAPTracker/de.lproj/Localizable.strings b/ios/SAPTracker/src/xcode/SAPTracker/de.lproj/Localizable.strings index 7a1d2b6e2b9..99759f2342d 100644 Binary files a/ios/SAPTracker/src/xcode/SAPTracker/de.lproj/Localizable.strings and b/ios/SAPTracker/src/xcode/SAPTracker/de.lproj/Localizable.strings differ diff --git a/ios/SAPTracker/src/xcode/SAPTracker/de.lproj/Main.strings b/ios/SAPTracker/src/xcode/SAPTracker/de.lproj/Main.strings deleted file mode 100644 index 1494b97b983..00000000000 --- a/ios/SAPTracker/src/xcode/SAPTracker/de.lproj/Main.strings +++ /dev/null @@ -1,192 +0,0 @@ - -/* Class = "UILabel"; text = "COG"; ObjectID = "1Tn-6d-NlO"; */ -"1Tn-6d-NlO.text" = "COG"; - -/* Class = "UIView"; accessibilityLabel = "Name, Sail ID"; ObjectID = "2UK-je-59c"; */ -"2UK-je-59c.accessibilityLabel" = "Name, Sail ID"; - -/* Class = "UILabel"; text = "Tracking läuft"; ObjectID = "5Xu-6g-tqP"; */ -"5Xu-6g-tqP.text" = "Tracking läuft"; - -/* Class = "UIButton"; normalTitle = "EULA"; ObjectID = "8Vc-YY-1rh"; */ -"8Vc-YY-1rh.normalTitle" = "EULA"; - -/* Class = "UILabel"; accessibilityLabel = "Der QR-Code befindet sich auf Ihrer Teilnahmebestätigung"; ObjectID = "8aO-2n-aG5"; */ -"8aO-2n-aG5.accessibilityLabel" = "Der QR-Code befindet sich auf Ihrer Teilnahmebestätigung"; - -/* Class = "UILabel"; text = "Bitte achten Sie auf die Durchsagen"; ObjectID = "8aO-2n-aG5"; */ -"8aO-2n-aG5.text" = "Bitte achten Sie auf die Durchsagen"; - -/* Class = "UINavigationItem"; title = "Über"; ObjectID = "8o6-Yh-CuN"; */ -"8o6-Yh-CuN.title" = "Über"; - -/* Class = "UINavigationItem"; title = "Leader Board"; ObjectID = "8qz-J9-1KL"; */ -"8qz-J9-1KL.title" = "Leader Board"; - -/* Class = "UIBarButtonItem"; title = "Home"; ObjectID = "ASu-3l-KjT"; */ -"ASu-3l-KjT.title" = "Home"; - -/* Class = "UIBarButtonItem"; title = "Annehmen"; ObjectID = "Agc-gU-hjA"; */ -"Agc-gU-hjA.title" = "Annehmen"; - -/* Class = "UINavigationItem"; title = "Regatta"; ObjectID = "BjQ-Fx-PEX"; */ -"BjQ-Fx-PEX.title" = "Regatta"; - -/* Class = "UIButton"; normalTitle = "Team Foto"; ObjectID = "CDA-ep-bjo"; */ -"CDA-ep-bjo.normalTitle" = "Team Foto"; - -/* Class = "UILabel"; text = "kein GPS"; ObjectID = "DiM-MR-SGV"; */ -"DiM-MR-SGV.text" = "kein GPS"; - -/* Class = "UILabel"; text = "Minuten"; ObjectID = "EES-a9-qxv"; */ -"EES-a9-qxv.text" = "Minuten"; - -/* Class = "UIButton"; accessibilityLabel = "Sie haben keinen QR-Code?"; ObjectID = "Fp0-61-7he"; */ -"Fp0-61-7he.accessibilityLabel" = "Sie haben keinen QR-Code?"; - -/* Class = "UIButton"; normalTitle = "Sie haben keinen QR-Code?"; ObjectID = "Fp0-61-7he"; */ -"Fp0-61-7he.normalTitle" = "Sie haben keinen QR-Code?"; - -/* Class = "UILabel"; text = "Titel"; ObjectID = "FzL-oN-acm"; */ -"FzL-oN-acm.text" = "Titel"; - -/* Class = "UILabel"; text = "Tracking Zeit"; ObjectID = "IeZ-JM-OWw"; */ -"IeZ-JM-OWw.text" = "Tracking Zeit"; - -/* Class = "UIButton"; accessibilityLabel = "QR-Code scannen"; ObjectID = "Ieu-ch-jeI"; */ -"Ieu-ch-jeI.accessibilityLabel" = "QR-Code scannen"; - -/* Class = "UIButton"; normalTitle = "QR-Code scannen"; ObjectID = "Ieu-ch-jeI"; */ -"Ieu-ch-jeI.normalTitle" = "QR-Code scannen"; - -/* Class = "UILabel"; text = "1.0.0"; ObjectID = "Jsi-LA-7jU"; */ -"Jsi-LA-7jU.text" = "1.0.0"; - -/* Class = "UINavigationItem"; title = "QR-Code scannen"; ObjectID = "LQ4-39-f6l"; */ -"LQ4-39-f6l.title" = "QR-Code scannen"; - -/* Class = "UIButton"; normalTitle = "Lizenzinformationen"; ObjectID = "MpZ-GD-6aE"; */ -"MpZ-GD-6aE.normalTitle" = "Lizenzinformationen"; - -/* Class = "UILabel"; accessibilityLabel = "Der QR-Code befindet sich auf Ihrer Teilnahmebestätigung"; ObjectID = "OqX-q3-43s"; */ -"OqX-q3-43s.accessibilityLabel" = "Der QR-Code befindet sich auf Ihrer Teilnahmebestätigung"; - -/* Class = "UILabel"; text = "Der QR-Code befindet sich auf Ihrer Teilnahmebestätigung"; ObjectID = "OqX-q3-43s"; */ -"OqX-q3-43s.text" = "Der QR-Code befindet sich auf Ihrer Teilnahmebestätigung"; - -/* Class = "UIButton"; normalTitle = "Leader Board"; ObjectID = "P9e-ZM-HZP"; */ -"P9e-ZM-HZP.normalTitle" = "Leader Board"; - -/* Class = "UITableViewSection"; headerTitle = "Batterie Sparen"; ObjectID = "PQM-l6-Zw8"; */ -"PQM-l6-Zw8.headerTitle" = "Batterie Sparen"; - -/* Class = "UINavigationItem"; title = "Tracker"; ObjectID = "Pei-UE-kDI"; */ -"Pei-UE-kDI.title" = "Tracker"; - -/* Class = "UIViewController"; title = "Timer"; ObjectID = "QJL-mi-hJE"; */ -"QJL-mi-hJE.title" = "Timer"; - -/* Class = "UIViewController"; title = "Geschwindigkeit"; ObjectID = "RAt-Nw-u56"; */ -"RAt-Nw-u56.title" = "Geschwindigkeit"; - -/* Class = "UINavigationItem"; title = "Einstellungen"; ObjectID = "SbA-xV-4ro"; */ -"SbA-xV-4ro.title" = "Einstellungen"; - -/* Class = "UILabel"; text = "59"; ObjectID = "Txm-uf-MP4"; */ -"Txm-uf-MP4.text" = "59"; - -/* Class = "UIButton"; normalTitle = "Stoppe Tracking"; ObjectID = "ULl-vy-5gb"; */ -"ULl-vy-5gb.normalTitle" = "Stoppe Tracking"; - -/* Class = "UILabel"; text = "Cached Fixes"; ObjectID = "Ujw-jg-ilY"; */ -"Ujw-jg-ilY.text" = "Cached Fixes"; - -/* Class = "UILabel"; text = "Geschwindigkeit"; ObjectID = "V9h-qX-rao"; */ -"V9h-qX-rao.text" = "Geschwindigkeit"; - -/* Class = "UILabel"; text = "Modus"; ObjectID = "Xww-rc-pOA"; */ -"Xww-rc-pOA.text" = "Modus"; - -/* Class = "UILabel"; text = "Version"; ObjectID = "YpQ-wa-mW3"; */ -"YpQ-wa-mW3.text" = "Version"; - -/* Class = "UILabel"; text = "GPS Genauigkeit"; ObjectID = "Z1d-5I-pbj"; */ -"Z1d-5I-pbj.text" = "GPS Genauigkeit"; - -/* Class = "UINavigationItem"; title = "AGB"; ObjectID = "bO3-X5-ui2"; */ -"bO3-X5-ui2.title" = "AGB"; - -/* Class = "UILabel"; text = "Stunden"; ObjectID = "c2J-Uj-KEg"; */ -"c2J-Uj-KEg.text" = "Stunden"; - -/* Class = "UILabel"; text = "0"; ObjectID = "dz3-w7-CCh"; */ -"dz3-w7-CCh.text" = "0"; - -/* Class = "UIViewController"; title = "Tracking"; ObjectID = "eHd-jN-WkS"; */ -"eHd-jN-WkS.title" = "Tracking"; - -/* Class = "UILabel"; text = "Batterie Sparen"; ObjectID = "eRQ-p8-ydN"; */ -"eRQ-p8-ydN.text" = "Batterie Sparen"; - -/* Class = "UILabel"; text = "Regatta beginnt in"; ObjectID = "ft9-jD-C5m"; */ -"ft9-jD-C5m.text" = "Regatta beginnt in"; - -/* Class = "UINavigationItem"; title = "Tracking"; ObjectID = "fyS-rY-bYp"; */ -"fyS-rY-bYp.title" = "Tracking"; - -/* Class = "UILabel"; text = "Letzte Synchronisierung"; ObjectID = "gHJ-am-Ulb"; */ -"gHJ-am-Ulb.text" = "Letzte Synchronisierung"; - -/* Class = "UILabel"; text = "24"; ObjectID = "gaG-Iv-Xyq"; */ -"gaG-Iv-Xyq.text" = "24"; - -/* Class = "UILabel"; text = "GER 17"; ObjectID = "iIf-9z-7fe"; */ -"iIf-9z-7fe.text" = "GER 17"; - -/* Class = "UILabel"; text = "0.0 kn"; ObjectID = "l5u-i3-029"; */ -"l5u-i3-029.text" = "0.0 kn"; - -/* Class = "UILabel"; text = "Tage"; ObjectID = "l8F-Sg-cUb"; */ -"l8F-Sg-cUb.text" = "Tage"; - -/* Class = "UINavigationItem"; title = "Tracker"; ObjectID = "lqI-5f-PEI"; */ -"lqI-5f-PEI.title" = "Tracker"; - -/* Class = "UILabel"; text = "00:00.00"; ObjectID = "mUm-EE-6Is"; */ -"mUm-EE-6Is.text" = "00:00.00"; - -/* Class = "UIButton"; normalTitle = "Starte Tracking"; ObjectID = "mj9-m1-nYY"; */ -"mj9-m1-nYY.normalTitle" = "Starte Tracking"; - -/* Class = "UILabel"; text = "Max Mustermann"; ObjectID = "oJS-dM-2B6"; */ -"oJS-dM-2B6.text" = "Max Mustermann"; - -/* Class = "UIViewController"; title = "Kurs"; ObjectID = "pzM-XJ-vUZ"; */ -"pzM-XJ-vUZ.title" = "Kurs"; - -/* Class = "UINavigationItem"; title = "Tracking"; ObjectID = "qW6-wb-0HC"; */ -"qW6-wb-0HC.title" = "Tracking"; - -/* Class = "UINavigationItem"; title = "Tracking"; ObjectID = "qfB-FT-Ysz"; */ -"qfB-FT-Ysz.title" = "Tracking"; - -/* Class = "UILabel"; text = "Status"; ObjectID = "r6d-OU-cRI"; */ -"r6d-OU-cRI.text" = "Status"; - -/* Class = "UIPageViewController"; title = "Tracking Page View Controller"; ObjectID = "rjH-vb-OUF"; */ -"rjH-vb-OUF.title" = "Tracking Page View Controller"; - -/* Class = "UILabel"; text = "356"; ObjectID = "sGD-0U-P4b"; */ -"sGD-0U-P4b.text" = "356"; - -/* Class = "UILabel"; text = "0 °"; ObjectID = "sGK-xV-9a0"; */ -"sGK-xV-9a0.text" = "0 °"; - -/* Class = "UILabel"; text = "Online"; ObjectID = "tJY-RR-vpe"; */ -"tJY-RR-vpe.text" = "Online"; - -/* Class = "UIViewController"; title = "Home"; ObjectID = "vXZ-lx-hvc"; */ -"vXZ-lx-hvc.title" = "Home"; - -/* Class = "UIBarButtonItem"; title = "Ablehnen"; ObjectID = "xAL-3o-tyx"; */ -"xAL-3o-tyx.title" = "Ablehnen"; diff --git a/ios/SAPTracker/src/xcode/SAPTracker/de.lproj/eula-ios.html b/ios/SAPTracker/src/xcode/SAPTracker/de.lproj/eula-ios.html deleted file mode 100644 index 47599f8eb96..00000000000 --- a/ios/SAPTracker/src/xcode/SAPTracker/de.lproj/eula-ios.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - -

Please scroll down and read the following end user license agreement carefully. This is a legal agreement ("Agreement") between you and SAP SE which provides the terms of your use of the SAP Mobile Application ("Software"). By clicking "I Accept" or by installing and/or using the Software, you are agreeing to all of the terms and conditions stated in this Agreement. If You do not agree to these terms, do not click "agree", and do not use the Software.

-

1 Definitions

- -

"SAP" refers to SAP SE, for and on behalf of itself and its subsidiaries and affiliates as defined in Section 15 German Stock Corporation Act. "You" and "Your" refers to the individual that wishes to use the Software. "Apple" refers to Apple, Inc. and its majority owned affiliates.

- -

2 Supported Devices

- -

The Software supports certain Apple mobile devices, and data networks such as 3G, EDGE and WiFi, and enables users to access SAP Standard Software for use of specifically enabled business processes through such Apple mobile devices.

- -

3 License

- -

Subject to the terms, conditions and limitations stated in this Agreement and the Apple App Store Terms of Service, SAP grants You a personal, non-exclusive, non-transferable, non-sublicensable, revocable, limited license to run the Software on Your Apple mobile device solely for the purpose of the Software accessing SAP Backend Software. For the avoidance of doubt, this Agreement does not include a license for SAP Standard Software. You are not permitted to use the Software for any purpose other than as expressly permitted under this Agreement. SAP may audit Your use of the Software. You shall use the Software only in a manner consistent with this Agreement and the documentation (the "Documentation") which SAP may provide, in its sole discretion, in electronic and/or printed form with the Software and which can be found under http://service.sap.com.

- -

4 Intellectual Property

- -

SAP retains all ownership and intellectual property rights in the Software. You may not: a) remove or modify any marks or proprietary notices of SAP, b) provide or make the Software available to any third party, c) use the Software to provide third party training for SAP products, d) assign this Agreement or give or transfer the Software or an interest in them to another individual or entity, e) decompile, disassemble or reverse engineer (except to the extent permitted by applicable law) the Software, f) create derivative works of or based on the Software or g) use any SAP name, trademark or logo.

- -

5 User Content

- -

a) "User Content" means any communications, images, and all the material, data, and information that You upload or transmits through Software. -b) Company hereby grants SAP a perpetual and irrevocable, worldwide, fully paid-up and royalty free, non-exclusive, unlimited license, including the right to sublicense and assign to third parties, and right to store, use, copy, reproduce, fix, adapt, modify, improve, translate, reformat, create derivative works from, process, analyze, manufacture, introduce into circulation, commercialize, publish, distribute, license, sublicense, transfer, rent, lease, transmit, publicly display, publicly perform, or provide access to electronically, broadcast, communicate to the public by telecommunication, display, perform, enter into computer memory, and use and practice, in any way now known or in the future discovered, Your User Content as well as all modified and derivative works thereof. -c) By transmitting or submitting any User Content while using the Software, You affirm, represent and warrant that such transmission or submission is (i) accurate; (ii) not in violation of any laws, contractual restrictions or other third party rights, and that You have permission from any third party whose information or intellectual property is comprised in the User Content; and (iii) free of viruses, adware, spyware, worms or other malicious code. -d) You acknowledge and agree that any of Your personal information within such content will at all times be processed by SAP in accordance with its Privacy Policy (http://www.sap.com/corporate-en/our-company/legal/privacy.epx).

- -

6 Warranty

- -

As there is no charge for the license of the Software hereunder, You are not entitled to the elimination of any defects or to subsequent delivery of Software. SAP will compensate for loss or wasted anticipatory expenditure arising out of defects subject to the limitation of liability in section 7 herein.

- -

7 Liability

- -

7.1 SAP is liable for damages or wasted anticipatory expenditures, in tort or otherwise, only (a) under German product liability legislation, (b) for SAP’s gross negligence or intent, (c) for absence of an expressly assured or guaranteed quality, or (d) for personal injury. -7.2 Where SAP is liable for grossly negligent acts of its employees who are not directors or officers of SAP, SAP’s total liability for damages is limited to that liability and to not more than the quantum of loss that SAP ought, in the light of its knowledge of circumstances at the time this License Agreement was made, to have foreseen as typical in connection with provision and licensed use of Software. -7.3 Where SAP is liable under section 7.2, it is not liable for indirect loss, consequential damages, or loss of profit. -7.4 SAP and Licensee agree that the typical foreseeable quantum of loss cannot exceed €50,000 in any case. -7.5 Licensee undertakes to take appropriate steps to safeguard its data and programs, including without limitation making backup copies not less frequently than is recommended by SAP. Notwithstanding the other limitations of this section 7, SAP is not liable for the loss of data and its recreation, in so far as this would have been avoidable through observance of this obligation. -7.6 The benefit of exclusions and limitations in this section 7 also extends to claims of Customer against employees, contractors, and agents of SAP.

- -

8 Indemnification

- -

SAP will defend at its own expense any legal proceeding brought against You, to the extent that such proceeding is based on a claim that the use of the Software as permitted under this Agreement represents an infringement or misappropriation of a third party’s copyright, patent, or a trade secret, and will pay all damages and costs awarded by a court of final appeal attributable to such claim; provided, however, that You: a) provide notice of the claim promptly to SAP (but no later than one (1) month after You received notice of the claim), b) give SAP sole control of the defense and settlement of the claim, provided that You, at Your option and expense, may also be represented in the legal proceeding by independent counsel, c) provides to SAP, at SAP’s expense, all commercially reasonable information, assistance and authority to defend such claim and d) have not compromised or settled such proceeding without SAP’s prior written consent.SAP shall have no liability for any infringement or claim which results from the use of the Software provided hereunder in combination with any equipment, software or data not provided or approved by SAP. This section states the entire liability of SAP with respect to the indemnification of any intellectual property right infringement hereunder and there shall be no additional liability with respect to any alleged or proven infringement. Section 7 shall apply accordingly.

- -

9 Export

- -

The Software is subject to German, EU and US export control regulations. You confirm that: a) You will not use the Software for, and will not allow the Software to be used for, any purposes prohibited by German, EU and US law, including, without limitation, for the development, design, manufacture or production of nuclear, chemical or biological weapons of mass destruction, b) You are not located in a country that is subject to a U.S. Government embargo, or that has been designated by the U.S. Government as a "terrorist supporting" country, c) You are not a citizen, national or resident of, and are not under the control of, the government of: Cuba, Iran, Sudan, Iraq, North Korea, Syria, nor any other country to which the United States has prohibited export, d) You will not download or otherwise export or re-export the Software, directly or indirectly, neither to the above-mentioned countries nor to citizens, nationals or residents of those countries, e) You are not listed on the United States Department of Treasury lists of Specially Designated Nationals, Specially Designated Terrorists, and Specially Designated Narcotic Traffickers, nor listed on the United States Department of Commerce Table of Denial Orders or any other U.S. government list of prohibited or restricted parties and f) You will not download or otherwise export or re-export the Software, directly or indirectly, to persons on the above-mentioned lists.

- -

10 Data Protection

- -

SAP and You must comply with the provisions of the law of data protection. Where SAP is granted access (for example, for remote maintenance) to hardware and software that You use, it is not the intention that SAP process or use personal data for business purposes. Rather, transfer of personal data will only take place in exceptional circumstances, as an incidental effect of SAP’s performing its contractual duties. If in the course of contract maintenance SAP stores, processes, or uses personal data, it will comply with Your instructions in that respect. Additional remuneration is payable by You to the extent such instructions require goods, works, or services not included in the contract. SAP and You must implement the technical and organizational measures required by the German Federal Data Protection Act, section 9 and the schedule thereto, to protect personal data from misuse. SAP will deploy on work involving the processing of personal data only personnel bound to data secrecy in the meaning of the German Federal Data Protection Act, section 5. SAP will bind to the applicable provisions of the law of data protection any subcontractor with access to personal data. If the subcontractor is not domiciled in the European Union (EU), SAP will take steps to achieve a level of data protection that is appropriate in accordance with EU data protection requirements. You must ensure that all legal requirements on your part are met so that SAP can perform its contractual services without infringing the law. You acknowledge and agree that any of Your personal information will at all times be processed by SAP in accordance with its Privacy Policy (http://www.sap.com/corporate-en/our-company/legal/privacy.epx).

- -

11 Support

- -

SAP does not offer support for the Software other than – at its sole discretion - provision of updates, patches, bug fixes and new versions.

- -

12 Term and Termination

- -

You may terminate this Agreement by destroying all copies of the Software on Your Apple mobile device. SAP shall be entitled to terminate Your license to use the Software if You fail to comply with any of the terms of this Agreement. This Agreement terminates automatically upon termination or expiration of the SAP Standard Software agreement between You or Your employer and either the respective SAP entity or the authorized SAP reselling partner. In case of termination or expiration of this Agreement, You must destroy all copies of the Software on Your Apple mobile device.

- -

13 Law/Venue

- -

German law applies exclusively to all claims in contract, in tort or otherwise, and the UN sales laws convention is excluded. If You are a merchant within the meaning of the German Commercial Code (HGB), section 1, or a public-law juristic person or special fund, the sole place of jurisdiction for all differences arising out of or in connection with the Software Agreement shall be Karlsruhe.

- -

14 Third Party Product License Terms

- -

14.1 Google Maps Service ("GM Service"). In case the Software accesses the GM Service through a Google Maps API, Your use of the GM Service is subject to Google’s Terms of Use which are set forth on: http://www.google.com/intl/en_ALL/help/terms_maps.html. If You do not accept such Google Terms of Use, including, but not limited to all limitations and restrictions therein, You may not use the GM Service in the Software. You acknowledge and agree that use of the GM Service in or through the Software will constitute Your acceptance of Google´s Terms of Use. Company’s usage of GM Service within the Software can be terminated by SAP without stating any reason at any time. In that case SAP is not required to provide an equivalent service via another provider. Company is not entitled to seek any damages thereof. -14.2 Bing Maps Service ("BM Service"). In case the Software accesses the BM Service through a Bing Maps API, Company’s use of the BM Service is subject to Microsoft’s Terms of Use which are set forth on: http://www.microsoft.com/maps/assets/docs/terms.aspx#l1. If Company does not accept such Microsoft Terms of Use, including, but not limited to all limitations and restrictions therein, you or Company may not use the BM Service in the Software. Company acknowledges and agrees that use of the BM Service in or through the Software will constitute Company’s acceptance of Microsoft’s Terms of Use. Company’s usage of BM Service within the Software can be terminated by SAP without stating any reason at any time. In that case SAP is not required to provide an equivalent service via another provider. Company is not entitled to seek any damages thereof.

- -

15 Miscellaneous

- -

This Agreement is the complete Agreement for the Software licensed (including reference to information/documentation contained in a URL). This Agreement supersedes all prior or contemporaneous agreements or representations with regards to the subject matter of this Agreement. If any term of this Agreement is found to be invalid or unenforceable, the surviving provisions shall remain effective. SAP´s failure to enforce any right or provisions stipulated in this Agreement will not constitute a waiver of such provision, or any other provision of this Agreement. -You and SAP agree that: (a) this Agreement is between SAP and You, and that Apple is not a party to this Agreement; (b) that SAP is solely responsible for the Software and the content thereof; (c) that Apple, and Apple's subsidiaries, are third party beneficiaries of this Agreement, and d) Apple will have the right (and will be deemed to have accepted the right) to enforce this Agreement against You as a third party beneficiary hereof, but only if You accept the terms of this Agreement as outlined above.

- -

16 Contact

- -

If you have any questions or support-issues with regards to the Software please refer to our help portal: http://service.sap.com.

- - - diff --git a/ios/SAPTracker/src/xcode/SAPTrackerTests/SAPTrackerAPITests.swift b/ios/SAPTracker/src/xcode/SAPTrackerTests/SAPTrackerAPITests.swift index a861b0cac44..176223853f3 100644 --- a/ios/SAPTracker/src/xcode/SAPTrackerTests/SAPTrackerAPITests.swift +++ b/ios/SAPTracker/src/xcode/SAPTrackerTests/SAPTrackerAPITests.swift @@ -17,42 +17,42 @@ class SAPTrackerAPITests: XCTestCase { override func setUp() { // TODO: point to real server - APIManager.sharedManager.initManager("http://95.85.58.11:8000/") + // APIManager.sharedManager.initManager("http://95.85.58.11:8000/") } // MARK: - Event - func testParseEvent() { - // read JSON from resources - let data = NSData(contentsOfURL: bundle.URLForResource("event1", withExtension: "json")!) - do { - let dictionary = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers) as! [String: AnyObject] - - // check values - checkEventDictionary(dictionary) - } catch { - print(error) - } - } +// func testParseEvent() { +// // read JSON from resources +// let data = NSData(contentsOfURL: bundle.URLForResource("event1", withExtension: "json")!) +// do { +// let dictionary = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers) as! [String: AnyObject] +// +// // check values +// checkEventDictionary(dictionary) +// } catch { +// print(error) +// } +// } - func testGetEvent() { - let expectation = expectationWithDescription("get event from server") - - // get JSON from server - APIManager.sharedManager.getEvent("35dc9389-b59d-4ebd-8f6b-432065642f40", - success: { (AFHTTPRequestOperation operation, AnyObject eventResponseObject) -> Void in - // check values - self.checkEventDictionary(eventResponseObject as! [String: AnyObject]) - expectation.fulfill() - }, - failure: { (AFHTTPRequestOperation operation, NSError error) -> Void in - XCTFail("server error \(error)") - expectation.fulfill() - } - ); - - waitForExpectationsWithTimeout(1, handler: nil) - } +// func testGetEvent() { +// let expectation = expectationWithDescription("get event from server") +// +// // get JSON from server +// APIManager.sharedManager.getEvent("35dc9389-b59d-4ebd-8f6b-432065642f40", +// success: { (AFHTTPRequestOperation operation, AnyObject eventResponseObject) -> Void in +// // check values +// self.checkEventDictionary(eventResponseObject as! [String: AnyObject]) +// expectation.fulfill() +// }, +// failure: { (AFHTTPRequestOperation operation, NSError error) -> Void in +// XCTFail("server error \(error)") +// expectation.fulfill() +// } +// ); +// +// waitForExpectationsWithTimeout(1, handler: nil) +// } /* { @@ -87,59 +87,60 @@ class SAPTrackerAPITests: XCTestCase { }] } */ - func checkEventDictionary(dictionary: [String: AnyObject]) { - // http://stackoverflow.com/a/26444319 - let entity = NSEntityDescription.entityForName("Event", inManagedObjectContext: DataManager.sharedManager.managedObjectContext!) - - // create (temporary) event object - var event = Event(entity: entity!, insertIntoManagedObjectContext: DataManager.sharedManager.managedObjectContext!) - - // read dictionary into object - event.initWithDictionary(dictionary) - - // test values - XCTAssertEqual(event.eventId, "35dc9389-b59d-4ebd-8f6b-432065642f40") - XCTAssertEqual(event.name, "505 Worlds 2013") - XCTAssertEqual(event.startDate, NSDate(timeIntervalSince1970: 1429653600)) - XCTAssertEqual(event.endDate, NSDate(timeIntervalSince1970: 1430604000)) - - // delete test object - DataManager.sharedManager.managedObjectContext!.deleteObject(event) - } + +// func checkEventDictionary(dictionary: [String: AnyObject]) { +// // http://stackoverflow.com/a/26444319 +// let entity = NSEntityDescription.entityForName("Event", inManagedObjectContext: DataManager.sharedManager.managedObjectContext!) +// +// // create (temporary) event object +// var event = Event(entity: entity!, insertIntoManagedObjectContext: DataManager.sharedManager.managedObjectContext!) +// +// // read dictionary into object +// event.initWithDictionary(dictionary) +// +// // test values +// XCTAssertEqual(event.eventId, "35dc9389-b59d-4ebd-8f6b-432065642f40") +// XCTAssertEqual(event.name, "505 Worlds 2013") +// XCTAssertEqual(event.startDate, NSDate(timeIntervalSince1970: 1429653600)) +// XCTAssertEqual(event.endDate, NSDate(timeIntervalSince1970: 1430604000)) +// +// // delete test object +// DataManager.sharedManager.managedObjectContext!.deleteObject(event) +// } // MARK: - Leader Board - func testParseLeaderBoard() { - // read JSON from resources - let data = NSData(contentsOfURL: bundle.URLForResource("leaderboard1", withExtension: "json")!) - do { - let dictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! [String: AnyObject] - - // check values - checkLeaderBoardDictionary(dictionary) - } catch { - print(error) - } - } +// func testParseLeaderBoard() { +// // read JSON from resources +// let data = NSData(contentsOfURL: bundle.URLForResource("leaderboard1", withExtension: "json")!) +// do { +// let dictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! [String: AnyObject] +// +// // check values +// checkLeaderBoardDictionary(dictionary) +// } catch { +// print(error) +// } +// } - func testGetLeaderBoard() { - let expectation = expectationWithDescription("get leader board from server") - - // get JSON from server - APIManager.sharedManager.getLeaderBoard("505%20Worlds%202013", - success: { (AFHTTPRequestOperation operation, AnyObject eventResponseObject) -> Void in - // check values - self.checkLeaderBoardDictionary(eventResponseObject as! [String: AnyObject]) - expectation.fulfill() - }, - failure: { (AFHTTPRequestOperation operation, NSError error) -> Void in - XCTFail("server error \(error)") - expectation.fulfill() - } - ); - - waitForExpectationsWithTimeout(1, handler: nil) - } +// func testGetLeaderBoard() { +// let expectation = expectationWithDescription("get leader board from server") +// +// // get JSON from server +// APIManager.sharedManager.getLeaderBoard("505%20Worlds%202013", +// success: { (AFHTTPRequestOperation operation, AnyObject eventResponseObject) -> Void in +// // check values +// self.checkLeaderBoardDictionary(eventResponseObject as! [String: AnyObject]) +// expectation.fulfill() +// }, +// failure: { (AFHTTPRequestOperation operation, NSError error) -> Void in +// XCTFail("server error \(error)") +// expectation.fulfill() +// } +// ); +// +// waitForExpectationsWithTimeout(1, handler: nil) +// } /* { @@ -155,56 +156,57 @@ class SAPTrackerAPITests: XCTestCase { ... ] */ - func checkLeaderBoardDictionary(dictionary: [String: AnyObject]) { - // http://stackoverflow.com/a/26444319 - let entity = NSEntityDescription.entityForName("LeaderBoard", inManagedObjectContext: DataManager.sharedManager.managedObjectContext!) - - // create (temporary) event object - var leaderBoard = LeaderBoard(entity: entity!, insertIntoManagedObjectContext: DataManager.sharedManager.managedObjectContext!) - - // read dictionary into object - leaderBoard.initWithDictionary(dictionary) - - // test values - XCTAssertEqual(leaderBoard.name, "505 Worlds 2013") - - // delete test object - DataManager.sharedManager.managedObjectContext!.deleteObject(leaderBoard) - } + +// func checkLeaderBoardDictionary(dictionary: [String: AnyObject]) { +// // http://stackoverflow.com/a/26444319 +// let entity = NSEntityDescription.entityForName("LeaderBoard", inManagedObjectContext: DataManager.sharedManager.managedObjectContext!) +// +// // create (temporary) event object +// var leaderBoard = LeaderBoard(entity: entity!, insertIntoManagedObjectContext: DataManager.sharedManager.managedObjectContext!) +// +// // read dictionary into object +// leaderBoard.initWithDictionary(dictionary) +// +// // test values +// XCTAssertEqual(leaderBoard.name, "505 Worlds 2013") +// +// // delete test object +// DataManager.sharedManager.managedObjectContext!.deleteObject(leaderBoard) +// } // MARK: - Competitor - func testParseCompetitor() { - // read JSON from resources - let data = NSData(contentsOfURL: bundle.URLForResource("competitor1", withExtension: "json")!) - do { - let dictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! [String: AnyObject] - - // check values - checkCompetitorDictionary(dictionary) - } catch { - print(error) - } - } +// func testParseCompetitor() { +// // read JSON from resources +// let data = NSData(contentsOfURL: bundle.URLForResource("competitor1", withExtension: "json")!) +// do { +// let dictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! [String: AnyObject] +// +// // check values +// checkCompetitorDictionary(dictionary) +// } catch { +// print(error) +// } +// } - func testGetCompetitor() { - let expectation = expectationWithDescription("get competitor from server") - - // get JSON from server - APIManager.sharedManager.getCompetitor("1d028378-e12c-a6bd-afa3-b8b21bc5a9ea", - success: { (AFHTTPRequestOperation operation, AnyObject eventResponseObject) -> Void in - // check values - self.checkCompetitorDictionary(eventResponseObject as! [String: AnyObject]) - expectation.fulfill() - }, - failure: { (AFHTTPRequestOperation operation, NSError error) -> Void in - XCTFail("server error \(error)") - expectation.fulfill() - } - ); - - waitForExpectationsWithTimeout(1, handler: nil) - } +// func testGetCompetitor() { +// let expectation = expectationWithDescription("get competitor from server") +// +// // get JSON from server +// APIManager.sharedManager.getCompetitor("1d028378-e12c-a6bd-afa3-b8b21bc5a9ea", +// success: { (AFHTTPRequestOperation operation, AnyObject eventResponseObject) -> Void in +// // check values +// self.checkCompetitorDictionary(eventResponseObject as! [String: AnyObject]) +// expectation.fulfill() +// }, +// failure: { (AFHTTPRequestOperation operation, NSError error) -> Void in +// XCTFail("server error \(error)") +// expectation.fulfill() +// } +// ); +// +// waitForExpectationsWithTimeout(1, handler: nil) +// } /* { @@ -216,31 +218,32 @@ class SAPTrackerAPITests: XCTestCase { "boatClassName": "49er" } */ - func checkCompetitorDictionary(dictionary: [String: AnyObject]) { - // http://stackoverflow.com/a/26444319 - let entity = NSEntityDescription.entityForName("Competitor", inManagedObjectContext: DataManager.sharedManager.managedObjectContext!) - - // create (temporary) event object - let competitor = Competitor(entity: entity!, insertIntoManagedObjectContext: DataManager.sharedManager.managedObjectContext!) - - // read dictionary into object - competitor.initWithDictionary(dictionary) - - // test values - XCTAssertEqual(competitor.name, "Lukas ZIELINSKI") - XCTAssertEqual(competitor.competitorId, "1d028378-e12c-a6bd-afa3-b8b21bc5a9ea") - XCTAssertEqual(competitor.sailId, "LUK 1") - XCTAssertEqual(competitor.nationality, "GER") - XCTAssertEqual(competitor.countryCode, "DE") - - // delete test object - DataManager.sharedManager.managedObjectContext!.deleteObject(competitor) - } - func testParseUrl() { - let url = "comsapsailingtracker://95.85.58.11:8000?event_id=35dc9389-b59d-4ebd-8f6b-432065642f40&leaderboard_name=505%20Worlds%202013&competitor_id=92d06f15-1d61-fc2d-4e64-dae37577d3d2" - let qrcodeData = QRCodeData() - XCTAssertTrue(qrcodeData.parseString(url), "cannot parse QR code URL "+url) - } +// func checkCompetitorDictionary(dictionary: [String: AnyObject]) { +// // http://stackoverflow.com/a/26444319 +// let entity = NSEntityDescription.entityForName("Competitor", inManagedObjectContext: DataManager.sharedManager.managedObjectContext!) +// +// // create (temporary) event object +// let competitor = Competitor(entity: entity!, insertIntoManagedObjectContext: DataManager.sharedManager.managedObjectContext!) +// +// // read dictionary into object +// competitor.initWithDictionary(dictionary) +// +// // test values +// XCTAssertEqual(competitor.name, "Lukas ZIELINSKI") +// XCTAssertEqual(competitor.competitorId, "1d028378-e12c-a6bd-afa3-b8b21bc5a9ea") +// XCTAssertEqual(competitor.sailId, "LUK 1") +// XCTAssertEqual(competitor.nationality, "GER") +// XCTAssertEqual(competitor.countryCode, "DE") +// +// // delete test object +// DataManager.sharedManager.managedObjectContext!.deleteObject(competitor) +// } + +// func testParseUrl() { +// let url = "comsapsailingtracker://95.85.58.11:8000?event_id=35dc9389-b59d-4ebd-8f6b-432065642f40&leaderboard_name=505%20Worlds%202013&competitor_id=92d06f15-1d61-fc2d-4e64-dae37577d3d2" +// let qrcodeData = QRCodeData() +// XCTAssertTrue(qrcodeData.parseString(url), "cannot parse QR code URL "+url) +// } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/NonGwtUrlHelperTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/NonGwtUrlHelperTest.java index 8ca6a8f896d..07217faae00 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/NonGwtUrlHelperTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/NonGwtUrlHelperTest.java @@ -18,7 +18,7 @@ public class NonGwtUrlHelperTest { @Test public void testEncodeQueryStringWithWhitespace() { - testCase("Test%20Test", "Test Test"); + testCase("Test+Test", "Test Test"); } @Test @@ -38,7 +38,7 @@ public class NonGwtUrlHelperTest { @Test public void testEncodeQueryStringComplex() { - testCase("Test%20%2B%20Test%20%2F%20Test%20%26%20Test", "Test + Test / Test & Test"); + testCase("Test+%2B+Test+%2F+Test+%26+Test", "Test + Test / Test & Test"); } private void testCase(String expectedEncodedString, String decodedString) { diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/client/GwtUrlHelperTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/client/GwtUrlHelperTest.java index 5cd97cb9bc7..fbc1ec96195 100644 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/client/GwtUrlHelperTest.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/client/GwtUrlHelperTest.java @@ -16,7 +16,7 @@ public class GwtUrlHelperTest extends GWTTestCase { @Test public void testEncodeQueryStringWithWhitespace() { - testCase("Test%20Test", "Test Test"); + testCase("Test+Test", "Test Test"); } @Test @@ -36,7 +36,7 @@ public class GwtUrlHelperTest extends GWTTestCase { @Test public void testEncodeQueryStringComplex() { - testCase("Test%20%2B%20Test%20%2F%20Test%20%26%20Test", "Test + Test / Test & Test"); + testCase("Test+%2B+Test+%2F+Test+%26+Test", "Test + Test / Test & Test"); } private void testCase(String expectedEncodedString, String decodedString) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/GwtUrlHelper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/GwtUrlHelper.java index 249bf6eeb76..976f141a857 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/GwtUrlHelper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/GwtUrlHelper.java @@ -16,13 +16,7 @@ public enum GwtUrlHelper implements UrlHelper { @Override public String encodeQueryString(String queryString) { - // TODO See bug3664 => https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=3664 - // Because of changes in the query string encoding, the Sail InSight-App for iOS will now have problems - // while parsing the registration URLs, which are sent to invited competitors, if e.g. the leaderboard name - // contains whitespaces. To avoid this problems, we use this temporary fix until a new version of the Sail - // InSight-App for iOS is rolled out. Afterwards this fix must be replaced by the line below. - return URL.encodePathSegment(queryString); - // return URL.encodeQueryString(queryString); + return URL.encodeQueryString(queryString); } } diff --git a/java/com.sap.sse.shared.android/src/com/sap/sse/util/impl/NonGwtUrlHelper.java b/java/com.sap.sse.shared.android/src/com/sap/sse/util/impl/NonGwtUrlHelper.java index 10a9f5f5d95..76b6eb33d7a 100644 --- a/java/com.sap.sse.shared.android/src/com/sap/sse/util/impl/NonGwtUrlHelper.java +++ b/java/com.sap.sse.shared.android/src/com/sap/sse/util/impl/NonGwtUrlHelper.java @@ -15,13 +15,7 @@ public enum NonGwtUrlHelper implements UrlHelper { @Override public String encodeQueryString(String queryString) { try { - // TODO See bug3664 => https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=3664 - // Because of changes in the query string encoding, the Sail InSight-App for iOS will now have problems - // while parsing the registration URLs, which are sent to invited competitors, if e.g. the leaderboard name - // contains whitespaces. To avoid this problems, we use this temporary fix until a new version of the Sail - // InSight-App for iOS is rolled out. Afterwards this fix must be replaced by the line below. - return URLEncoder.encode(queryString, "UTF-8").replace("+", "%20"); - // return URLEncoder.encode(queryString, "UTF-8"); + return URLEncoder.encode(queryString, "UTF-8"); } catch (UnsupportedEncodingException e) { logger.log(Level.WARNING, "problem encoding URL query string "+queryString, e); return null;