commit 0971c33d175c5519b84eff938eaad7fdbf6b3bb1 Author: Archer.wen Date: Mon Nov 16 14:49:03 2020 +0800 no message diff --git a/Podfile b/Podfile new file mode 100644 index 0000000..c41da8c --- /dev/null +++ b/Podfile @@ -0,0 +1,13 @@ +# Uncomment the next line to define a global platform for your project +# platform :ios, '9.0' + +target 'goodpk' do + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + + # Pods for goodpk + + pod 'JSONModel' + pod 'CocoaSecurity' + +end diff --git a/Podfile.lock b/Podfile.lock new file mode 100644 index 0000000..eb9f0e5 --- /dev/null +++ b/Podfile.lock @@ -0,0 +1,20 @@ +PODS: + - CocoaSecurity (1.2.4) + - JSONModel (1.8.0) + +DEPENDENCIES: + - CocoaSecurity + - JSONModel + +SPEC REPOS: + trunk: + - CocoaSecurity + - JSONModel + +SPEC CHECKSUMS: + CocoaSecurity: d288a6f87e0f363823d2cb83e753814a6944f71a + JSONModel: 02ab723958366a3fd27da57ea2af2113658762e9 + +PODFILE CHECKSUM: 8f0d15fb3bf327bd25b9de3dee5d9d3d90351b9b + +COCOAPODS: 1.8.4 diff --git a/Pods/CocoaSecurity/CocoaSecurity/CocoaSecurity.h b/Pods/CocoaSecurity/CocoaSecurity/CocoaSecurity.h new file mode 100644 index 0000000..e574fbd --- /dev/null +++ b/Pods/CocoaSecurity/CocoaSecurity/CocoaSecurity.h @@ -0,0 +1,85 @@ +/* + CocoaSecurity 1.1 + + Created by Kelp on 12/5/12. + Copyright (c) 2012 Kelp http://kelp.phate.org/ + MIT License + + CocoaSecurity is core. It provides AES encrypt, AES decrypt, Hash(MD5, HmacMD5, SHA1~SHA512, HmacSHA1~HmacSHA512) messages. +*/ + +#import +#import + + +#pragma mark - CocoaSecurityResult +@interface CocoaSecurityResult : NSObject + +@property (strong, nonatomic, readonly) NSData *data; +@property (strong, nonatomic, readonly) NSString *utf8String; +@property (strong, nonatomic, readonly) NSString *hex; +@property (strong, nonatomic, readonly) NSString *hexLower; +@property (strong, nonatomic, readonly) NSString *base64; + +- (id)initWithBytes:(unsigned char[])initData length:(NSUInteger)length; + +@end + + +#pragma mark - CocoaSecurity +@interface CocoaSecurity : NSObject +#pragma mark - AES Encrypt ++ (CocoaSecurityResult *)aesEncrypt:(NSString *)data key:(NSString *)key; ++ (CocoaSecurityResult *)aesEncrypt:(NSString *)data hexKey:(NSString *)key hexIv:(NSString *)iv; ++ (CocoaSecurityResult *)aesEncrypt:(NSString *)data key:(NSData *)key iv:(NSData *)iv; ++ (CocoaSecurityResult *)aesEncryptWithData:(NSData *)data key:(NSData *)key iv:(NSData *)iv; +#pragma mark AES Decrypt ++ (CocoaSecurityResult *)aesDecryptWithBase64:(NSString *)data key:(NSString *)key; ++ (CocoaSecurityResult *)aesDecryptWithBase64:(NSString *)data hexKey:(NSString *)key hexIv:(NSString *)iv; ++ (CocoaSecurityResult *)aesDecryptWithBase64:(NSString *)data key:(NSData *)key iv:(NSData *)iv; ++ (CocoaSecurityResult *)aesDecryptWithData:(NSData *)data key:(NSData *)key iv:(NSData *)iv; + +#pragma mark - MD5 ++ (CocoaSecurityResult *)md5:(NSString *)hashString; ++ (CocoaSecurityResult *)md5WithData:(NSData *)hashData; +#pragma mark HMAC-MD5 ++ (CocoaSecurityResult *)hmacMd5:(NSString *)hashString hmacKey:(NSString *)key; ++ (CocoaSecurityResult *)hmacMd5WithData:(NSData *)hashData hmacKey:(NSString *)key; + +#pragma mark - SHA ++ (CocoaSecurityResult *)sha1:(NSString *)hashString; ++ (CocoaSecurityResult *)sha1WithData:(NSData *)hashData; ++ (CocoaSecurityResult *)sha224:(NSString *)hashString; ++ (CocoaSecurityResult *)sha224WithData:(NSData *)hashData; ++ (CocoaSecurityResult *)sha256:(NSString *)hashString; ++ (CocoaSecurityResult *)sha256WithData:(NSData *)hashData; ++ (CocoaSecurityResult *)sha384:(NSString *)hashString; ++ (CocoaSecurityResult *)sha384WithData:(NSData *)hashData; ++ (CocoaSecurityResult *)sha512:(NSString *)hashString; ++ (CocoaSecurityResult *)sha512WithData:(NSData *)hashData; +#pragma mark HMAC-SHA ++ (CocoaSecurityResult *)hmacSha1:(NSString *)hashString hmacKey:(NSString *)key; ++ (CocoaSecurityResult *)hmacSha1WithData:(NSData *)hashData hmacKey:(NSString *)key; ++ (CocoaSecurityResult *)hmacSha224:(NSString *)hashString hmacKey:(NSString *)key; ++ (CocoaSecurityResult *)hmacSha224WithData:(NSData *)hashData hmacKey:(NSString *)key; ++ (CocoaSecurityResult *)hmacSha256:(NSString *)hashString hmacKey:(NSString *)key; ++ (CocoaSecurityResult *)hmacSha256WithData:(NSData *)hashData hmacKey:(NSString *)key; ++ (CocoaSecurityResult *)hmacSha384:(NSString *)hashString hmacKey:(NSString *)key; ++ (CocoaSecurityResult *)hmacSha384WithData:(NSData *)hashData hmacKey:(NSString *)key; ++ (CocoaSecurityResult *)hmacSha512:(NSString *)hashString hmacKey:(NSString *)key; ++ (CocoaSecurityResult *)hmacSha512WithData:(NSData *)hashData hmacKey:(NSString *)key; +@end + + +#pragma mark - CocoaSecurityEncoder +@interface CocoaSecurityEncoder : NSObject +- (NSString *)base64:(NSData *)data; +- (NSString *)hex:(NSData *)data useLower:(BOOL)isOutputLower; +@end + + +#pragma mark - CocoaSecurityDecoder +@interface CocoaSecurityDecoder : NSObject +- (NSData *)base64:(NSString *)data; +- (NSData *)hex:(NSString *)data; +@end diff --git a/Pods/CocoaSecurity/CocoaSecurity/CocoaSecurity.m b/Pods/CocoaSecurity/CocoaSecurity/CocoaSecurity.m new file mode 100644 index 0000000..b519285 --- /dev/null +++ b/Pods/CocoaSecurity/CocoaSecurity/CocoaSecurity.m @@ -0,0 +1,508 @@ +// +// CocoaSecurity.m +// +// Created by Kelp on 12/5/12. +// Copyright (c) 2012 Kelp http://kelp.phate.org/ +// MIT License +// + +#import "CocoaSecurity.h" +#import +#import +#import "Base64.h" + +#pragma mark - CocoaSecurity +@implementation CocoaSecurity + + +#pragma mark - AES Encrypt +// default AES Encrypt, key -> SHA384(key).sub(0, 32), iv -> SHA384(key).sub(32, 16) ++ (CocoaSecurityResult *)aesEncrypt:(NSString *)data key:(NSString *)key +{ + CocoaSecurityResult * sha = [self sha384:key]; + NSData *aesKey = [sha.data subdataWithRange:NSMakeRange(0, 32)]; + NSData *aesIv = [sha.data subdataWithRange:NSMakeRange(32, 16)]; + + return [self aesEncrypt:data key:aesKey iv:aesIv]; +} +#pragma mark AES Encrypt 128, 192, 256 ++ (CocoaSecurityResult *)aesEncrypt:(NSString *)data hexKey:(NSString *)key hexIv:(NSString *)iv +{ + CocoaSecurityDecoder *decoder = [CocoaSecurityDecoder new]; + NSData *aesKey = [decoder hex:key]; + NSData *aesIv = [decoder hex:iv]; + + return [self aesEncrypt:data key:aesKey iv:aesIv]; +} ++ (CocoaSecurityResult *)aesEncrypt:(NSString *)data key:(NSData *)key iv:(NSData *)iv +{ + return [self aesEncryptWithData:[data dataUsingEncoding:NSUTF8StringEncoding] key:key iv:iv]; +} ++ (CocoaSecurityResult *)aesEncryptWithData:(NSData *)data key:(NSData *)key iv:(NSData *)iv +{ + // check length of key and iv + if ([iv length] != 16) { + @throw [NSException exceptionWithName:@"Cocoa Security" + reason:@"Length of iv is wrong. Length of iv should be 16(128bits)" + userInfo:nil]; + } + if ([key length] != 16 && [key length] != 24 && [key length] != 32 ) { + @throw [NSException exceptionWithName:@"Cocoa Security" + reason:@"Length of key is wrong. Length of iv should be 16, 24 or 32(128, 192 or 256bits)" + userInfo:nil]; + } + + // setup output buffer + size_t bufferSize = [data length] + kCCBlockSizeAES128; + void *buffer = malloc(bufferSize); + + // do encrypt + size_t encryptedSize = 0; + CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, + kCCAlgorithmAES128, + kCCOptionPKCS7Padding, + [key bytes], // Key + [key length], // kCCKeySizeAES + [iv bytes], // IV + [data bytes], + [data length], + buffer, + bufferSize, + &encryptedSize); + if (cryptStatus == kCCSuccess) { + CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:buffer length:encryptedSize]; + free(buffer); + + return result; + } + else { + free(buffer); + @throw [NSException exceptionWithName:@"Cocoa Security" + reason:@"Encrypt Error!" + userInfo:nil]; + return nil; + } +} +#pragma mark - AES Decrypt +// default AES Decrypt, key -> SHA384(key).sub(0, 32), iv -> SHA384(key).sub(32, 16) ++ (CocoaSecurityResult *)aesDecryptWithBase64:(NSString *)data key:(NSString *)key +{ + CocoaSecurityResult * sha = [self sha384:key]; + NSData *aesKey = [sha.data subdataWithRange:NSMakeRange(0, 32)]; + NSData *aesIv = [sha.data subdataWithRange:NSMakeRange(32, 16)]; + + return [self aesDecryptWithBase64:data key:aesKey iv:aesIv]; +} +#pragma mark AES Decrypt 128, 192, 256 ++ (CocoaSecurityResult *)aesDecryptWithBase64:(NSString *)data hexKey:(NSString *)key hexIv:(NSString *)iv +{ + CocoaSecurityDecoder *decoder = [CocoaSecurityDecoder new]; + NSData *aesKey = [decoder hex:key]; + NSData *aesIv = [decoder hex:iv]; + + return [self aesDecryptWithBase64:data key:aesKey iv:aesIv]; +} ++ (CocoaSecurityResult *)aesDecryptWithBase64:(NSString *)data key:(NSData *)key iv:(NSData *)iv +{ + CocoaSecurityDecoder *decoder = [CocoaSecurityDecoder new]; + return [self aesDecryptWithData:[decoder base64:data] key:key iv:iv]; +} ++ (CocoaSecurityResult *)aesDecryptWithData:(NSData *)data key:(NSData *)key iv:(NSData *)iv +{ + // check length of key and iv + if ([iv length] != 16) { + @throw [NSException exceptionWithName:@"Cocoa Security" + reason:@"Length of iv is wrong. Length of iv should be 16(128bits)" + userInfo:nil]; + } + if ([key length] != 16 && [key length] != 24 && [key length] != 32 ) { + @throw [NSException exceptionWithName:@"Cocoa Security" + reason:@"Length of key is wrong. Length of iv should be 16, 24 or 32(128, 192 or 256bits)" + userInfo:nil]; + } + + // setup output buffer + size_t bufferSize = [data length] + kCCBlockSizeAES128; + void *buffer = malloc(bufferSize); + + // do encrypt + size_t encryptedSize = 0; + CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, + kCCAlgorithmAES128, + kCCOptionPKCS7Padding, + [key bytes], // Key + [key length], // kCCKeySizeAES + [iv bytes], // IV + [data bytes], + [data length], + buffer, + bufferSize, + &encryptedSize); + if (cryptStatus == kCCSuccess) { + CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:buffer length:encryptedSize]; + free(buffer); + + return result; + } + else { + free(buffer); + @throw [NSException exceptionWithName:@"Cocoa Security" + reason:@"Decrypt Error!" + userInfo:nil]; + return nil; + } +} + + +#pragma mark - MD5 ++ (CocoaSecurityResult *)md5:(NSString *)hashString +{ + return [self md5WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding]]; +} ++ (CocoaSecurityResult *)md5WithData:(NSData *)hashData +{ + unsigned char *digest; + digest = malloc(CC_MD5_DIGEST_LENGTH); + + CC_MD5([hashData bytes], (CC_LONG)[hashData length], digest); + CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_MD5_DIGEST_LENGTH]; + free(digest); + + return result; +} +#pragma mark - HMAC-MD5 ++ (CocoaSecurityResult *)hmacMd5:(NSString *)hashString hmacKey:(NSString *)key +{ + return [self hmacMd5WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding] hmacKey:key]; +} ++ (CocoaSecurityResult *)hmacMd5WithData:(NSData *)hashData hmacKey:(NSString *)key +{ + unsigned char *digest; + digest = malloc(CC_MD5_DIGEST_LENGTH); + const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding]; + + CCHmac(kCCHmacAlgMD5, cKey, strlen(cKey), [hashData bytes], [hashData length], digest); + CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_MD5_DIGEST_LENGTH]; + free(digest); + cKey = nil; + + return result; +} + + +#pragma mark - SHA1 ++ (CocoaSecurityResult *)sha1:(NSString *)hashString +{ + return [self sha1WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding]]; +} ++ (CocoaSecurityResult *)sha1WithData:(NSData *)hashData +{ + unsigned char *digest; + digest = malloc(CC_SHA1_DIGEST_LENGTH); + + CC_SHA1([hashData bytes], (CC_LONG)[hashData length], digest); + CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA1_DIGEST_LENGTH]; + free(digest); + + return result; +} +#pragma mark SHA224 ++ (CocoaSecurityResult *)sha224:(NSString *)hashString +{ + return [self sha224WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding]]; +} ++ (CocoaSecurityResult *)sha224WithData:(NSData *)hashData +{ + unsigned char *digest; + digest = malloc(CC_SHA224_DIGEST_LENGTH); + + CC_SHA224([hashData bytes], (CC_LONG)[hashData length], digest); + CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA224_DIGEST_LENGTH]; + free(digest); + + return result; +} +#pragma mark SHA256 ++ (CocoaSecurityResult *)sha256:(NSString *)hashString +{ + return [self sha256WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding]]; +} ++ (CocoaSecurityResult *)sha256WithData:(NSData *)hashData +{ + unsigned char *digest; + digest = malloc(CC_SHA256_DIGEST_LENGTH); + + CC_SHA256([hashData bytes], (CC_LONG)[hashData length], digest); + CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA256_DIGEST_LENGTH]; + free(digest); + + return result; +} +#pragma mark SHA384 ++ (CocoaSecurityResult *)sha384:(NSString *)hashString +{ + return [self sha384WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding]]; +} ++ (CocoaSecurityResult *)sha384WithData:(NSData *)hashData +{ + unsigned char *digest; + digest = malloc(CC_SHA384_DIGEST_LENGTH); + + CC_SHA384([hashData bytes], (CC_LONG)[hashData length], digest); + CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA384_DIGEST_LENGTH]; + free(digest); + + return result; +} +#pragma mark SHA512 ++ (CocoaSecurityResult *)sha512:(NSString *)hashString +{ + return [self sha512WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding]]; +} ++ (CocoaSecurityResult *)sha512WithData:(NSData *)hashData +{ + unsigned char *digest; + digest = malloc(CC_SHA512_DIGEST_LENGTH); + + CC_SHA512([hashData bytes], (CC_LONG)[hashData length], digest); + CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA512_DIGEST_LENGTH]; + free(digest); + + return result; +} + + +#pragma mark - HMAC-SHA1 ++ (CocoaSecurityResult *)hmacSha1:(NSString *)hashString hmacKey:(NSString *)key +{ + return [self hmacSha1WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding] hmacKey:key]; +} ++ (CocoaSecurityResult *)hmacSha1WithData:(NSData *)hashData hmacKey:(NSString *)key +{ + unsigned char *digest; + digest = malloc(CC_SHA1_DIGEST_LENGTH); + const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding]; + + CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), [hashData bytes], [hashData length], digest); + CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA1_DIGEST_LENGTH]; + free(digest); + cKey = nil; + + return result; +} +#pragma mark HMAC-SHA224 ++ (CocoaSecurityResult *)hmacSha224:(NSString *)hashString hmacKey:(NSString *)key +{ + return [self hmacSha224WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding] hmacKey:key]; +} ++ (CocoaSecurityResult *)hmacSha224WithData:(NSData *)hashData hmacKey:(NSString *)key +{ + unsigned char *digest; + digest = malloc(CC_SHA224_DIGEST_LENGTH); + const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding]; + + CCHmac(kCCHmacAlgSHA224, cKey, strlen(cKey), [hashData bytes], [hashData length], digest); + CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA224_DIGEST_LENGTH]; + free(digest); + cKey = nil; + + return result; +} +#pragma mark HMAC-SHA256 ++ (CocoaSecurityResult *)hmacSha256:(NSString *)hashString hmacKey:(NSString *)key +{ + return [self hmacSha256WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding] hmacKey:key]; +} ++ (CocoaSecurityResult *)hmacSha256WithData:(NSData *)hashData hmacKey:(NSString *)key +{ + unsigned char *digest; + digest = malloc(CC_SHA256_DIGEST_LENGTH); + const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding]; + + CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), [hashData bytes], [hashData length], digest); + CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA256_DIGEST_LENGTH]; + free(digest); + cKey = nil; + + return result; +} +#pragma mark HMAC-SHA384 ++ (CocoaSecurityResult *)hmacSha384:(NSString *)hashString hmacKey:(NSString *)key +{ + return [self hmacSha384WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding] hmacKey:key]; +} ++ (CocoaSecurityResult *)hmacSha384WithData:(NSData *)hashData hmacKey:(NSString *)key +{ + unsigned char *digest; + digest = malloc(CC_SHA384_DIGEST_LENGTH); + const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding]; + + CCHmac(kCCHmacAlgSHA384, cKey, strlen(cKey), [hashData bytes], [hashData length], digest); + CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA384_DIGEST_LENGTH]; + free(digest); + cKey = nil; + + return result; +} +#pragma mark HMAC-SHA512 ++ (CocoaSecurityResult *)hmacSha512:(NSString *)hashString hmacKey:(NSString *)key +{ + return [self hmacSha512WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding] hmacKey:key]; +} ++ (CocoaSecurityResult *)hmacSha512WithData:(NSData *)hashData hmacKey:(NSString *)key +{ + unsigned char *digest; + digest = malloc(CC_SHA512_DIGEST_LENGTH); + const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding]; + + CCHmac(kCCHmacAlgSHA512, cKey, strlen(cKey), [hashData bytes], [hashData length], digest); + CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA512_DIGEST_LENGTH]; + free(digest); + cKey = nil; + + return result; +} + +@end + + + +#pragma mark - CocoaSecurityResult +@implementation CocoaSecurityResult + +@synthesize data = _data; + +#pragma mark - Init +- (id)initWithBytes:(unsigned char[])initData length:(NSUInteger)length +{ + self = [super init]; + if (self) { + _data = [NSData dataWithBytes:initData length:length]; + } + return self; +} + +#pragma mark UTF8 String +// convert CocoaSecurityResult to UTF8 string +- (NSString *)utf8String +{ + NSString *result = [[NSString alloc] initWithData:_data encoding:NSUTF8StringEncoding]; + return result; +} + +#pragma mark HEX +// convert CocoaSecurityResult to HEX string +- (NSString *)hex +{ + CocoaSecurityEncoder *encoder = [CocoaSecurityEncoder new]; + return [encoder hex:_data useLower:false]; +} +- (NSString *)hexLower +{ + CocoaSecurityEncoder *encoder = [CocoaSecurityEncoder new]; + return [encoder hex:_data useLower:true]; +} + +#pragma mark Base64 +// convert CocoaSecurityResult to Base64 string +- (NSString *)base64 +{ + CocoaSecurityEncoder *encoder = [CocoaSecurityEncoder new]; + return [encoder base64:_data]; +} + +@end + + +#pragma mark - CocoaSecurityEncoder +@implementation CocoaSecurityEncoder + +// convert NSData to Base64 +- (NSString *)base64:(NSData *)data +{ + return [data base64EncodedString]; +} + +// convert NSData to hex string +- (NSString *)hex:(NSData *)data useLower:(BOOL)isOutputLower +{ + if (data.length == 0) { return nil; } + + static const char HexEncodeCharsLower[] = "0123456789abcdef"; + static const char HexEncodeChars[] = "0123456789ABCDEF"; + char *resultData; + // malloc result data + resultData = malloc([data length] * 2 +1); + // convert imgData(NSData) to char[] + unsigned char *sourceData = ((unsigned char *)[data bytes]); + NSUInteger length = [data length]; + + if (isOutputLower) { + for (NSUInteger index = 0; index < length; index++) { + // set result data + resultData[index * 2] = HexEncodeCharsLower[(sourceData[index] >> 4)]; + resultData[index * 2 + 1] = HexEncodeCharsLower[(sourceData[index] % 0x10)]; + } + } + else { + for (NSUInteger index = 0; index < length; index++) { + // set result data + resultData[index * 2] = HexEncodeChars[(sourceData[index] >> 4)]; + resultData[index * 2 + 1] = HexEncodeChars[(sourceData[index] % 0x10)]; + } + } + resultData[[data length] * 2] = 0; + + // convert result(char[]) to NSString + NSString *result = [NSString stringWithCString:resultData encoding:NSASCIIStringEncoding]; + sourceData = nil; + free(resultData); + + return result; +} + +@end + +#pragma mark - CocoaSecurityDecoder +@implementation CocoaSecurityDecoder +- (NSData *)base64:(NSString *)string +{ + return [NSData dataWithBase64EncodedString:string]; +} +- (NSData *)hex:(NSString *)data +{ + if (data.length == 0) { return nil; } + + static const unsigned char HexDecodeChars[] = + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, //49 + 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, //59 + 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, + 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, //79 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, //99 + 13, 14, 15 + }; + + // convert data(NSString) to CString + const char *source = [data cStringUsingEncoding:NSUTF8StringEncoding]; + // malloc buffer + unsigned char *buffer; + NSUInteger length = strlen(source) / 2; + buffer = malloc(length); + for (NSUInteger index = 0; index < length; index++) { + buffer[index] = (HexDecodeChars[source[index * 2]] << 4) + (HexDecodeChars[source[index * 2 + 1]]); + } + // init result NSData + NSData *result = [NSData dataWithBytes:buffer length:length]; + free(buffer); + source = nil; + + return result; +} + +@end diff --git a/Pods/CocoaSecurity/LICENSE b/Pods/CocoaSecurity/LICENSE new file mode 100644 index 0000000..fcbc817 --- /dev/null +++ b/Pods/CocoaSecurity/LICENSE @@ -0,0 +1,8 @@ +The MIT License (MIT) +Copyright (c) 2013 Kelp https://github.com/kelp404 + +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/Pods/CocoaSecurity/README.md b/Pods/CocoaSecurity/README.md new file mode 100644 index 0000000..aa692a1 --- /dev/null +++ b/Pods/CocoaSecurity/README.md @@ -0,0 +1,111 @@ +#CocoaSecurity [![Build Status](https://secure.travis-ci.org/kelp404/CocoaSecurity.png?branch=master)](http://travis-ci.org/#!/kelp404/CocoaSecurity) + +Kelp https://twitter.com/kelp404/ +[MIT License][mit] +[MIT]: http://www.opensource.org/licenses/mit-license.php + + +CocoaSecurity include 4 classes, `CocoaSecurity`, `CocoaSecurityResult`, `CocoaSecurityEncoder` and `CocoaSecurityDecoder`. + +##CocoaSecurity +CocoaSecurity is core. It provides AES encrypt, AES decrypt, Hash(MD5, HmacMD5, SHA1~SHA512, HmacSHA1~HmacSHA512) messages. + +**MD5:** +```objective-c +CocoaSecurityResult *md5 = [CocoaSecurity md5:@"kelp"]; + +// md5.hex = 'C40C69779E15780ADAE46C45EB451E23' +// md5.hexLower = 'c40c69779e15780adae46c45eb451e23' +// md5.base64 = 'xAxpd54VeAra5GxF60UeIw==' +``` +**SHA256:** +```objective-c +CocoaSecurityResult *sha256 = [CocoaSecurity sha256:@"kelp"]; + +// sha256.hexLower = '280f8bb8c43d532f389ef0e2a5321220b0782b065205dcdfcb8d8f02ed5115b9' +// sha256.base64 = 'KA+LuMQ9Uy84nvDipTISILB4KwZSBdzfy42PAu1RFbk=' +``` +**default AES Encrypt:**
+key -> SHA384(key).sub(0, 32)
+iv -> SHA384(key).sub(32, 16) +```objective-c +CocoaSecurityResult *aesDefault = [CocoaSecurity aesEncrypt:@"kelp" key:@"key"]; + +// aesDefault.base64 = 'ez9uubPneV1d2+rpjnabJw==' +``` +**AES256 Encrypt & Decrypt:** +```objective-c +CocoaSecurityResult *aes256 = [CocoaSecurity aesEncrypt:@"kelp" + hexKey:@"280f8bb8c43d532f389ef0e2a5321220b0782b065205dcdfcb8d8f02ed5115b9" + hexIv:@"CC0A69779E15780ADAE46C45EB451A23"]; +// aes256.base64 = 'WQYg5qvcGyCBY3IF0hPsoQ==' + +CocoaSecurityResult *aes256Decrypt = [CocoaSecurity aesDecryptWithBase64:@"WQYg5qvcGyCBY3IF0hPsoQ==" + hexKey:@"280f8bb8c43d532f389ef0e2a5321220b0782b065205dcdfcb8d8f02ed5115b9" + hexIv:@"CC0A69779E15780ADAE46C45EB451A23"]; +// aes256Decrypt.utf8String = 'kelp' +``` + + +##CocoaSecurityResult +CocoaSecurityResult is the result class of CocoaSecurity. It provides convert result data to NSData, NSString, HEX string, Base64 string. + +```objective-c +@property (strong, nonatomic, readonly) NSData *data; +@property (strong, nonatomic, readonly) NSString *utf8String; +@property (strong, nonatomic, readonly) NSString *hex; +@property (strong, nonatomic, readonly) NSString *hexLower; +@property (strong, nonatomic, readonly) NSString *base64; +``` + + +##CocoaSecurityEncoder +CocoaSecurityEncoder provides convert NSData to HEX string, Base64 string. + +```objective-c +- (NSString *)base64:(NSData *)data; +- (NSString *)hex:(NSData *)data useLower:(BOOL)isOutputLower; +``` +**example:** +```objective-c +CocoaSecurityEncoder *encoder = [CocoaSecurityEncoder new]; +NSString *str1 = [encoder hex:[@"kelp" dataUsingEncoding:NSUTF8StringEncoding] useLower:NO]; +// str1 = '6B656C70' +NSString *str2 = [encoder base64:[@"kelp" dataUsingEncoding:NSUTF8StringEncoding]]; +// str2 = 'a2VscA==' +``` + +##CocoaSecurityDecoder +CocoaSecurityEncoder provides convert HEX string or Base64 string to NSData. + +```objective-c +- (NSData *)base64:(NSString *)data; +- (NSData *)hex:(NSString *)data; +``` +**example:** +```objective-c +CocoaSecurityDecoder *decoder = [CocoaSecurityDecoder new]; +NSData *data1 = [decoder hex:@"CC0A69779E15780ADAE46C45EB451A23"]; +// data1 = +NSData *data2 = [decoder base64:@"zT1PS64MnXIUDCUiy13RRg=="]; +// data2 = +``` + + +##Installation +1. **git:** +``` +$ git clone git://github.com/kelp404/CocoaSecurity.git +$ cd CocoaSecurity +$ git submodule update --init +``` + +2. **CocoadPods:** +add `Podfile` in your project path +``` +platform :ios +pod 'CocoaSecurity' +``` +``` +$ pod install +``` diff --git a/Pods/CocoaSecurity/submodules/Base64/Base64/Base64.h b/Pods/CocoaSecurity/submodules/Base64/Base64/Base64.h new file mode 100644 index 0000000..69154a3 --- /dev/null +++ b/Pods/CocoaSecurity/submodules/Base64/Base64/Base64.h @@ -0,0 +1,53 @@ +// +// Base64.h +// +// Version 1.2 +// +// Created by Nick Lockwood on 12/01/2012. +// Copyright (C) 2012 Charcoal Design +// +// Distributed under the permissive zlib License +// Get the latest version from here: +// +// https://github.com/nicklockwood/Base64 +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// + +#import + + +@interface NSData (Base64) + ++ (NSData *)dataWithBase64EncodedString:(NSString *)string; +- (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth; +- (NSString *)base64EncodedString; + +@end + + +@interface NSString (Base64) + ++ (NSString *)stringWithBase64EncodedString:(NSString *)string; +- (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth; +- (NSString *)base64EncodedString; +- (NSString *)base64DecodedString; +- (NSData *)base64DecodedData; + +@end diff --git a/Pods/CocoaSecurity/submodules/Base64/Base64/Base64.m b/Pods/CocoaSecurity/submodules/Base64/Base64/Base64.m new file mode 100644 index 0000000..0dffdb0 --- /dev/null +++ b/Pods/CocoaSecurity/submodules/Base64/Base64/Base64.m @@ -0,0 +1,167 @@ +// +// Base64.m +// +// Version 1.2 +// +// Created by Nick Lockwood on 12/01/2012. +// Copyright (C) 2012 Charcoal Design +// +// Distributed under the permissive zlib License +// Get the latest version from here: +// +// https://github.com/nicklockwood/Base64 +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an aacknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// + +#import "Base64.h" + + +#pragma GCC diagnostic ignored "-Wselector" + + +#import +#if !__has_feature(objc_arc) +#error This library requires automatic reference counting +#endif + + +@implementation NSData (Base64) + ++ (NSData *)dataWithBase64EncodedString:(NSString *)string +{ + if (![string length]) return nil; + + NSData *decoded = nil; + +#if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_9 || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0 + + if (![NSData instancesRespondToSelector:@selector(initWithBase64EncodedString:options:)]) + { + decoded = [[self alloc] initWithBase64Encoding:[string stringByReplacingOccurrencesOfString:@"[^A-Za-z0-9+/=]" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, [string length])]]; + } + else + +#endif + + { + decoded = [[self alloc] initWithBase64EncodedString:string options:NSDataBase64DecodingIgnoreUnknownCharacters]; + } + + return [decoded length]? decoded: nil; +} + +- (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth +{ + if (![self length]) return nil; + + NSString *encoded = nil; + +#if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_9 || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0 + + if (![NSData instancesRespondToSelector:@selector(base64EncodedStringWithOptions:)]) + { + encoded = [self base64Encoding]; + } + else + +#endif + + { + switch (wrapWidth) + { + case 64: + { + return [self base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; + } + case 76: + { + return [self base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength]; + } + default: + { + encoded = [self base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)0]; + } + } + } + + if (!wrapWidth || wrapWidth >= [encoded length]) + { + return encoded; + } + + wrapWidth = (wrapWidth / 4) * 4; + NSMutableString *result = [NSMutableString string]; + for (NSUInteger i = 0; i < [encoded length]; i+= wrapWidth) + { + if (i + wrapWidth >= [encoded length]) + { + [result appendString:[encoded substringFromIndex:i]]; + break; + } + [result appendString:[encoded substringWithRange:NSMakeRange(i, wrapWidth)]]; + [result appendString:@"\r\n"]; + } + + return result; +} + +- (NSString *)base64EncodedString +{ + return [self base64EncodedStringWithWrapWidth:0]; +} + +@end + + +@implementation NSString (Base64) + ++ (NSString *)stringWithBase64EncodedString:(NSString *)string +{ + NSData *data = [NSData dataWithBase64EncodedString:string]; + if (data) + { + return [[self alloc] initWithData:data encoding:NSUTF8StringEncoding]; + } + return nil; +} + +- (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth +{ + NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; + return [data base64EncodedStringWithWrapWidth:wrapWidth]; +} + +- (NSString *)base64EncodedString +{ + NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; + return [data base64EncodedString]; +} + +- (NSString *)base64DecodedString +{ + return [NSString stringWithBase64EncodedString:self]; +} + +- (NSData *)base64DecodedData +{ + return [NSData dataWithBase64EncodedString:self]; +} + +@end diff --git a/Pods/JSONModel/JSONModel/JSONModel/JSONModel.h b/Pods/JSONModel/JSONModel/JSONModel/JSONModel.h new file mode 100644 index 0000000..c4ca47c --- /dev/null +++ b/Pods/JSONModel/JSONModel/JSONModel/JSONModel.h @@ -0,0 +1,284 @@ +// +// JSONModel.h +// JSONModel +// + +#import + +#import "JSONModelError.h" +#import "JSONValueTransformer.h" +#import "JSONKeyMapper.h" + +///////////////////////////////////////////////////////////////////////////////////////////// +#if TARGET_IPHONE_SIMULATOR +#define JMLog( s, ... ) NSLog( @"[%@:%d] %@", [[NSString stringWithUTF8String:__FILE__] \ +lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] ) +#else +#define JMLog( s, ... ) +#endif +///////////////////////////////////////////////////////////////////////////////////////////// + +DEPRECATED_ATTRIBUTE +@protocol ConvertOnDemand +@end + +DEPRECATED_ATTRIBUTE +@protocol Index +@end + +#pragma mark - Property Protocols +/** + * Protocol for defining properties in a JSON Model class that should not be considered at all + * neither while importing nor when exporting JSON. + * + * @property (strong, nonatomic) NSString *propertyName; + * + */ +@protocol Ignore +@end + +/** + * Protocol for defining optional properties in a JSON Model class. Use like below to define + * model properties that are not required to have values in the JSON input: + * + * @property (strong, nonatomic) NSString *propertyName; + * + */ +@protocol Optional +@end + +/** + * Make all objects compatible to avoid compiler warnings + */ +@interface NSObject (JSONModelPropertyCompatibility) +@end + +///////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - JSONModel protocol +/** + * A protocol describing an abstract JSONModel class + * JSONModel conforms to this protocol, so it can use itself abstractly + */ +@protocol AbstractJSONModelProtocol + +@required +/** + * All JSONModel classes should implement initWithDictionary: + * + * For most classes the default initWithDictionary: inherited from JSONModel itself + * should suffice, but developers have the option to also overwrite it if needed. + * + * @param dict a dictionary holding JSON objects, to be imported in the model. + * @param err an error or NULL + */ +- (instancetype)initWithDictionary:(NSDictionary *)dict error:(NSError **)err; + + +/** + * All JSONModel classes should implement initWithData:error: + * + * For most classes the default initWithData: inherited from JSONModel itself + * should suffice, but developers have the option to also overwrite it if needed. + * + * @param data representing a JSON response (usually fetched from web), to be imported in the model. + * @param error an error or NULL + */ +- (instancetype)initWithData:(NSData *)data error:(NSError **)error; + +/** + * All JSONModel classes should be able to export themselves as a dictionary of + * JSON compliant objects. + * + * For most classes the inherited from JSONModel default toDictionary implementation + * should suffice. + * + * @return NSDictionary dictionary of JSON compliant objects + * @exception JSONModelTypeNotAllowedException thrown when one of your model's custom class properties + * does not have matching transformer method in an JSONValueTransformer. + */ +- (NSDictionary *)toDictionary; + +/** + * Export a model class to a dictionary, including only given properties + * + * @param propertyNames the properties to export; if nil, all properties exported + * @return NSDictionary dictionary of JSON compliant objects + * @exception JSONModelTypeNotAllowedException thrown when one of your model's custom class properties + * does not have matching transformer method in an JSONValueTransformer. + */ +- (NSDictionary *)toDictionaryWithKeys:(NSArray *)propertyNames; +@end + +///////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - JSONModel interface +/** + * The JSONModel is an abstract model class, you should not instantiate it directly, + * as it does not have any properties, and therefore cannot serve as a data model. + * Instead you should subclass it, and define the properties you want your data model + * to have as properties of your own class. + */ +@interface JSONModel : NSObject + +// deprecated ++ (NSMutableArray *)arrayOfModelsFromDictionaries:(NSArray *)array DEPRECATED_MSG_ATTRIBUTE("use arrayOfModelsFromDictionaries:error:"); ++ (void)setGlobalKeyMapper:(JSONKeyMapper *)globalKeyMapper DEPRECATED_MSG_ATTRIBUTE("override +keyMapper in a base model class instead"); ++ (NSString *)protocolForArrayProperty:(NSString *)propertyName DEPRECATED_MSG_ATTRIBUTE("use classForCollectionProperty:"); +- (void)mergeFromDictionary:(NSDictionary *)dict useKeyMapping:(BOOL)useKeyMapping DEPRECATED_MSG_ATTRIBUTE("use mergeFromDictionary:useKeyMapping:error:"); +- (NSString *)indexPropertyName DEPRECATED_ATTRIBUTE; +- (NSComparisonResult)compare:(id)object DEPRECATED_ATTRIBUTE; + +/** @name Creating and initializing models */ + +/** + * Create a new model instance and initialize it with the JSON from a text parameter. The method assumes UTF8 encoded input text. + * @param string JSON text data + * @param err an initialization error or nil + * @exception JSONModelTypeNotAllowedException thrown when unsupported type is found in the incoming JSON, + * or a property type in your model is not supported by JSONValueTransformer and its categories + * @see initWithString:usingEncoding:error: for use of custom text encodings + */ +- (instancetype)initWithString:(NSString *)string error:(JSONModelError **)err; + +/** + * Create a new model instance and initialize it with the JSON from a text parameter using the given encoding. + * @param string JSON text data + * @param encoding the text encoding to use when parsing the string (see NSStringEncoding) + * @param err an initialization error or nil + * @exception JSONModelTypeNotAllowedException thrown when unsupported type is found in the incoming JSON, + * or a property type in your model is not supported by JSONValueTransformer and its categories + */ +- (instancetype)initWithString:(NSString *)string usingEncoding:(NSStringEncoding)encoding error:(JSONModelError **)err; + +/** @name Exporting model contents */ + +/** + * Export the whole object to a JSON data text string + * @return JSON text describing the data model + */ +- (NSString *)toJSONString; + +/** + * Export the whole object to a JSON data text string + * @return JSON text data describing the data model + */ +- (NSData *)toJSONData; + +/** + * Export the specified properties of the object to a JSON data text string + * @param propertyNames the properties to export; if nil, all properties exported + * @return JSON text describing the data model + */ +- (NSString *)toJSONStringWithKeys:(NSArray *)propertyNames; + +/** + * Export the specified properties of the object to a JSON data text string + * @param propertyNames the properties to export; if nil, all properties exported + * @return JSON text data describing the data model + */ +- (NSData *)toJSONDataWithKeys:(NSArray *)propertyNames; + +/** @name Batch methods */ + +/** + * If you have a list of dictionaries in a JSON feed, you can use this method to create an NSArray + * of model objects. Handy when importing JSON data lists. + * This method will loop over the input list and initialize a data model for every dictionary in the list. + * + * @param array list of dictionaries to be imported as models + * @return list of initialized data model objects + * @exception JSONModelTypeNotAllowedException thrown when unsupported type is found in the incoming JSON, + * or a property type in your model is not supported by JSONValueTransformer and its categories + * @exception JSONModelInvalidDataException thrown when the input data does not include all required keys + * @see arrayOfDictionariesFromModels: + */ ++ (NSMutableArray *)arrayOfModelsFromDictionaries:(NSArray *)array error:(NSError **)err; ++ (NSMutableArray *)arrayOfModelsFromData:(NSData *)data error:(NSError **)err; ++ (NSMutableArray *)arrayOfModelsFromString:(NSString *)string error:(NSError **)err; ++ (NSMutableDictionary *)dictionaryOfModelsFromDictionary:(NSDictionary *)dictionary error:(NSError **)err; ++ (NSMutableDictionary *)dictionaryOfModelsFromData:(NSData *)data error:(NSError **)err; ++ (NSMutableDictionary *)dictionaryOfModelsFromString:(NSString *)string error:(NSError **)err; + +/** + * If you have an NSArray of data model objects, this method takes it in and outputs a list of the + * matching dictionaries. This method does the opposite of arrayOfObjectsFromDictionaries: + * @param array list of JSONModel objects + * @return a list of NSDictionary objects + * @exception JSONModelTypeNotAllowedException thrown when unsupported type is found in the incoming JSON, + * or a property type in your model is not supported by JSONValueTransformer and its categories + * @see arrayOfModelsFromDictionaries: + */ ++ (NSMutableArray *)arrayOfDictionariesFromModels:(NSArray *)array; ++ (NSMutableDictionary *)dictionaryOfDictionariesFromModels:(NSDictionary *)dictionary; + +/** @name Validation */ + +/** + * Overwrite the validate method in your own models if you need to perform some custom validation over the model data. + * This method gets called at the very end of the JSONModel initializer, thus the model is in the state that you would + * get it back when initialized. Check the values of any property that needs to be validated and if any invalid values + * are encountered return NO and set the error parameter to an NSError object. If the model is valid return YES. + * + * NB: Only setting the error parameter is not enough to fail the validation, you also need to return a NO value. + * + * @param error a pointer to an NSError object, to pass back an error if needed + * @return a BOOL result, showing whether the model data validates or not. You can use the convenience method + * [JSONModelError errorModelIsInvalid] to set the NSError param if the data fails your custom validation + */ +- (BOOL)validate:(NSError **)error; + +/** @name Key mapping */ +/** + * Overwrite in your models if your property names don't match your JSON key names. + * Lookup JSONKeyMapper docs for more details. + */ ++ (JSONKeyMapper *)keyMapper; + +/** + * Indicates whether the property with the given name is Optional. + * To have a model with all of its properties being Optional just return YES. + * This method returns by default NO, since the default behaviour is to have all properties required. + * @param propertyName the name of the property + * @return a BOOL result indicating whether the property is optional + */ ++ (BOOL)propertyIsOptional:(NSString *)propertyName; + +/** + * Indicates whether the property with the given name is Ignored. + * To have a model with all of its properties being Ignored just return YES. + * This method returns by default NO, since the default behaviour is to have all properties required. + * @param propertyName the name of the property + * @return a BOOL result indicating whether the property is ignored + */ ++ (BOOL)propertyIsIgnored:(NSString *)propertyName; + +/** + * Indicates the class used for the elements of a collection property. + * Rather than using: + * @property (strong) NSArray *things; + * You can implement classForCollectionProperty: and keep your property + * defined like: + * @property (strong) NSArray *things; + * @param propertyName the name of the property + * @return Class the class used to deserialize the elements of the collection + * + * Example in Swift 3.0: + * override static func classForCollectionProperty(propertyName: String) -> AnyClass? { + * switch propertyName { + * case "childModel": + * return ChildModel.self + * default: + * return nil + * } + * } + */ ++ (Class)classForCollectionProperty:(NSString *)propertyName NS_SWIFT_NAME(classForCollectionProperty(propertyName:)); + +/** + * Merges values from the given dictionary into the model instance. + * @param dict dictionary with values + * @param useKeyMapping if YES the method will use the model's key mapper and the global key mapper, if NO + * it'll just try to match the dictionary keys to the model's properties + */ +- (BOOL)mergeFromDictionary:(NSDictionary *)dict useKeyMapping:(BOOL)useKeyMapping error:(NSError **)error; + +@end diff --git a/Pods/JSONModel/JSONModel/JSONModel/JSONModel.m b/Pods/JSONModel/JSONModel/JSONModel/JSONModel.m new file mode 100644 index 0000000..4ae211a --- /dev/null +++ b/Pods/JSONModel/JSONModel/JSONModel/JSONModel.m @@ -0,0 +1,1387 @@ +// +// JSONModel.m +// JSONModel +// + +#if !__has_feature(objc_arc) +#error The JSONMOdel framework is ARC only, you can enable ARC on per file basis. +#endif + + +#import +#import + + +#import "JSONModel.h" +#import "JSONModelClassProperty.h" + +#pragma mark - associated objects names +static const char * kMapperObjectKey; +static const char * kClassPropertiesKey; +static const char * kClassRequiredPropertyNamesKey; +static const char * kIndexPropertyNameKey; + +#pragma mark - class static variables +static NSArray* allowedJSONTypes = nil; +static NSArray* allowedPrimitiveTypes = nil; +static JSONValueTransformer* valueTransformer = nil; +static Class JSONModelClass = NULL; + +#pragma mark - model cache +static JSONKeyMapper* globalKeyMapper = nil; + +#pragma mark - JSONModel implementation +@implementation JSONModel +{ + NSString* _description; +} + +#pragma mark - initialization methods + ++(void)load +{ + static dispatch_once_t once; + dispatch_once(&once, ^{ + // initialize all class static objects, + // which are common for ALL JSONModel subclasses + + @autoreleasepool { + allowedJSONTypes = @[ + [NSString class], [NSNumber class], [NSDecimalNumber class], [NSArray class], [NSDictionary class], [NSNull class], //immutable JSON classes + [NSMutableString class], [NSMutableArray class], [NSMutableDictionary class] //mutable JSON classes + ]; + + allowedPrimitiveTypes = @[ + @"BOOL", @"float", @"int", @"long", @"double", @"short", + @"unsigned int", @"usigned long", @"long long", @"unsigned long long", @"unsigned short", @"char", @"unsigned char", + //and some famous aliases + @"NSInteger", @"NSUInteger", + @"Block" + ]; + + valueTransformer = [[JSONValueTransformer alloc] init]; + + // This is quite strange, but I found the test isSubclassOfClass: (line ~291) to fail if using [JSONModel class]. + // somewhat related: https://stackoverflow.com/questions/6524165/nsclassfromstring-vs-classnamednsstring + // //; seems to break the unit tests + + // Using NSClassFromString instead of [JSONModel class], as this was breaking unit tests, see below + //http://stackoverflow.com/questions/21394919/xcode-5-unit-test-seeing-wrong-class + JSONModelClass = NSClassFromString(NSStringFromClass(self)); + } + }); +} + +-(void)__setup__ +{ + //if first instance of this model, generate the property list + if (!objc_getAssociatedObject(self.class, &kClassPropertiesKey)) { + [self __inspectProperties]; + } + + //if there's a custom key mapper, store it in the associated object + id mapper = [[self class] keyMapper]; + if ( mapper && !objc_getAssociatedObject(self.class, &kMapperObjectKey) ) { + objc_setAssociatedObject( + self.class, + &kMapperObjectKey, + mapper, + OBJC_ASSOCIATION_RETAIN // This is atomic + ); + } +} + +-(id)init +{ + self = [super init]; + if (self) { + //do initial class setup + [self __setup__]; + } + return self; +} + +-(instancetype)initWithData:(NSData *)data error:(NSError *__autoreleasing *)err +{ + //check for nil input + if (!data) { + if (err) *err = [JSONModelError errorInputIsNil]; + return nil; + } + //read the json + JSONModelError* initError = nil; + id obj = [NSJSONSerialization JSONObjectWithData:data + options:kNilOptions + error:&initError]; + + if (initError) { + if (err) *err = [JSONModelError errorBadJSON]; + return nil; + } + + //init with dictionary + id objModel = [self initWithDictionary:obj error:&initError]; + if (initError && err) *err = initError; + return objModel; +} + +-(id)initWithString:(NSString*)string error:(JSONModelError**)err +{ + JSONModelError* initError = nil; + id objModel = [self initWithString:string usingEncoding:NSUTF8StringEncoding error:&initError]; + if (initError && err) *err = initError; + return objModel; +} + +-(id)initWithString:(NSString *)string usingEncoding:(NSStringEncoding)encoding error:(JSONModelError**)err +{ + //check for nil input + if (!string) { + if (err) *err = [JSONModelError errorInputIsNil]; + return nil; + } + + JSONModelError* initError = nil; + id objModel = [self initWithData:[string dataUsingEncoding:encoding] error:&initError]; + if (initError && err) *err = initError; + return objModel; + +} + +-(id)initWithDictionary:(NSDictionary*)dict error:(NSError**)err +{ + //check for nil input + if (!dict) { + if (err) *err = [JSONModelError errorInputIsNil]; + return nil; + } + + //invalid input, just create empty instance + if (![dict isKindOfClass:[NSDictionary class]]) { + if (err) *err = [JSONModelError errorInvalidDataWithMessage:@"Attempt to initialize JSONModel object using initWithDictionary:error: but the dictionary parameter was not an 'NSDictionary'."]; + return nil; + } + + //create a class instance + self = [self init]; + if (!self) { + + //super init didn't succeed + if (err) *err = [JSONModelError errorModelIsInvalid]; + return nil; + } + + //check incoming data structure + if (![self __doesDictionary:dict matchModelWithKeyMapper:self.__keyMapper error:err]) { + return nil; + } + + //import the data from a dictionary + if (![self __importDictionary:dict withKeyMapper:self.__keyMapper validation:YES error:err]) { + return nil; + } + + //run any custom model validation + if (![self validate:err]) { + return nil; + } + + //model is valid! yay! + return self; +} + +-(JSONKeyMapper*)__keyMapper +{ + //get the model key mapper + return objc_getAssociatedObject(self.class, &kMapperObjectKey); +} + +-(BOOL)__doesDictionary:(NSDictionary*)dict matchModelWithKeyMapper:(JSONKeyMapper*)keyMapper error:(NSError**)err +{ + //check if all required properties are present + NSArray* incomingKeysArray = [dict allKeys]; + NSMutableSet* requiredProperties = [self __requiredPropertyNames].mutableCopy; + NSSet* incomingKeys = [NSSet setWithArray: incomingKeysArray]; + + //transform the key names, if necessary + if (keyMapper || globalKeyMapper) { + + NSMutableSet* transformedIncomingKeys = [NSMutableSet setWithCapacity: requiredProperties.count]; + NSString* transformedName = nil; + + //loop over the required properties list + for (JSONModelClassProperty* property in [self __properties__]) { + + transformedName = (keyMapper||globalKeyMapper) ? [self __mapString:property.name withKeyMapper:keyMapper] : property.name; + + //check if exists and if so, add to incoming keys + id value; + @try { + value = [dict valueForKeyPath:transformedName]; + } + @catch (NSException *exception) { + value = dict[transformedName]; + } + + if (value) { + [transformedIncomingKeys addObject: property.name]; + } + } + + //overwrite the raw incoming list with the mapped key names + incomingKeys = transformedIncomingKeys; + } + + //check for missing input keys + if (![requiredProperties isSubsetOfSet:incomingKeys]) { + + //get a list of the missing properties + [requiredProperties minusSet:incomingKeys]; + + //not all required properties are in - invalid input + JMLog(@"Incoming data was invalid [%@ initWithDictionary:]. Keys missing: %@", self.class, requiredProperties); + + if (err) *err = [JSONModelError errorInvalidDataWithMissingKeys:requiredProperties]; + return NO; + } + + //not needed anymore + incomingKeys= nil; + requiredProperties= nil; + + return YES; +} + +-(NSString*)__mapString:(NSString*)string withKeyMapper:(JSONKeyMapper*)keyMapper +{ + if (keyMapper) { + //custom mapper + NSString* mappedName = [keyMapper convertValue:string]; + if (globalKeyMapper && [mappedName isEqualToString: string]) { + mappedName = [globalKeyMapper convertValue:string]; + } + string = mappedName; + } else if (globalKeyMapper) { + //global keymapper + string = [globalKeyMapper convertValue:string]; + } + + return string; +} + +-(BOOL)__importDictionary:(NSDictionary*)dict withKeyMapper:(JSONKeyMapper*)keyMapper validation:(BOOL)validation error:(NSError**)err +{ + //loop over the incoming keys and set self's properties + for (JSONModelClassProperty* property in [self __properties__]) { + + //convert key name to model keys, if a mapper is provided + NSString* jsonKeyPath = (keyMapper||globalKeyMapper) ? [self __mapString:property.name withKeyMapper:keyMapper] : property.name; + //JMLog(@"keyPath: %@", jsonKeyPath); + + //general check for data type compliance + id jsonValue; + @try { + jsonValue = [dict valueForKeyPath: jsonKeyPath]; + } + @catch (NSException *exception) { + jsonValue = dict[jsonKeyPath]; + } + + //check for Optional properties + if (isNull(jsonValue)) { + //skip this property, continue with next property + if (property.isOptional || !validation) continue; + + if (err) { + //null value for required property + NSString* msg = [NSString stringWithFormat:@"Value of required model key %@ is null", property.name]; + JSONModelError* dataErr = [JSONModelError errorInvalidDataWithMessage:msg]; + *err = [dataErr errorByPrependingKeyPathComponent:property.name]; + } + return NO; + } + + Class jsonValueClass = [jsonValue class]; + BOOL isValueOfAllowedType = NO; + + for (Class allowedType in allowedJSONTypes) { + if ( [jsonValueClass isSubclassOfClass: allowedType] ) { + isValueOfAllowedType = YES; + break; + } + } + + if (isValueOfAllowedType==NO) { + //type not allowed + JMLog(@"Type %@ is not allowed in JSON.", NSStringFromClass(jsonValueClass)); + + if (err) { + NSString* msg = [NSString stringWithFormat:@"Type %@ is not allowed in JSON.", NSStringFromClass(jsonValueClass)]; + JSONModelError* dataErr = [JSONModelError errorInvalidDataWithMessage:msg]; + *err = [dataErr errorByPrependingKeyPathComponent:property.name]; + } + return NO; + } + + //check if there's matching property in the model + if (property) { + + // check for custom setter, than the model doesn't need to do any guessing + // how to read the property's value from JSON + if ([self __customSetValue:jsonValue forProperty:property]) { + //skip to next JSON key + continue; + }; + + // 0) handle primitives + if (property.type == nil && property.structName==nil) { + + //generic setter + if (jsonValue != [self valueForKey:property.name]) { + [self setValue:jsonValue forKey: property.name]; + } + + //skip directly to the next key + continue; + } + + // 0.5) handle nils + if (isNull(jsonValue)) { + if ([self valueForKey:property.name] != nil) { + [self setValue:nil forKey: property.name]; + } + continue; + } + + + // 1) check if property is itself a JSONModel + if ([self __isJSONModelSubClass:property.type]) { + + //initialize the property's model, store it + JSONModelError* initErr = nil; + id value = [[property.type alloc] initWithDictionary: jsonValue error:&initErr]; + + if (!value) { + //skip this property, continue with next property + if (property.isOptional || !validation) continue; + + // Propagate the error, including the property name as the key-path component + if((err != nil) && (initErr != nil)) + { + *err = [initErr errorByPrependingKeyPathComponent:property.name]; + } + return NO; + } + if (![value isEqual:[self valueForKey:property.name]]) { + [self setValue:value forKey: property.name]; + } + + //for clarity, does the same without continue + continue; + + } else { + + // 2) check if there's a protocol to the property + // ) might or not be the case there's a built in transform for it + if (property.protocol) { + + //JMLog(@"proto: %@", p.protocol); + jsonValue = [self __transform:jsonValue forProperty:property error:err]; + if (!jsonValue) { + if ((err != nil) && (*err == nil)) { + NSString* msg = [NSString stringWithFormat:@"Failed to transform value, but no error was set during transformation. (%@)", property]; + JSONModelError* dataErr = [JSONModelError errorInvalidDataWithMessage:msg]; + *err = [dataErr errorByPrependingKeyPathComponent:property.name]; + } + return NO; + } + } + + // 3.1) handle matching standard JSON types + if (property.isStandardJSONType && [jsonValue isKindOfClass: property.type]) { + + //mutable properties + if (property.isMutable) { + jsonValue = [jsonValue mutableCopy]; + } + + //set the property value + if (![jsonValue isEqual:[self valueForKey:property.name]]) { + [self setValue:jsonValue forKey: property.name]; + } + continue; + } + + // 3.3) handle values to transform + if ( + (![jsonValue isKindOfClass:property.type] && !isNull(jsonValue)) + || + //the property is mutable + property.isMutable + || + //custom struct property + property.structName + ) { + + // searched around the web how to do this better + // but did not find any solution, maybe that's the best idea? (hardly) + Class sourceClass = [JSONValueTransformer classByResolvingClusterClasses:[jsonValue class]]; + + //JMLog(@"to type: [%@] from type: [%@] transformer: [%@]", p.type, sourceClass, selectorName); + + //build a method selector for the property and json object classes + NSString* selectorName = [NSString stringWithFormat:@"%@From%@:", + (property.structName? property.structName : property.type), //target name + sourceClass]; //source name + SEL selector = NSSelectorFromString(selectorName); + + //check for custom transformer + BOOL foundCustomTransformer = NO; + if ([valueTransformer respondsToSelector:selector]) { + foundCustomTransformer = YES; + } else { + //try for hidden custom transformer + selectorName = [NSString stringWithFormat:@"__%@",selectorName]; + selector = NSSelectorFromString(selectorName); + if ([valueTransformer respondsToSelector:selector]) { + foundCustomTransformer = YES; + } + } + + //check if there's a transformer with that name + if (foundCustomTransformer) { + IMP imp = [valueTransformer methodForSelector:selector]; + id (*func)(id, SEL, id) = (void *)imp; + jsonValue = func(valueTransformer, selector, jsonValue); + + if (![jsonValue isEqual:[self valueForKey:property.name]]) + [self setValue:jsonValue forKey:property.name]; + } else { + if (err) { + NSString* msg = [NSString stringWithFormat:@"%@ type not supported for %@.%@", property.type, [self class], property.name]; + JSONModelError* dataErr = [JSONModelError errorInvalidDataWithTypeMismatch:msg]; + *err = [dataErr errorByPrependingKeyPathComponent:property.name]; + } + return NO; + } + } else { + // 3.4) handle "all other" cases (if any) + if (![jsonValue isEqual:[self valueForKey:property.name]]) + [self setValue:jsonValue forKey:property.name]; + } + } + } + } + + return YES; +} + +#pragma mark - property inspection methods + +-(BOOL)__isJSONModelSubClass:(Class)class +{ +// http://stackoverflow.com/questions/19883472/objc-nsobject-issubclassofclass-gives-incorrect-failure +#ifdef UNIT_TESTING + return [@"JSONModel" isEqualToString: NSStringFromClass([class superclass])]; +#else + return [class isSubclassOfClass:JSONModelClass]; +#endif +} + +//returns a set of the required keys for the model +-(NSMutableSet*)__requiredPropertyNames +{ + //fetch the associated property names + NSMutableSet* classRequiredPropertyNames = objc_getAssociatedObject(self.class, &kClassRequiredPropertyNamesKey); + + if (!classRequiredPropertyNames) { + classRequiredPropertyNames = [NSMutableSet set]; + [[self __properties__] enumerateObjectsUsingBlock:^(JSONModelClassProperty* p, NSUInteger idx, BOOL *stop) { + if (!p.isOptional) [classRequiredPropertyNames addObject:p.name]; + }]; + + //persist the list + objc_setAssociatedObject( + self.class, + &kClassRequiredPropertyNamesKey, + classRequiredPropertyNames, + OBJC_ASSOCIATION_RETAIN // This is atomic + ); + } + return classRequiredPropertyNames; +} + +//returns a list of the model's properties +-(NSArray*)__properties__ +{ + //fetch the associated object + NSDictionary* classProperties = objc_getAssociatedObject(self.class, &kClassPropertiesKey); + if (classProperties) return [classProperties allValues]; + + //if here, the class needs to inspect itself + [self __setup__]; + + //return the property list + classProperties = objc_getAssociatedObject(self.class, &kClassPropertiesKey); + return [classProperties allValues]; +} + +//inspects the class, get's a list of the class properties +-(void)__inspectProperties +{ + //JMLog(@"Inspect class: %@", [self class]); + + NSMutableDictionary* propertyIndex = [NSMutableDictionary dictionary]; + + //temp variables for the loops + Class class = [self class]; + NSScanner* scanner = nil; + NSString* propertyType = nil; + + // inspect inherited properties up to the JSONModel class + while (class != [JSONModel class]) { + //JMLog(@"inspecting: %@", NSStringFromClass(class)); + + unsigned int propertyCount; + objc_property_t *properties = class_copyPropertyList(class, &propertyCount); + + //loop over the class properties + for (unsigned int i = 0; i < propertyCount; i++) { + + JSONModelClassProperty* p = [[JSONModelClassProperty alloc] init]; + + //get property name + objc_property_t property = properties[i]; + const char *propertyName = property_getName(property); + p.name = @(propertyName); + + //JMLog(@"property: %@", p.name); + + //get property attributes + const char *attrs = property_getAttributes(property); + NSString* propertyAttributes = @(attrs); + NSArray* attributeItems = [propertyAttributes componentsSeparatedByString:@","]; + + //ignore read-only properties + if ([attributeItems containsObject:@"R"]) { + continue; //to next property + } + + scanner = [NSScanner scannerWithString: propertyAttributes]; + + //JMLog(@"attr: %@", [NSString stringWithCString:attrs encoding:NSUTF8StringEncoding]); + [scanner scanUpToString:@"T" intoString: nil]; + [scanner scanString:@"T" intoString:nil]; + + //check if the property is an instance of a class + if ([scanner scanString:@"@\"" intoString: &propertyType]) { + + [scanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"\"<"] + intoString:&propertyType]; + + //JMLog(@"type: %@", propertyClassName); + p.type = NSClassFromString(propertyType); + p.isMutable = ([propertyType rangeOfString:@"Mutable"].location != NSNotFound); + p.isStandardJSONType = [allowedJSONTypes containsObject:p.type]; + + //read through the property protocols + while ([scanner scanString:@"<" intoString:NULL]) { + + NSString* protocolName = nil; + + [scanner scanUpToString:@">" intoString: &protocolName]; + + if ([protocolName isEqualToString:@"Optional"]) { + p.isOptional = YES; + } else if([protocolName isEqualToString:@"Index"]) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + p.isIndex = YES; +#pragma GCC diagnostic pop + + objc_setAssociatedObject( + self.class, + &kIndexPropertyNameKey, + p.name, + OBJC_ASSOCIATION_RETAIN // This is atomic + ); + } else if([protocolName isEqualToString:@"Ignore"]) { + p = nil; + } else { + p.protocol = protocolName; + } + + [scanner scanString:@">" intoString:NULL]; + } + + } + //check if the property is a structure + else if ([scanner scanString:@"{" intoString: &propertyType]) { + [scanner scanCharactersFromSet:[NSCharacterSet alphanumericCharacterSet] + intoString:&propertyType]; + + p.isStandardJSONType = NO; + p.structName = propertyType; + + } + //the property must be a primitive + else { + + //the property contains a primitive data type + [scanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@","] + intoString:&propertyType]; + + //get the full name of the primitive type + propertyType = valueTransformer.primitivesNames[propertyType]; + + if (![allowedPrimitiveTypes containsObject:propertyType]) { + + //type not allowed - programmer mistaken -> exception + @throw [NSException exceptionWithName:@"JSONModelProperty type not allowed" + reason:[NSString stringWithFormat:@"Property type of %@.%@ is not supported by JSONModel.", self.class, p.name] + userInfo:nil]; + } + + } + + NSString *nsPropertyName = @(propertyName); + if([[self class] propertyIsOptional:nsPropertyName]){ + p.isOptional = YES; + } + + if([[self class] propertyIsIgnored:nsPropertyName]){ + p = nil; + } + + Class customClass = [[self class] classForCollectionProperty:nsPropertyName]; + if (customClass) { + p.protocol = NSStringFromClass(customClass); + } + + //few cases where JSONModel will ignore properties automatically + if ([propertyType isEqualToString:@"Block"]) { + p = nil; + } + + //add the property object to the temp index + if (p && ![propertyIndex objectForKey:p.name]) { + [propertyIndex setValue:p forKey:p.name]; + } + + // generate custom setters and getter + if (p) + { + NSString *name = [p.name stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:[p.name substringToIndex:1].uppercaseString]; + + // getter + SEL getter = NSSelectorFromString([NSString stringWithFormat:@"JSONObjectFor%@", name]); + + if ([self respondsToSelector:getter]) + p.customGetter = getter; + + // setters + p.customSetters = [NSMutableDictionary new]; + + SEL genericSetter = NSSelectorFromString([NSString stringWithFormat:@"set%@WithJSONObject:", name]); + + if ([self respondsToSelector:genericSetter]) + p.customSetters[@"generic"] = [NSValue valueWithBytes:&genericSetter objCType:@encode(SEL)]; + + for (Class type in allowedJSONTypes) + { + NSString *class = NSStringFromClass([JSONValueTransformer classByResolvingClusterClasses:type]); + + if (p.customSetters[class]) + continue; + + SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set%@With%@:", name, class]); + + if ([self respondsToSelector:setter]) + p.customSetters[class] = [NSValue valueWithBytes:&setter objCType:@encode(SEL)]; + } + } + } + + free(properties); + + //ascend to the super of the class + //(will do that until it reaches the root class - JSONModel) + class = [class superclass]; + } + + //finally store the property index in the static property index + objc_setAssociatedObject( + self.class, + &kClassPropertiesKey, + [propertyIndex copy], + OBJC_ASSOCIATION_RETAIN // This is atomic + ); +} + +#pragma mark - built-in transformer methods +//few built-in transformations +-(id)__transform:(id)value forProperty:(JSONModelClassProperty*)property error:(NSError**)err +{ + Class protocolClass = NSClassFromString(property.protocol); + if (!protocolClass) { + + //no other protocols on arrays and dictionaries + //except JSONModel classes + if ([value isKindOfClass:[NSArray class]]) { + @throw [NSException exceptionWithName:@"Bad property protocol declaration" + reason:[NSString stringWithFormat:@"<%@> is not allowed JSONModel property protocol, and not a JSONModel class.", property.protocol] + userInfo:nil]; + } + return value; + } + + //if the protocol is actually a JSONModel class + if ([self __isJSONModelSubClass:protocolClass]) { + + //check if it's a list of models + if ([property.type isSubclassOfClass:[NSArray class]]) { + + // Expecting an array, make sure 'value' is an array + if(![[value class] isSubclassOfClass:[NSArray class]]) + { + if(err != nil) + { + NSString* mismatch = [NSString stringWithFormat:@"Property '%@' is declared as NSArray<%@>* but the corresponding JSON value is not a JSON Array.", property.name, property.protocol]; + JSONModelError* typeErr = [JSONModelError errorInvalidDataWithTypeMismatch:mismatch]; + *err = [typeErr errorByPrependingKeyPathComponent:property.name]; + } + return nil; + } + + //one shot conversion + JSONModelError* arrayErr = nil; + value = [[protocolClass class] arrayOfModelsFromDictionaries:value error:&arrayErr]; + if((err != nil) && (arrayErr != nil)) + { + *err = [arrayErr errorByPrependingKeyPathComponent:property.name]; + return nil; + } + } + + //check if it's a dictionary of models + if ([property.type isSubclassOfClass:[NSDictionary class]]) { + + // Expecting a dictionary, make sure 'value' is a dictionary + if(![[value class] isSubclassOfClass:[NSDictionary class]]) + { + if(err != nil) + { + NSString* mismatch = [NSString stringWithFormat:@"Property '%@' is declared as NSDictionary<%@>* but the corresponding JSON value is not a JSON Object.", property.name, property.protocol]; + JSONModelError* typeErr = [JSONModelError errorInvalidDataWithTypeMismatch:mismatch]; + *err = [typeErr errorByPrependingKeyPathComponent:property.name]; + } + return nil; + } + + NSMutableDictionary* res = [NSMutableDictionary dictionary]; + + for (NSString* key in [value allKeys]) { + JSONModelError* initErr = nil; + id obj = [[[protocolClass class] alloc] initWithDictionary:value[key] error:&initErr]; + if (obj == nil) + { + // Propagate the error, including the property name as the key-path component + if((err != nil) && (initErr != nil)) + { + initErr = [initErr errorByPrependingKeyPathComponent:key]; + *err = [initErr errorByPrependingKeyPathComponent:property.name]; + } + return nil; + } + [res setValue:obj forKey:key]; + } + value = [NSDictionary dictionaryWithDictionary:res]; + } + } + + return value; +} + +//built-in reverse transformations (export to JSON compliant objects) +-(id)__reverseTransform:(id)value forProperty:(JSONModelClassProperty*)property +{ + Class protocolClass = NSClassFromString(property.protocol); + if (!protocolClass) return value; + + //if the protocol is actually a JSONModel class + if ([self __isJSONModelSubClass:protocolClass]) { + + //check if should export list of dictionaries + if (property.type == [NSArray class] || property.type == [NSMutableArray class]) { + NSMutableArray* tempArray = [NSMutableArray arrayWithCapacity: [(NSArray*)value count] ]; + for (NSObject* model in (NSArray*)value) { + if ([model respondsToSelector:@selector(toDictionary)]) { + [tempArray addObject: [model toDictionary]]; + } else + [tempArray addObject: model]; + } + return [tempArray copy]; + } + + //check if should export dictionary of dictionaries + if (property.type == [NSDictionary class] || property.type == [NSMutableDictionary class]) { + NSMutableDictionary* res = [NSMutableDictionary dictionary]; + for (NSString* key in [(NSDictionary*)value allKeys]) { + id model = value[key]; + [res setValue: [model toDictionary] forKey: key]; + } + return [NSDictionary dictionaryWithDictionary:res]; + } + } + + return value; +} + +#pragma mark - custom transformations +- (BOOL)__customSetValue:(id )value forProperty:(JSONModelClassProperty *)property +{ + NSString *class = NSStringFromClass([JSONValueTransformer classByResolvingClusterClasses:[value class]]); + + SEL setter = nil; + [property.customSetters[class] getValue:&setter]; + + if (!setter) + [property.customSetters[@"generic"] getValue:&setter]; + + if (!setter) + return NO; + + IMP imp = [self methodForSelector:setter]; + void (*func)(id, SEL, id ) = (void *)imp; + func(self, setter, value); + + return YES; +} + +- (BOOL)__customGetValue:(id *)value forProperty:(JSONModelClassProperty *)property +{ + SEL getter = property.customGetter; + + if (!getter) + return NO; + + IMP imp = [self methodForSelector:getter]; + id (*func)(id, SEL) = (void *)imp; + *value = func(self, getter); + + return YES; +} + +#pragma mark - persistance +-(void)__createDictionariesForKeyPath:(NSString*)keyPath inDictionary:(NSMutableDictionary**)dict +{ + //find if there's a dot left in the keyPath + NSUInteger dotLocation = [keyPath rangeOfString:@"."].location; + if (dotLocation==NSNotFound) return; + + //inspect next level + NSString* nextHierarchyLevelKeyName = [keyPath substringToIndex: dotLocation]; + NSDictionary* nextLevelDictionary = (*dict)[nextHierarchyLevelKeyName]; + + if (nextLevelDictionary==nil) { + //create non-existing next level here + nextLevelDictionary = [NSMutableDictionary dictionary]; + } + + //recurse levels + [self __createDictionariesForKeyPath:[keyPath substringFromIndex: dotLocation+1] + inDictionary:&nextLevelDictionary ]; + + //create the hierarchy level + [*dict setValue:nextLevelDictionary forKeyPath: nextHierarchyLevelKeyName]; +} + +-(NSDictionary*)toDictionary +{ + return [self toDictionaryWithKeys:nil]; +} + +-(NSString*)toJSONString +{ + return [self toJSONStringWithKeys:nil]; +} + +-(NSData*)toJSONData +{ + return [self toJSONDataWithKeys:nil]; +} + +//exports the model as a dictionary of JSON compliant objects +- (NSDictionary *)toDictionaryWithKeys:(NSArray *)propertyNames +{ + NSArray* properties = [self __properties__]; + NSMutableDictionary* tempDictionary = [NSMutableDictionary dictionaryWithCapacity:properties.count]; + + id value; + + //loop over all properties + for (JSONModelClassProperty* p in properties) { + + //skip if unwanted + if (propertyNames != nil && ![propertyNames containsObject:p.name]) + continue; + + //fetch key and value + NSString* keyPath = (self.__keyMapper||globalKeyMapper) ? [self __mapString:p.name withKeyMapper:self.__keyMapper] : p.name; + value = [self valueForKey: p.name]; + + //JMLog(@"toDictionary[%@]->[%@] = '%@'", p.name, keyPath, value); + + if ([keyPath rangeOfString:@"."].location != NSNotFound) { + //there are sub-keys, introduce dictionaries for them + [self __createDictionariesForKeyPath:keyPath inDictionary:&tempDictionary]; + } + + //check for custom getter + if ([self __customGetValue:&value forProperty:p]) { + //custom getter, all done + [tempDictionary setValue:value forKeyPath:keyPath]; + continue; + } + + //export nil when they are not optional values as JSON null, so that the structure of the exported data + //is still valid if it's to be imported as a model again + if (isNull(value)) { + + if (value == nil) + { + [tempDictionary removeObjectForKey:keyPath]; + } + else + { + [tempDictionary setValue:[NSNull null] forKeyPath:keyPath]; + } + continue; + } + + //check if the property is another model + if ([value isKindOfClass:JSONModelClass]) { + + //recurse models + value = [(JSONModel*)value toDictionary]; + [tempDictionary setValue:value forKeyPath: keyPath]; + + //for clarity + continue; + + } else { + + // 1) check for built-in transformation + if (p.protocol) { + value = [self __reverseTransform:value forProperty:p]; + } + + // 2) check for standard types OR 2.1) primitives + if (p.structName==nil && (p.isStandardJSONType || p.type==nil)) { + + //generic get value + [tempDictionary setValue:value forKeyPath: keyPath]; + + continue; + } + + // 3) try to apply a value transformer + if (YES) { + + //create selector from the property's class name + NSString* selectorName = [NSString stringWithFormat:@"%@From%@:", @"JSONObject", p.type?p.type:p.structName]; + SEL selector = NSSelectorFromString(selectorName); + + BOOL foundCustomTransformer = NO; + if ([valueTransformer respondsToSelector:selector]) { + foundCustomTransformer = YES; + } else { + //try for hidden transformer + selectorName = [NSString stringWithFormat:@"__%@",selectorName]; + selector = NSSelectorFromString(selectorName); + if ([valueTransformer respondsToSelector:selector]) { + foundCustomTransformer = YES; + } + } + + //check if there's a transformer declared + if (foundCustomTransformer) { + IMP imp = [valueTransformer methodForSelector:selector]; + id (*func)(id, SEL, id) = (void *)imp; + value = func(valueTransformer, selector, value); + + [tempDictionary setValue:value forKeyPath:keyPath]; + } else { + //in this case most probably a custom property was defined in a model + //but no default reverse transformer for it + @throw [NSException exceptionWithName:@"Value transformer not found" + reason:[NSString stringWithFormat:@"[JSONValueTransformer %@] not found", selectorName] + userInfo:nil]; + return nil; + } + } + } + } + + return [tempDictionary copy]; +} + +//exports model to a dictionary and then to a JSON string +- (NSData *)toJSONDataWithKeys:(NSArray *)propertyNames +{ + NSData* jsonData = nil; + NSError* jsonError = nil; + + @try { + NSDictionary* dict = [self toDictionaryWithKeys:propertyNames]; + jsonData = [NSJSONSerialization dataWithJSONObject:dict options:kNilOptions error:&jsonError]; + } + @catch (NSException *exception) { + //this should not happen in properly design JSONModel + //usually means there was no reverse transformer for a custom property + JMLog(@"EXCEPTION: %@", exception.description); + return nil; + } + + return jsonData; +} + +- (NSString *)toJSONStringWithKeys:(NSArray *)propertyNames +{ + return [[NSString alloc] initWithData: [self toJSONDataWithKeys: propertyNames] + encoding: NSUTF8StringEncoding]; +} + +#pragma mark - import/export of lists +//loop over an NSArray of JSON objects and turn them into models ++(NSMutableArray*)arrayOfModelsFromDictionaries:(NSArray*)array +{ + return [self arrayOfModelsFromDictionaries:array error:nil]; +} + ++ (NSMutableArray *)arrayOfModelsFromData:(NSData *)data error:(NSError **)err +{ + id json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:err]; + if (!json || ![json isKindOfClass:[NSArray class]]) return nil; + + return [self arrayOfModelsFromDictionaries:json error:err]; +} + ++ (NSMutableArray *)arrayOfModelsFromString:(NSString *)string error:(NSError **)err +{ + return [self arrayOfModelsFromData:[string dataUsingEncoding:NSUTF8StringEncoding] error:err]; +} + +// Same as above, but with error reporting ++(NSMutableArray*)arrayOfModelsFromDictionaries:(NSArray*)array error:(NSError**)err +{ + //bail early + if (isNull(array)) return nil; + + //parse dictionaries to objects + NSMutableArray* list = [NSMutableArray arrayWithCapacity: [array count]]; + + for (id d in array) + { + if ([d isKindOfClass:NSDictionary.class]) + { + JSONModelError* initErr = nil; + id obj = [[self alloc] initWithDictionary:d error:&initErr]; + if (obj == nil) + { + // Propagate the error, including the array index as the key-path component + if((err != nil) && (initErr != nil)) + { + NSString* path = [NSString stringWithFormat:@"[%lu]", (unsigned long)list.count]; + *err = [initErr errorByPrependingKeyPathComponent:path]; + } + return nil; + } + + [list addObject: obj]; + } else if ([d isKindOfClass:NSArray.class]) + { + [list addObjectsFromArray:[self arrayOfModelsFromDictionaries:d error:err]]; + } else + { + // This is very bad + } + + } + + return list; +} + ++ (NSMutableDictionary *)dictionaryOfModelsFromString:(NSString *)string error:(NSError **)err +{ + return [self dictionaryOfModelsFromData:[string dataUsingEncoding:NSUTF8StringEncoding] error:err]; +} + ++ (NSMutableDictionary *)dictionaryOfModelsFromData:(NSData *)data error:(NSError **)err +{ + id json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:err]; + if (!json || ![json isKindOfClass:[NSDictionary class]]) return nil; + + return [self dictionaryOfModelsFromDictionary:json error:err]; +} + ++ (NSMutableDictionary *)dictionaryOfModelsFromDictionary:(NSDictionary *)dictionary error:(NSError **)err +{ + NSMutableDictionary *output = [NSMutableDictionary dictionaryWithCapacity:dictionary.count]; + + for (NSString *key in dictionary.allKeys) + { + id object = dictionary[key]; + + if ([object isKindOfClass:NSDictionary.class]) + { + id obj = [[self alloc] initWithDictionary:object error:err]; + if (obj == nil) return nil; + output[key] = obj; + } + else if ([object isKindOfClass:NSArray.class]) + { + id obj = [self arrayOfModelsFromDictionaries:object error:err]; + if (obj == nil) return nil; + output[key] = obj; + } + else + { + if (err) { + *err = [JSONModelError errorInvalidDataWithTypeMismatch:@"Only dictionaries and arrays are supported"]; + } + return nil; + } + } + + return output; +} + +//loop over NSArray of models and export them to JSON objects ++(NSMutableArray*)arrayOfDictionariesFromModels:(NSArray*)array +{ + //bail early + if (isNull(array)) return nil; + + //convert to dictionaries + NSMutableArray* list = [NSMutableArray arrayWithCapacity: [array count]]; + + for (id object in array) { + + id obj = [object toDictionary]; + if (!obj) return nil; + + [list addObject: obj]; + } + return list; +} + +//loop over NSArray of models and export them to JSON objects with specific properties ++(NSMutableArray*)arrayOfDictionariesFromModels:(NSArray*)array propertyNamesToExport:(NSArray*)propertyNamesToExport; +{ + //bail early + if (isNull(array)) return nil; + + //convert to dictionaries + NSMutableArray* list = [NSMutableArray arrayWithCapacity: [array count]]; + + for (id object in array) { + + id obj = [object toDictionaryWithKeys:propertyNamesToExport]; + if (!obj) return nil; + + [list addObject: obj]; + } + return list; +} + ++(NSMutableDictionary *)dictionaryOfDictionariesFromModels:(NSDictionary *)dictionary +{ + //bail early + if (isNull(dictionary)) return nil; + + NSMutableDictionary *output = [NSMutableDictionary dictionaryWithCapacity:dictionary.count]; + + for (NSString *key in dictionary.allKeys) { + id object = dictionary[key]; + id obj = [object toDictionary]; + if (!obj) return nil; + output[key] = obj; + } + + return output; +} + +#pragma mark - custom comparison methods + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +-(NSString*)indexPropertyName +{ + //custom getter for an associated object + return objc_getAssociatedObject(self.class, &kIndexPropertyNameKey); +} + +-(BOOL)isEqual:(id)object +{ + //bail early if different classes + if (![object isMemberOfClass:[self class]]) return NO; + + if (self.indexPropertyName) { + //there's a defined ID property + id objectId = [object valueForKey: self.indexPropertyName]; + return [[self valueForKey: self.indexPropertyName] isEqual:objectId]; + } + + //default isEqual implementation + return [super isEqual:object]; +} + +-(NSComparisonResult)compare:(id)object +{ + if (self.indexPropertyName) { + id objectId = [object valueForKey: self.indexPropertyName]; + if ([objectId respondsToSelector:@selector(compare:)]) { + return [[self valueForKey:self.indexPropertyName] compare:objectId]; + } + } + + //on purpose postponing the asserts for speed optimization + //these should not happen anyway in production conditions + NSAssert(self.indexPropertyName, @"Can't compare models with no property"); + NSAssert1(NO, @"The property of %@ is not comparable class.", [self class]); + return kNilOptions; +} + +- (NSUInteger)hash +{ + if (self.indexPropertyName) { + id val = [self valueForKey:self.indexPropertyName]; + + if (val) { + return [val hash]; + } + } + + return [super hash]; +} + +#pragma GCC diagnostic pop + +#pragma mark - custom data validation +-(BOOL)validate:(NSError**)error +{ + return YES; +} + +#pragma mark - custom recursive description +//custom description method for debugging purposes +-(NSString*)description +{ + NSMutableString* text = [NSMutableString stringWithFormat:@"<%@> \n", [self class]]; + + for (JSONModelClassProperty *p in [self __properties__]) { + + id value = ([p.name isEqualToString:@"description"])?self->_description:[self valueForKey:p.name]; + NSString* valueDescription = (value)?[value description]:@""; + + if (p.isStandardJSONType && ![value respondsToSelector:@selector(count)] && [valueDescription length]>60) { + + //cap description for longer values + valueDescription = [NSString stringWithFormat:@"%@...", [valueDescription substringToIndex:59]]; + } + valueDescription = [valueDescription stringByReplacingOccurrencesOfString:@"\n" withString:@"\n "]; + [text appendFormat:@" [%@]: %@\n", p.name, valueDescription]; + } + + [text appendFormat:@"", [self class]]; + return text; +} + +#pragma mark - key mapping ++(JSONKeyMapper*)keyMapper +{ + return nil; +} + ++(void)setGlobalKeyMapper:(JSONKeyMapper*)globalKeyMapperParam +{ + globalKeyMapper = globalKeyMapperParam; +} + ++(BOOL)propertyIsOptional:(NSString*)propertyName +{ + return NO; +} + ++(BOOL)propertyIsIgnored:(NSString *)propertyName +{ + return NO; +} + ++(NSString*)protocolForArrayProperty:(NSString *)propertyName +{ + return nil; +} + ++(Class)classForCollectionProperty:(NSString *)propertyName +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + NSString *protocolName = [self protocolForArrayProperty:propertyName]; +#pragma GCC diagnostic pop + + if (!protocolName) + return nil; + + return NSClassFromString(protocolName); +} + +#pragma mark - working with incomplete models +- (void)mergeFromDictionary:(NSDictionary *)dict useKeyMapping:(BOOL)useKeyMapping +{ + [self mergeFromDictionary:dict useKeyMapping:useKeyMapping error:nil]; +} + +- (BOOL)mergeFromDictionary:(NSDictionary *)dict useKeyMapping:(BOOL)useKeyMapping error:(NSError **)error +{ + return [self __importDictionary:dict withKeyMapper:(useKeyMapping)? self.__keyMapper:nil validation:NO error:error]; +} + +#pragma mark - NSCopying, NSCoding +-(instancetype)copyWithZone:(NSZone *)zone +{ + return [NSKeyedUnarchiver unarchiveObjectWithData: + [NSKeyedArchiver archivedDataWithRootObject:self] + ]; +} + +-(instancetype)initWithCoder:(NSCoder *)decoder +{ + NSString* json; + + if ([decoder respondsToSelector:@selector(decodeObjectOfClass:forKey:)]) { + json = [decoder decodeObjectOfClass:[NSString class] forKey:@"json"]; + } else { + json = [decoder decodeObjectForKey:@"json"]; + } + + JSONModelError *error = nil; + self = [self initWithString:json error:&error]; + if (error) { + JMLog(@"%@",[error localizedDescription]); + } + return self; +} + +-(void)encodeWithCoder:(NSCoder *)encoder +{ + [encoder encodeObject:self.toJSONString forKey:@"json"]; +} + ++ (BOOL)supportsSecureCoding +{ + return YES; +} + +@end diff --git a/Pods/JSONModel/JSONModel/JSONModel/JSONModelClassProperty.h b/Pods/JSONModel/JSONModel/JSONModel/JSONModelClassProperty.h new file mode 100644 index 0000000..67405ab --- /dev/null +++ b/Pods/JSONModel/JSONModel/JSONModel/JSONModelClassProperty.h @@ -0,0 +1,48 @@ +// +// JSONModelClassProperty.h +// JSONModel +// + +#import + +/** + * **You do not need to instantiate this class yourself.** This class is used internally by JSONModel + * to inspect the declared properties of your model class. + * + * Class to contain the information, representing a class property + * It features the property's name, type, whether it's a required property, + * and (optionally) the class protocol + */ +@interface JSONModelClassProperty : NSObject + +// deprecated +@property (assign, nonatomic) BOOL isIndex DEPRECATED_ATTRIBUTE; + +/** The name of the declared property (not the ivar name) */ +@property (copy, nonatomic) NSString *name; + +/** A property class type */ +@property (assign, nonatomic) Class type; + +/** Struct name if a struct */ +@property (strong, nonatomic) NSString *structName; + +/** The name of the protocol the property conforms to (or nil) */ +@property (copy, nonatomic) NSString *protocol; + +/** If YES, it can be missing in the input data, and the input would be still valid */ +@property (assign, nonatomic) BOOL isOptional; + +/** If YES - don't call any transformers on this property's value */ +@property (assign, nonatomic) BOOL isStandardJSONType; + +/** If YES - create a mutable object for the value of the property */ +@property (assign, nonatomic) BOOL isMutable; + +/** a custom getter for this property, found in the owning model */ +@property (assign, nonatomic) SEL customGetter; + +/** custom setters for this property, found in the owning model */ +@property (strong, nonatomic) NSMutableDictionary *customSetters; + +@end diff --git a/Pods/JSONModel/JSONModel/JSONModel/JSONModelClassProperty.m b/Pods/JSONModel/JSONModel/JSONModel/JSONModelClassProperty.m new file mode 100644 index 0000000..5330c92 --- /dev/null +++ b/Pods/JSONModel/JSONModel/JSONModel/JSONModelClassProperty.m @@ -0,0 +1,53 @@ +// +// JSONModelClassProperty.m +// JSONModel +// + +#import "JSONModelClassProperty.h" + +@implementation JSONModelClassProperty + +-(NSString*)description +{ + //build the properties string for the current class property + NSMutableArray* properties = [NSMutableArray arrayWithCapacity:8]; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + if (self.isIndex) [properties addObject:@"Index"]; +#pragma GCC diagnostic pop + + if (self.isOptional) [properties addObject:@"Optional"]; + if (self.isMutable) [properties addObject:@"Mutable"]; + if (self.isStandardJSONType) [properties addObject:@"Standard JSON type"]; + if (self.customGetter) [properties addObject:[NSString stringWithFormat: @"Getter = %@", NSStringFromSelector(self.customGetter)]]; + + if (self.customSetters) + { + NSMutableArray *setters = [NSMutableArray array]; + + for (id obj in self.customSetters.allValues) + { + SEL selector; + [obj getValue:&selector]; + [setters addObject:NSStringFromSelector(selector)]; + } + + [properties addObject:[NSString stringWithFormat: @"Setters = [%@]", [setters componentsJoinedByString:@", "]]]; + } + + NSString* propertiesString = @""; + if (properties.count>0) { + propertiesString = [NSString stringWithFormat:@"(%@)", [properties componentsJoinedByString:@", "]]; + } + + //return the name, type and additional properties + return [NSString stringWithFormat:@"@property %@%@ %@ %@", + self.type?[NSString stringWithFormat:@"%@*",self.type]:(self.structName?self.structName:@"primitive"), + self.protocol?[NSString stringWithFormat:@"<%@>", self.protocol]:@"", + self.name, + propertiesString + ]; +} + +@end diff --git a/Pods/JSONModel/JSONModel/JSONModel/JSONModelError.h b/Pods/JSONModel/JSONModel/JSONModel/JSONModelError.h new file mode 100644 index 0000000..266e6cc --- /dev/null +++ b/Pods/JSONModel/JSONModel/JSONModel/JSONModelError.h @@ -0,0 +1,103 @@ +// +// JSONModelError.h +// JSONModel +// + +#import + +///////////////////////////////////////////////////////////////////////////////////////////// +typedef NS_ENUM(int, kJSONModelErrorTypes) +{ + kJSONModelErrorInvalidData = 1, + kJSONModelErrorBadResponse = 2, + kJSONModelErrorBadJSON = 3, + kJSONModelErrorModelIsInvalid = 4, + kJSONModelErrorNilInput = 5 +}; + +///////////////////////////////////////////////////////////////////////////////////////////// +/** The domain name used for the JSONModelError instances */ +extern NSString *const JSONModelErrorDomain; + +/** + * If the model JSON input misses keys that are required, check the + * userInfo dictionary of the JSONModelError instance you get back - + * under the kJSONModelMissingKeys key you will find a list of the + * names of the missing keys. + */ +extern NSString *const kJSONModelMissingKeys; + +/** + * If JSON input has a different type than expected by the model, check the + * userInfo dictionary of the JSONModelError instance you get back - + * under the kJSONModelTypeMismatch key you will find a description + * of the mismatched types. + */ +extern NSString *const kJSONModelTypeMismatch; + +/** + * If an error occurs in a nested model, check the userInfo dictionary of + * the JSONModelError instance you get back - under the kJSONModelKeyPath + * key you will find key-path at which the error occurred. + */ +extern NSString *const kJSONModelKeyPath; + +///////////////////////////////////////////////////////////////////////////////////////////// +/** + * Custom NSError subclass with shortcut methods for creating + * the common JSONModel errors + */ +@interface JSONModelError : NSError + +@property (strong, nonatomic) NSHTTPURLResponse *httpResponse; + +@property (strong, nonatomic) NSData *responseData; + +/** + * Creates a JSONModelError instance with code kJSONModelErrorInvalidData = 1 + */ ++ (id)errorInvalidDataWithMessage:(NSString *)message; + +/** + * Creates a JSONModelError instance with code kJSONModelErrorInvalidData = 1 + * @param keys a set of field names that were required, but not found in the input + */ ++ (id)errorInvalidDataWithMissingKeys:(NSSet *)keys; + +/** + * Creates a JSONModelError instance with code kJSONModelErrorInvalidData = 1 + * @param mismatchDescription description of the type mismatch that was encountered. + */ ++ (id)errorInvalidDataWithTypeMismatch:(NSString *)mismatchDescription; + +/** + * Creates a JSONModelError instance with code kJSONModelErrorBadResponse = 2 + */ ++ (id)errorBadResponse; + +/** + * Creates a JSONModelError instance with code kJSONModelErrorBadJSON = 3 + */ ++ (id)errorBadJSON; + +/** + * Creates a JSONModelError instance with code kJSONModelErrorModelIsInvalid = 4 + */ ++ (id)errorModelIsInvalid; + +/** + * Creates a JSONModelError instance with code kJSONModelErrorNilInput = 5 + */ ++ (id)errorInputIsNil; + +/** + * Creates a new JSONModelError with the same values plus information about the key-path of the error. + * Properties in the new error object are the same as those from the receiver, + * except that a new key kJSONModelKeyPath is added to the userInfo dictionary. + * This key contains the component string parameter. If the key is already present + * then the new error object has the component string prepended to the existing value. + */ +- (instancetype)errorByPrependingKeyPathComponent:(NSString *)component; + +///////////////////////////////////////////////////////////////////////////////////////////// +@end diff --git a/Pods/JSONModel/JSONModel/JSONModel/JSONModelError.m b/Pods/JSONModel/JSONModel/JSONModel/JSONModelError.m new file mode 100644 index 0000000..f357e70 --- /dev/null +++ b/Pods/JSONModel/JSONModel/JSONModel/JSONModelError.m @@ -0,0 +1,82 @@ +// +// JSONModelError.m +// JSONModel +// + +#import "JSONModelError.h" + +NSString* const JSONModelErrorDomain = @"JSONModelErrorDomain"; +NSString* const kJSONModelMissingKeys = @"kJSONModelMissingKeys"; +NSString* const kJSONModelTypeMismatch = @"kJSONModelTypeMismatch"; +NSString* const kJSONModelKeyPath = @"kJSONModelKeyPath"; + +@implementation JSONModelError + ++(id)errorInvalidDataWithMessage:(NSString*)message +{ + message = [NSString stringWithFormat:@"Invalid JSON data: %@", message]; + return [JSONModelError errorWithDomain:JSONModelErrorDomain + code:kJSONModelErrorInvalidData + userInfo:@{NSLocalizedDescriptionKey:message}]; +} + ++(id)errorInvalidDataWithMissingKeys:(NSSet *)keys +{ + return [JSONModelError errorWithDomain:JSONModelErrorDomain + code:kJSONModelErrorInvalidData + userInfo:@{NSLocalizedDescriptionKey:@"Invalid JSON data. Required JSON keys are missing from the input. Check the error user information.",kJSONModelMissingKeys:[keys allObjects]}]; +} + ++(id)errorInvalidDataWithTypeMismatch:(NSString*)mismatchDescription +{ + return [JSONModelError errorWithDomain:JSONModelErrorDomain + code:kJSONModelErrorInvalidData + userInfo:@{NSLocalizedDescriptionKey:@"Invalid JSON data. The JSON type mismatches the expected type. Check the error user information.",kJSONModelTypeMismatch:mismatchDescription}]; +} + ++(id)errorBadResponse +{ + return [JSONModelError errorWithDomain:JSONModelErrorDomain + code:kJSONModelErrorBadResponse + userInfo:@{NSLocalizedDescriptionKey:@"Bad network response. Probably the JSON URL is unreachable."}]; +} + ++(id)errorBadJSON +{ + return [JSONModelError errorWithDomain:JSONModelErrorDomain + code:kJSONModelErrorBadJSON + userInfo:@{NSLocalizedDescriptionKey:@"Malformed JSON. Check the JSONModel data input."}]; +} + ++(id)errorModelIsInvalid +{ + return [JSONModelError errorWithDomain:JSONModelErrorDomain + code:kJSONModelErrorModelIsInvalid + userInfo:@{NSLocalizedDescriptionKey:@"Model does not validate. The custom validation for the input data failed."}]; +} + ++(id)errorInputIsNil +{ + return [JSONModelError errorWithDomain:JSONModelErrorDomain + code:kJSONModelErrorNilInput + userInfo:@{NSLocalizedDescriptionKey:@"Initializing model with nil input object."}]; +} + +- (instancetype)errorByPrependingKeyPathComponent:(NSString*)component +{ + // Create a mutable copy of the user info so that we can add to it and update it + NSMutableDictionary* userInfo = [self.userInfo mutableCopy]; + + // Create or update the key-path + NSString* existingPath = userInfo[kJSONModelKeyPath]; + NSString* separator = [existingPath hasPrefix:@"["] ? @"" : @"."; + NSString* updatedPath = (existingPath == nil) ? component : [component stringByAppendingFormat:@"%@%@", separator, existingPath]; + userInfo[kJSONModelKeyPath] = updatedPath; + + // Create the new error + return [JSONModelError errorWithDomain:self.domain + code:self.code + userInfo:[NSDictionary dictionaryWithDictionary:userInfo]]; +} + +@end diff --git a/Pods/JSONModel/JSONModel/JSONModelLib.h b/Pods/JSONModel/JSONModel/JSONModelLib.h new file mode 100644 index 0000000..564ca46 --- /dev/null +++ b/Pods/JSONModel/JSONModel/JSONModelLib.h @@ -0,0 +1,19 @@ +// +// JSONModelLib.h +// JSONModel +// + +#import + +// core +#import "JSONModel.h" +#import "JSONModelError.h" + +// transformations +#import "JSONValueTransformer.h" +#import "JSONKeyMapper.h" + +// networking (deprecated) +#import "JSONHTTPClient.h" +#import "JSONModel+networking.h" +#import "JSONAPI.h" diff --git a/Pods/JSONModel/JSONModel/JSONModelNetworking/JSONAPI.h b/Pods/JSONModel/JSONModel/JSONModelNetworking/JSONAPI.h new file mode 100644 index 0000000..30a8743 --- /dev/null +++ b/Pods/JSONModel/JSONModel/JSONModelNetworking/JSONAPI.h @@ -0,0 +1,19 @@ +// +// JSONAPI.h +// JSONModel +// + +#import +#import "JSONHTTPClient.h" + +DEPRECATED_ATTRIBUTE +@interface JSONAPI : NSObject + ++ (void)setAPIBaseURLWithString:(NSString *)base DEPRECATED_ATTRIBUTE; ++ (void)setContentType:(NSString *)ctype DEPRECATED_ATTRIBUTE; ++ (void)getWithPath:(NSString *)path andParams:(NSDictionary *)params completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE; ++ (void)postWithPath:(NSString *)path andParams:(NSDictionary *)params completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE; ++ (void)rpcWithMethodName:(NSString *)method andArguments:(NSArray *)args completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE; ++ (void)rpc2WithMethodName:(NSString *)method andParams:(id)params completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE; + +@end diff --git a/Pods/JSONModel/JSONModel/JSONModelNetworking/JSONAPI.m b/Pods/JSONModel/JSONModel/JSONModelNetworking/JSONAPI.m new file mode 100644 index 0000000..a7e3326 --- /dev/null +++ b/Pods/JSONModel/JSONModel/JSONModelNetworking/JSONAPI.m @@ -0,0 +1,145 @@ +// +// JSONAPI.m +// JSONModel +// + +#import "JSONAPI.h" + +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#pragma GCC diagnostic ignored "-Wdeprecated-implementations" + +#pragma mark - helper error model class +@interface JSONAPIRPCErrorModel: JSONModel +@property (assign, nonatomic) int code; +@property (strong, nonatomic) NSString* message; +@property (strong, nonatomic) id data; +@end + +#pragma mark - static variables + +static JSONAPI* sharedInstance = nil; + +static long jsonRpcId = 0; + +#pragma mark - JSONAPI() private interface + +@interface JSONAPI () +@property (strong, nonatomic) NSString* baseURLString; +@end + +#pragma mark - JSONAPI implementation + +@implementation JSONAPI + +#pragma mark - initialize + ++(void)initialize +{ + static dispatch_once_t once; + dispatch_once(&once, ^{ + sharedInstance = [[JSONAPI alloc] init]; + }); +} + +#pragma mark - api config methods + ++(void)setAPIBaseURLWithString:(NSString*)base +{ + sharedInstance.baseURLString = base; +} + ++(void)setContentType:(NSString*)ctype +{ + [JSONHTTPClient setRequestContentType: ctype]; +} + +#pragma mark - GET methods ++(void)getWithPath:(NSString*)path andParams:(NSDictionary*)params completion:(JSONObjectBlock)completeBlock +{ + NSString* fullURL = [NSString stringWithFormat:@"%@%@", sharedInstance.baseURLString, path]; + + [JSONHTTPClient getJSONFromURLWithString: fullURL params:params completion:^(NSDictionary *json, JSONModelError *e) { + completeBlock(json, e); + }]; +} + +#pragma mark - POST methods ++(void)postWithPath:(NSString*)path andParams:(NSDictionary*)params completion:(JSONObjectBlock)completeBlock +{ + NSString* fullURL = [NSString stringWithFormat:@"%@%@", sharedInstance.baseURLString, path]; + + [JSONHTTPClient postJSONFromURLWithString: fullURL params:params completion:^(NSDictionary *json, JSONModelError *e) { + completeBlock(json, e); + }]; +} + +#pragma mark - RPC methods ++(void)__rpcRequestWithObject:(id)jsonObject completion:(JSONObjectBlock)completeBlock +{ + + NSData* jsonRequestData = [NSJSONSerialization dataWithJSONObject:jsonObject + options:kNilOptions + error:nil]; + NSString* jsonRequestString = [[NSString alloc] initWithData:jsonRequestData encoding: NSUTF8StringEncoding]; + + NSAssert(sharedInstance.baseURLString, @"API base URL not set"); + [JSONHTTPClient postJSONFromURLWithString: sharedInstance.baseURLString + bodyString: jsonRequestString + completion:^(NSDictionary *json, JSONModelError* e) { + + if (completeBlock) { + //handle the rpc response + NSDictionary* result = json[@"result"]; + + if (!result) { + JSONAPIRPCErrorModel* error = [[JSONAPIRPCErrorModel alloc] initWithDictionary:json[@"error"] error:nil]; + if (error) { + //custom server error + if (!error.message) error.message = @"Generic json rpc error"; + e = [JSONModelError errorWithDomain:JSONModelErrorDomain + code:error.code + userInfo: @{ NSLocalizedDescriptionKey : error.message}]; + } else { + //generic error + e = [JSONModelError errorBadResponse]; + } + } + + //invoke the callback + completeBlock(result, e); + } + }]; +} + ++(void)rpcWithMethodName:(NSString*)method andArguments:(NSArray*)args completion:(JSONObjectBlock)completeBlock +{ + NSAssert(method, @"No method specified"); + if (!args) args = @[]; + + [self __rpcRequestWithObject:@{ + //rpc 1.0 + @"id": @(++jsonRpcId), + @"params": args, + @"method": method + } completion:completeBlock]; +} + ++(void)rpc2WithMethodName:(NSString*)method andParams:(id)params completion:(JSONObjectBlock)completeBlock +{ + NSAssert(method, @"No method specified"); + if (!params) params = @[]; + + [self __rpcRequestWithObject:@{ + //rpc 2.0 + @"jsonrpc": @"2.0", + @"id": @(++jsonRpcId), + @"params": params, + @"method": method + } completion:completeBlock]; +} + +@end + +#pragma mark - helper rpc error model class implementation +@implementation JSONAPIRPCErrorModel +@end diff --git a/Pods/JSONModel/JSONModel/JSONModelNetworking/JSONHTTPClient.h b/Pods/JSONModel/JSONModel/JSONModelNetworking/JSONHTTPClient.h new file mode 100644 index 0000000..0f47cef --- /dev/null +++ b/Pods/JSONModel/JSONModel/JSONModelNetworking/JSONHTTPClient.h @@ -0,0 +1,33 @@ +// +// JSONModelHTTPClient.h +// JSONModel +// + +#import "JSONModel.h" + +extern NSString *const kHTTPMethodGET DEPRECATED_ATTRIBUTE; +extern NSString *const kHTTPMethodPOST DEPRECATED_ATTRIBUTE; +extern NSString *const kContentTypeAutomatic DEPRECATED_ATTRIBUTE; +extern NSString *const kContentTypeJSON DEPRECATED_ATTRIBUTE; +extern NSString *const kContentTypeWWWEncoded DEPRECATED_ATTRIBUTE; + +typedef void (^JSONObjectBlock)(id json, JSONModelError *err) DEPRECATED_ATTRIBUTE; + +DEPRECATED_ATTRIBUTE +@interface JSONHTTPClient : NSObject + ++ (NSMutableDictionary *)requestHeaders DEPRECATED_ATTRIBUTE; ++ (void)setDefaultTextEncoding:(NSStringEncoding)encoding DEPRECATED_ATTRIBUTE; ++ (void)setCachingPolicy:(NSURLRequestCachePolicy)policy DEPRECATED_ATTRIBUTE; ++ (void)setTimeoutInSeconds:(int)seconds DEPRECATED_ATTRIBUTE; ++ (void)setRequestContentType:(NSString *)contentTypeString DEPRECATED_ATTRIBUTE; ++ (void)getJSONFromURLWithString:(NSString *)urlString completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE; ++ (void)getJSONFromURLWithString:(NSString *)urlString params:(NSDictionary *)params completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE; ++ (void)JSONFromURLWithString:(NSString *)urlString method:(NSString *)method params:(NSDictionary *)params orBodyString:(NSString *)bodyString completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE; ++ (void)JSONFromURLWithString:(NSString *)urlString method:(NSString *)method params:(NSDictionary *)params orBodyString:(NSString *)bodyString headers:(NSDictionary *)headers completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE; ++ (void)JSONFromURLWithString:(NSString *)urlString method:(NSString *)method params:(NSDictionary *)params orBodyData:(NSData *)bodyData headers:(NSDictionary *)headers completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE; ++ (void)postJSONFromURLWithString:(NSString *)urlString params:(NSDictionary *)params completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE; ++ (void)postJSONFromURLWithString:(NSString *)urlString bodyString:(NSString *)bodyString completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE; ++ (void)postJSONFromURLWithString:(NSString *)urlString bodyData:(NSData *)bodyData completion:(JSONObjectBlock)completeBlock DEPRECATED_ATTRIBUTE; + +@end diff --git a/Pods/JSONModel/JSONModel/JSONModelNetworking/JSONHTTPClient.m b/Pods/JSONModel/JSONModel/JSONModelNetworking/JSONHTTPClient.m new file mode 100644 index 0000000..6c72dc5 --- /dev/null +++ b/Pods/JSONModel/JSONModel/JSONModelNetworking/JSONHTTPClient.m @@ -0,0 +1,361 @@ +// +// JSONModelHTTPClient.m +// JSONModel +// + +#import "JSONHTTPClient.h" + +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#pragma GCC diagnostic ignored "-Wdeprecated-implementations" + +typedef void (^RequestResultBlock)(NSData *data, JSONModelError *error); + +#pragma mark - constants +NSString* const kHTTPMethodGET = @"GET"; +NSString* const kHTTPMethodPOST = @"POST"; + +NSString* const kContentTypeAutomatic = @"jsonmodel/automatic"; +NSString* const kContentTypeJSON = @"application/json"; +NSString* const kContentTypeWWWEncoded = @"application/x-www-form-urlencoded"; + +#pragma mark - static variables + +/** + * Defaults for HTTP requests + */ +static NSStringEncoding defaultTextEncoding = NSUTF8StringEncoding; +static NSURLRequestCachePolicy defaultCachePolicy = NSURLRequestReloadIgnoringLocalCacheData; + +static int defaultTimeoutInSeconds = 60; + +/** + * Custom HTTP headers to send over with *each* request + */ +static NSMutableDictionary* requestHeaders = nil; + +/** + * Default request content type + */ +static NSString* requestContentType = nil; + +#pragma mark - implementation +@implementation JSONHTTPClient + +#pragma mark - initialization ++(void)initialize +{ + static dispatch_once_t once; + dispatch_once(&once, ^{ + requestHeaders = [NSMutableDictionary dictionary]; + requestContentType = kContentTypeAutomatic; + }); +} + +#pragma mark - configuration methods ++(NSMutableDictionary*)requestHeaders +{ + return requestHeaders; +} + ++(void)setDefaultTextEncoding:(NSStringEncoding)encoding +{ + defaultTextEncoding = encoding; +} + ++(void)setCachingPolicy:(NSURLRequestCachePolicy)policy +{ + defaultCachePolicy = policy; +} + ++(void)setTimeoutInSeconds:(int)seconds +{ + defaultTimeoutInSeconds = seconds; +} + ++(void)setRequestContentType:(NSString*)contentTypeString +{ + requestContentType = contentTypeString; +} + +#pragma mark - helper methods ++(NSString*)contentTypeForRequestString:(NSString*)requestString +{ + //fetch the charset name from the default string encoding + NSString* contentType = requestContentType; + + if (requestString.length>0 && [contentType isEqualToString:kContentTypeAutomatic]) { + //check for "eventual" JSON array or dictionary + NSString* firstAndLastChar = [NSString stringWithFormat:@"%@%@", + [requestString substringToIndex:1], + [requestString substringFromIndex: requestString.length -1] + ]; + + if ([firstAndLastChar isEqualToString:@"{}"] || [firstAndLastChar isEqualToString:@"[]"]) { + //guessing for a JSON request + contentType = kContentTypeJSON; + } else { + //fallback to www form encoded params + contentType = kContentTypeWWWEncoded; + } + } + + //type is set, just add charset + NSString *charset = (NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)); + return [NSString stringWithFormat:@"%@; charset=%@", contentType, charset]; +} + ++(NSString*)urlEncode:(id)value +{ + //make sure param is a string + if ([value isKindOfClass:[NSNumber class]]) { + value = [(NSNumber*)value stringValue]; + } + + NSAssert([value isKindOfClass:[NSString class]], @"request parameters can be only of NSString or NSNumber classes. '%@' is of class %@.", value, [value class]); + + NSString *str = (NSString *)value; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0 || __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_9 + return [str stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; + +#else + return (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes( + NULL, + (__bridge CFStringRef)str, + NULL, + (CFStringRef)@"!*'();:@&=+$,/?%#[]", + kCFStringEncodingUTF8)); +#endif +} + +#pragma mark - networking worker methods ++(void)requestDataFromURL:(NSURL*)url method:(NSString*)method requestBody:(NSData*)bodyData headers:(NSDictionary*)headers handler:(RequestResultBlock)handler +{ + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: url + cachePolicy: defaultCachePolicy + timeoutInterval: defaultTimeoutInSeconds]; + [request setHTTPMethod:method]; + + if ([requestContentType isEqualToString:kContentTypeAutomatic]) { + //automatic content type + if (bodyData) { + NSString *bodyString = [[NSString alloc] initWithData:bodyData encoding:NSUTF8StringEncoding]; + [request setValue: [self contentTypeForRequestString: bodyString] forHTTPHeaderField:@"Content-type"]; + } + } else { + //user set content type + [request setValue: requestContentType forHTTPHeaderField:@"Content-type"]; + } + + //add all the custom headers defined + for (NSString* key in [requestHeaders allKeys]) { + [request setValue:requestHeaders[key] forHTTPHeaderField:key]; + } + + //add the custom headers + for (NSString* key in [headers allKeys]) { + [request setValue:headers[key] forHTTPHeaderField:key]; + } + + if (bodyData) { + [request setHTTPBody: bodyData]; + [request setValue:[NSString stringWithFormat:@"%lu", (unsigned long)bodyData.length] forHTTPHeaderField:@"Content-Length"]; + } + + void (^completionHandler)(NSData *, NSURLResponse *, NSError *) = ^(NSData *data, NSURLResponse *origResponse, NSError *origError) { + NSHTTPURLResponse *response = (NSHTTPURLResponse *)origResponse; + JSONModelError *error = nil; + + //convert an NSError to a JSONModelError + if (origError) { + error = [JSONModelError errorWithDomain:origError.domain code:origError.code userInfo:origError.userInfo]; + } + + //special case for http error code 401 + if (error.code == NSURLErrorUserCancelledAuthentication) { + response = [[NSHTTPURLResponse alloc] initWithURL:url statusCode:401 HTTPVersion:@"HTTP/1.1" headerFields:@{}]; + } + + //if not OK status set the err to a JSONModelError instance + if (!error && (response.statusCode >= 300 || response.statusCode < 200)) { + error = [JSONModelError errorBadResponse]; + } + + //if there was an error, assign the response to the JSONModel instance + if (error) { + error.httpResponse = [response copy]; + } + + //empty respone, return nil instead + if (!data.length) { + data = nil; + } + + handler(data, error); + }; + + //fire the request + +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0 || __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_10 + NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:completionHandler]; + [task resume]; +#else + NSOperationQueue *queue = [NSOperationQueue new]; + + [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { + completionHandler(data, response, error); + }]; +#endif +} + ++(void)requestDataFromURL:(NSURL*)url method:(NSString*)method params:(NSDictionary*)params headers:(NSDictionary*)headers handler:(RequestResultBlock)handler +{ + //create the request body + NSMutableString* paramsString = nil; + + if (params) { + //build a simple url encoded param string + paramsString = [NSMutableString stringWithString:@""]; + for (NSString* key in [[params allKeys] sortedArrayUsingSelector:@selector(compare:)]) { + [paramsString appendFormat:@"%@=%@&", key, [self urlEncode:params[key]] ]; + } + if ([paramsString hasSuffix:@"&"]) { + paramsString = [[NSMutableString alloc] initWithString: [paramsString substringToIndex: paramsString.length-1]]; + } + } + + //set the request params + if ([method isEqualToString:kHTTPMethodGET] && params) { + + //add GET params to the query string + url = [NSURL URLWithString:[NSString stringWithFormat: @"%@%@%@", + [url absoluteString], + [url query] ? @"&" : @"?", + paramsString + ]]; + } + + //call the more general synq request method + [self requestDataFromURL: url + method: method + requestBody: [method isEqualToString:kHTTPMethodPOST]?[paramsString dataUsingEncoding:NSUTF8StringEncoding]:nil + headers: headers + handler:handler]; +} + +#pragma mark - Async network request ++(void)JSONFromURLWithString:(NSString*)urlString method:(NSString*)method params:(NSDictionary*)params orBodyString:(NSString*)bodyString completion:(JSONObjectBlock)completeBlock +{ + [self JSONFromURLWithString:urlString + method:method + params:params + orBodyString:bodyString + headers:nil + completion:completeBlock]; +} + ++(void)JSONFromURLWithString:(NSString *)urlString method:(NSString *)method params:(NSDictionary *)params orBodyString:(NSString *)bodyString headers:(NSDictionary *)headers completion:(JSONObjectBlock)completeBlock +{ + [self JSONFromURLWithString:urlString + method:method + params:params + orBodyData:[bodyString dataUsingEncoding:NSUTF8StringEncoding] + headers:headers + completion:completeBlock]; +} + ++(void)JSONFromURLWithString:(NSString*)urlString method:(NSString*)method params:(NSDictionary *)params orBodyData:(NSData*)bodyData headers:(NSDictionary*)headers completion:(JSONObjectBlock)completeBlock +{ + RequestResultBlock handler = ^(NSData *responseData, JSONModelError *error) { + id jsonObject = nil; + + //step 3: if there's no response so far, return a basic error + if (!responseData && !error) { + //check for false response, but no network error + error = [JSONModelError errorBadResponse]; + } + + //step 4: if there's a response at this and no errors, convert to object + if (error==nil) { + // Note: it is possible to have a valid response with empty response data (204 No Content). + // So only create the JSON object if there is some response data. + if(responseData.length > 0) + { + //convert to an object + jsonObject = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error]; + } + } + //step 4.5: cover an edge case in which meaningful content is return along an error HTTP status code + else if (error && responseData && jsonObject==nil) { + //try to get the JSON object, while preserving the original error object + jsonObject = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:nil]; + //keep responseData just in case it contains error information + error.responseData = responseData; + } + + //step 5: invoke the complete block + dispatch_async(dispatch_get_main_queue(), ^{ + if (completeBlock) { + completeBlock(jsonObject, error); + } + }); + }; + + NSURL *url = [NSURL URLWithString:urlString]; + + if (bodyData) { + [self requestDataFromURL:url method:method requestBody:bodyData headers:headers handler:handler]; + } else { + [self requestDataFromURL:url method:method params:params headers:headers handler:handler]; + } +} + +#pragma mark - request aliases ++(void)getJSONFromURLWithString:(NSString*)urlString completion:(JSONObjectBlock)completeBlock +{ + [self JSONFromURLWithString:urlString method:kHTTPMethodGET + params:nil + orBodyString:nil completion:^(id json, JSONModelError* e) { + if (completeBlock) completeBlock(json, e); + }]; +} + ++(void)getJSONFromURLWithString:(NSString*)urlString params:(NSDictionary*)params completion:(JSONObjectBlock)completeBlock +{ + [self JSONFromURLWithString:urlString method:kHTTPMethodGET + params:params + orBodyString:nil completion:^(id json, JSONModelError* e) { + if (completeBlock) completeBlock(json, e); + }]; +} + ++(void)postJSONFromURLWithString:(NSString*)urlString params:(NSDictionary*)params completion:(JSONObjectBlock)completeBlock +{ + [self JSONFromURLWithString:urlString method:kHTTPMethodPOST + params:params + orBodyString:nil completion:^(id json, JSONModelError* e) { + if (completeBlock) completeBlock(json, e); + }]; + +} + ++(void)postJSONFromURLWithString:(NSString*)urlString bodyString:(NSString*)bodyString completion:(JSONObjectBlock)completeBlock +{ + [self JSONFromURLWithString:urlString method:kHTTPMethodPOST + params:nil + orBodyString:bodyString completion:^(id json, JSONModelError* e) { + if (completeBlock) completeBlock(json, e); + }]; +} + ++(void)postJSONFromURLWithString:(NSString*)urlString bodyData:(NSData*)bodyData completion:(JSONObjectBlock)completeBlock +{ + [self JSONFromURLWithString:urlString method:kHTTPMethodPOST + params:nil + orBodyString:[[NSString alloc] initWithData:bodyData encoding:defaultTextEncoding] + completion:^(id json, JSONModelError* e) { + if (completeBlock) completeBlock(json, e); + }]; +} + +@end diff --git a/Pods/JSONModel/JSONModel/JSONModelNetworking/JSONModel+networking.h b/Pods/JSONModel/JSONModel/JSONModelNetworking/JSONModel+networking.h new file mode 100644 index 0000000..444f26d --- /dev/null +++ b/Pods/JSONModel/JSONModel/JSONModelNetworking/JSONModel+networking.h @@ -0,0 +1,18 @@ +// +// JSONModel+networking.h +// JSONModel +// + +#import "JSONModel.h" +#import "JSONHTTPClient.h" + +typedef void (^JSONModelBlock)(id model, JSONModelError *err) DEPRECATED_ATTRIBUTE; + +@interface JSONModel (Networking) + +@property (assign, nonatomic) BOOL isLoading DEPRECATED_ATTRIBUTE; +- (instancetype)initFromURLWithString:(NSString *)urlString completion:(JSONModelBlock)completeBlock DEPRECATED_ATTRIBUTE; ++ (void)getModelFromURLWithString:(NSString *)urlString completion:(JSONModelBlock)completeBlock DEPRECATED_ATTRIBUTE; ++ (void)postModel:(JSONModel *)post toURLWithString:(NSString *)urlString completion:(JSONModelBlock)completeBlock DEPRECATED_ATTRIBUTE; + +@end diff --git a/Pods/JSONModel/JSONModel/JSONModelNetworking/JSONModel+networking.m b/Pods/JSONModel/JSONModel/JSONModelNetworking/JSONModel+networking.m new file mode 100644 index 0000000..b3e0aa4 --- /dev/null +++ b/Pods/JSONModel/JSONModel/JSONModelNetworking/JSONModel+networking.m @@ -0,0 +1,101 @@ +// +// JSONModel+networking.m +// JSONModel +// + +#import "JSONModel+networking.h" +#import "JSONHTTPClient.h" + +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#pragma GCC diagnostic ignored "-Wdeprecated-implementations" + +BOOL _isLoading; + +@implementation JSONModel(Networking) + +@dynamic isLoading; + +-(BOOL)isLoading +{ + return _isLoading; +} + +-(void)setIsLoading:(BOOL)isLoading +{ + _isLoading = isLoading; +} + +-(instancetype)initFromURLWithString:(NSString *)urlString completion:(JSONModelBlock)completeBlock +{ + id placeholder = [super init]; + __block id blockSelf = self; + + if (placeholder) { + //initialization + self.isLoading = YES; + + [JSONHTTPClient getJSONFromURLWithString:urlString + completion:^(NSDictionary *json, JSONModelError* e) { + + JSONModelError* initError = nil; + blockSelf = [self initWithDictionary:json error:&initError]; + + if (completeBlock) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_MSEC), dispatch_get_main_queue(), ^{ + completeBlock(blockSelf, e?e:initError ); + }); + } + + self.isLoading = NO; + + }]; + } + return placeholder; +} + ++ (void)getModelFromURLWithString:(NSString*)urlString completion:(JSONModelBlock)completeBlock +{ + [JSONHTTPClient getJSONFromURLWithString:urlString + completion:^(NSDictionary* jsonDict, JSONModelError* err) + { + JSONModel* model = nil; + + if(err == nil) + { + model = [[self alloc] initWithDictionary:jsonDict error:&err]; + } + + if(completeBlock != nil) + { + dispatch_async(dispatch_get_main_queue(), ^ + { + completeBlock(model, err); + }); + } + }]; +} + ++ (void)postModel:(JSONModel*)post toURLWithString:(NSString*)urlString completion:(JSONModelBlock)completeBlock +{ + [JSONHTTPClient postJSONFromURLWithString:urlString + bodyString:[post toJSONString] + completion:^(NSDictionary* jsonDict, JSONModelError* err) + { + JSONModel* model = nil; + + if(err == nil) + { + model = [[self alloc] initWithDictionary:jsonDict error:&err]; + } + + if(completeBlock != nil) + { + dispatch_async(dispatch_get_main_queue(), ^ + { + completeBlock(model, err); + }); + } + }]; +} + +@end diff --git a/Pods/JSONModel/JSONModel/JSONModelTransformations/JSONKeyMapper.h b/Pods/JSONModel/JSONModel/JSONModelTransformations/JSONKeyMapper.h new file mode 100644 index 0000000..61ea929 --- /dev/null +++ b/Pods/JSONModel/JSONModel/JSONModelTransformations/JSONKeyMapper.h @@ -0,0 +1,96 @@ +// +// JSONKeyMapper.h +// JSONModel +// + +#import + +typedef NSString *(^JSONModelKeyMapBlock)(NSString *keyName); + +/** + * **You won't need to create or store instances of this class yourself.** If you want your model + * to have different property names than the JSON feed keys, look below on how to + * make your model use a key mapper. + * + * For example if you consume JSON from twitter + * you get back underscore_case style key names. For example: + * + *
"profile_sidebar_border_color": "0094C2",
+ * "profile_background_tile": false,
+ * + * To comply with Obj-C accepted camelCase property naming for your classes, + * you need to provide mapping between JSON keys and ObjC property names. + * + * In your model overwrite the + (JSONKeyMapper *)keyMapper method and provide a JSONKeyMapper + * instance to convert the key names for your model. + * + * If you need custom mapping it's as easy as: + *
+ * + (JSONKeyMapper *)keyMapper {
+ *   return [[JSONKeyMapper alloc] initWithDictionary:@{@"crazy_JSON_name":@"myCamelCaseName"}];
+ * }
+ * 
+ * In case you want to handle underscore_case, **use the predefined key mapper**, like so: + *
+ * + (JSONKeyMapper *)keyMapper {
+ *   return [JSONKeyMapper mapperFromUnderscoreCaseToCamelCase];
+ * }
+ * 
+ */ +@interface JSONKeyMapper : NSObject + +// deprecated +@property (readonly, nonatomic) JSONModelKeyMapBlock JSONToModelKeyBlock DEPRECATED_ATTRIBUTE; +- (NSString *)convertValue:(NSString *)value isImportingToModel:(BOOL)importing DEPRECATED_MSG_ATTRIBUTE("use convertValue:"); +- (instancetype)initWithDictionary:(NSDictionary *)map DEPRECATED_MSG_ATTRIBUTE("use initWithModelToJSONDictionary:"); +- (instancetype)initWithJSONToModelBlock:(JSONModelKeyMapBlock)toModel modelToJSONBlock:(JSONModelKeyMapBlock)toJSON DEPRECATED_MSG_ATTRIBUTE("use initWithModelToJSONBlock:"); ++ (instancetype)mapper:(JSONKeyMapper *)baseKeyMapper withExceptions:(NSDictionary *)exceptions DEPRECATED_MSG_ATTRIBUTE("use baseMapper:withModelToJSONExceptions:"); ++ (instancetype)mapperFromUnderscoreCaseToCamelCase DEPRECATED_MSG_ATTRIBUTE("use mapperForSnakeCase:"); ++ (instancetype)mapperFromUpperCaseToLowerCase DEPRECATED_ATTRIBUTE; + +/** @name Name converters */ +/** Block, which takes in a property name and converts it to the corresponding JSON key name */ +@property (readonly, nonatomic) JSONModelKeyMapBlock modelToJSONKeyBlock; + +/** Combined converter method + * @param value the source name + * @return JSONKeyMapper instance + */ +- (NSString *)convertValue:(NSString *)value; + +/** @name Creating a key mapper */ + +/** + * Creates a JSONKeyMapper instance, based on the block you provide this initializer. + * The parameter takes in a JSONModelKeyMapBlock block: + *
NSString *(^JSONModelKeyMapBlock)(NSString *keyName)
+ * The block takes in a string and returns the transformed (if at all) string. + * @param toJSON transforms your model property name to a JSON key + */ +- (instancetype)initWithModelToJSONBlock:(JSONModelKeyMapBlock)toJSON; + +/** + * Creates a JSONKeyMapper instance, based on the mapping you provide. + * Use your JSONModel property names as keys, and the JSON key names as values. + * @param toJSON map dictionary, in the format:
@{@"myCamelCaseName":@"crazy_JSON_name"}
+ * @return JSONKeyMapper instance + */ +- (instancetype)initWithModelToJSONDictionary:(NSDictionary *)toJSON; + +/** + * Given a camelCase model property, this mapper finds JSON keys using the snake_case equivalent. + */ ++ (instancetype)mapperForSnakeCase; + +/** + * Given a camelCase model property, this mapper finds JSON keys using the TitleCase equivalent. + */ ++ (instancetype)mapperForTitleCase; + +/** + * Creates a JSONKeyMapper based on a built-in JSONKeyMapper, with specific exceptions. + * Use your JSONModel property names as keys, and the JSON key names as values. + */ ++ (instancetype)baseMapper:(JSONKeyMapper *)baseKeyMapper withModelToJSONExceptions:(NSDictionary *)toJSON; + +@end diff --git a/Pods/JSONModel/JSONModel/JSONModelTransformations/JSONKeyMapper.m b/Pods/JSONModel/JSONModel/JSONModelTransformations/JSONKeyMapper.m new file mode 100644 index 0000000..e1daa17 --- /dev/null +++ b/Pods/JSONModel/JSONModel/JSONModelTransformations/JSONKeyMapper.m @@ -0,0 +1,146 @@ +// +// JSONKeyMapper.m +// JSONModel +// + +#import "JSONKeyMapper.h" + +@implementation JSONKeyMapper + +- (instancetype)initWithJSONToModelBlock:(JSONModelKeyMapBlock)toModel modelToJSONBlock:(JSONModelKeyMapBlock)toJSON +{ + return [self initWithModelToJSONBlock:toJSON]; +} + +- (instancetype)initWithModelToJSONBlock:(JSONModelKeyMapBlock)toJSON +{ + if (!(self = [self init])) + return nil; + + _modelToJSONKeyBlock = toJSON; + + return self; +} + +- (instancetype)initWithDictionary:(NSDictionary *)map +{ + NSDictionary *toJSON = [JSONKeyMapper swapKeysAndValuesInDictionary:map]; + + return [self initWithModelToJSONDictionary:toJSON]; +} + +- (instancetype)initWithModelToJSONDictionary:(NSDictionary *)toJSON +{ + if (!(self = [super init])) + return nil; + + _modelToJSONKeyBlock = ^NSString *(NSString *keyName) + { + return [toJSON valueForKeyPath:keyName] ?: keyName; + }; + + return self; +} + +- (JSONModelKeyMapBlock)JSONToModelKeyBlock +{ + return nil; +} + ++ (NSDictionary *)swapKeysAndValuesInDictionary:(NSDictionary *)dictionary +{ + NSArray *keys = dictionary.allKeys; + NSArray *values = [dictionary objectsForKeys:keys notFoundMarker:[NSNull null]]; + + return [NSDictionary dictionaryWithObjects:keys forKeys:values]; +} + +- (NSString *)convertValue:(NSString *)value isImportingToModel:(BOOL)importing +{ + return [self convertValue:value]; +} + +- (NSString *)convertValue:(NSString *)value +{ + return _modelToJSONKeyBlock(value); +} + ++ (instancetype)mapperFromUnderscoreCaseToCamelCase +{ + return [self mapperForSnakeCase]; +} + ++ (instancetype)mapperForSnakeCase +{ + return [[self alloc] initWithModelToJSONBlock:^NSString *(NSString *keyName) + { + NSMutableString *result = [NSMutableString stringWithString:keyName]; + NSRange range; + + // handle upper case chars + range = [result rangeOfCharacterFromSet:[NSCharacterSet uppercaseLetterCharacterSet]]; + while (range.location != NSNotFound) + { + NSString *lower = [result substringWithRange:range].lowercaseString; + [result replaceCharactersInRange:range withString:[NSString stringWithFormat:@"_%@", lower]]; + range = [result rangeOfCharacterFromSet:[NSCharacterSet uppercaseLetterCharacterSet]]; + } + + // handle numbers + range = [result rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]]; + while (range.location != NSNotFound) + { + NSRange end = [result rangeOfString:@"\\D" options:NSRegularExpressionSearch range:NSMakeRange(range.location, result.length - range.location)]; + + // spans to the end of the key name + if (end.location == NSNotFound) + end = NSMakeRange(result.length, 1); + + NSRange replaceRange = NSMakeRange(range.location, end.location - range.location); + NSString *digits = [result substringWithRange:replaceRange]; + [result replaceCharactersInRange:replaceRange withString:[NSString stringWithFormat:@"_%@", digits]]; + range = [result rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet] options:0 range:NSMakeRange(end.location + 1, result.length - end.location - 1)]; + } + + return result; + }]; +} + ++ (instancetype)mapperForTitleCase +{ + return [[self alloc] initWithModelToJSONBlock:^NSString *(NSString *keyName) + { + return [keyName stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:[keyName substringToIndex:1].uppercaseString]; + }]; +} + ++ (instancetype)mapperFromUpperCaseToLowerCase +{ + return [[self alloc] initWithModelToJSONBlock:^NSString *(NSString *keyName) + { + return keyName.uppercaseString; + }]; +} + ++ (instancetype)mapper:(JSONKeyMapper *)baseKeyMapper withExceptions:(NSDictionary *)exceptions +{ + NSDictionary *toJSON = [JSONKeyMapper swapKeysAndValuesInDictionary:exceptions]; + + return [self baseMapper:baseKeyMapper withModelToJSONExceptions:toJSON]; +} + ++ (instancetype)baseMapper:(JSONKeyMapper *)baseKeyMapper withModelToJSONExceptions:(NSDictionary *)toJSON +{ + return [[self alloc] initWithModelToJSONBlock:^NSString *(NSString *keyName) + { + if (!keyName) + return nil; + + if (toJSON[keyName]) + return toJSON[keyName]; + + return baseKeyMapper.modelToJSONKeyBlock(keyName); + }]; +} + +@end diff --git a/Pods/JSONModel/JSONModel/JSONModelTransformations/JSONValueTransformer.h b/Pods/JSONModel/JSONModel/JSONModelTransformations/JSONValueTransformer.h new file mode 100644 index 0000000..7dd585c --- /dev/null +++ b/Pods/JSONModel/JSONModel/JSONModelTransformations/JSONValueTransformer.h @@ -0,0 +1,209 @@ +// +// JSONValueTransformer.h +// JSONModel +// + +#import + +///////////////////////////////////////////////////////////////////////////////////////////// + +#pragma mark - extern definitions +/** + * Boolean function to check for null values. Handy when you need to both check + * for nil and [NSNUll null] + */ +extern BOOL isNull(id value); + +///////////////////////////////////////////////////////////////////////////////////////////// + +#pragma mark - JSONValueTransformer interface +/** + * **You don't need to call methods of this class manually.** + * + * Class providing methods to transform values from one class to another. + * You are given a number of built-in transformers, but you are encouraged to + * extend this class with your own categories to add further value transformers. + * Just few examples of what can you add to JSONValueTransformer: hex colors in JSON to UIColor, + * hex numbers in JSON to NSNumber model properties, base64 encoded strings in JSON to UIImage properties, and more. + * + * The class is invoked by JSONModel while transforming incoming + * JSON types into your target class property classes, and vice versa. + * One static copy is create and store in the JSONModel class scope. + */ +@interface JSONValueTransformer : NSObject + +@property (strong, nonatomic, readonly) NSDictionary *primitivesNames; + +/** @name Resolving cluster class names */ +/** + * This method returns the umbrella class for any standard class cluster members. + * For example returns NSString when given as input NSString, NSMutableString, __CFString and __CFConstantString + * The method currently looksup a pre-defined list. + * @param sourceClass the class to get the umbrella class for + * @return Class + */ ++ (Class)classByResolvingClusterClasses:(Class)sourceClass; + +#pragma mark - NSMutableString <-> NSString +/** @name Transforming to Mutable copies */ +/** + * Transforms a string value to a mutable string value + * @param string incoming string + * @return mutable string + */ +- (NSMutableString *)NSMutableStringFromNSString:(NSString *)string; + +#pragma mark - NSMutableArray <-> NSArray +/** + * Transforms an array to a mutable array + * @param array incoming array + * @return mutable array + */ +- (NSMutableArray *)NSMutableArrayFromNSArray:(NSArray *)array; + +#pragma mark - NSMutableDictionary <-> NSDictionary +/** + * Transforms a dictionary to a mutable dictionary + * @param dict incoming dictionary + * @return mutable dictionary + */ +- (NSMutableDictionary *)NSMutableDictionaryFromNSDictionary:(NSDictionary *)dict; + +#pragma mark - NSSet <-> NSArray +/** @name Transforming Sets */ +/** + * Transforms an array to a set + * @param array incoming array + * @return set with the array's elements + */ +- (NSSet *)NSSetFromNSArray:(NSArray *)array; + +/** + * Transforms an array to a mutable set + * @param array incoming array + * @return mutable set with the array's elements + */ +- (NSMutableSet *)NSMutableSetFromNSArray:(NSArray *)array; + +/** + * Transforms a set to an array + * @param set incoming set + * @return an array with the set's elements + */ +- (NSArray *)JSONObjectFromNSSet:(NSSet *)set; + +/** + * Transforms a mutable set to an array + * @param set incoming mutable set + * @return an array with the set's elements + */ +- (NSArray *)JSONObjectFromNSMutableSet:(NSMutableSet *)set; + +#pragma mark - BOOL <-> number/string +/** @name Transforming JSON types */ +/** + * Transforms a number object to a bool number object + * @param number the number to convert + * @return the resulting number + */ +- (NSNumber *)BOOLFromNSNumber:(NSNumber *)number; + +/** + * Transforms a number object to a bool number object + * @param string the string value to convert, "0" converts to NO, everything else to YES + * @return the resulting number + */ +- (NSNumber *)BOOLFromNSString:(NSString *)string; + +/** + * Transforms a BOOL value to a bool number object + * @param number an NSNumber value coming from the model + * @return the result number + */ +- (NSNumber *)JSONObjectFromBOOL:(NSNumber *)number; + +#pragma mark - string <-> number +/** + * Transforms a string object to a number object + * @param string the string to convert + * @return the resulting number + */ +- (NSNumber *)NSNumberFromNSString:(NSString *)string; + +/** + * Transforms a number object to a string object + * @param number the number to convert + * @return the resulting string + */ +- (NSString *)NSStringFromNSNumber:(NSNumber *)number; + +/** + * Transforms a string object to a nsdecimalnumber object + * @param string the string to convert + * @return the resulting number + */ +- (NSDecimalNumber *)NSDecimalNumberFromNSString:(NSString *)string; + +/** + * Transforms a nsdecimalnumber object to a string object + * @param number the number to convert + * @return the resulting string + */ +- (NSString *)NSStringFromNSDecimalNumber:(NSDecimalNumber *)number; + + +#pragma mark - string <-> url +/** @name Transforming URLs */ +/** + * Transforms a string object to an NSURL object + * @param string the string to convert + * @return the resulting url object + */ +- (NSURL *)NSURLFromNSString:(NSString *)string; + +/** + * Transforms an NSURL object to a string + * @param url the url object to convert + * @return the resulting string + */ +- (NSString *)JSONObjectFromNSURL:(NSURL *)url; + +#pragma mark - string <-> time zone + +/** @name Transforming NSTimeZone */ +/** + * Transforms a string object to an NSTimeZone object + * @param string the string to convert + * @return the resulting NSTimeZone object + */ +- (NSTimeZone *)NSTimeZoneFromNSString:(NSString *)string; + +/** + * Transforms an NSTimeZone object to a string + * @param timeZone the time zone object to convert + * @return the resulting string + */ +- (NSString *)JSONObjectFromNSTimeZone:(NSTimeZone *)timeZone; + +#pragma mark - string <-> date +/** @name Transforming Dates */ +/** + * The following two methods are not public. This way if there is a category on converting + * dates it'll override them. If there isn't a category the default methods found in the .m + * file will be invoked. If these are public a warning is produced at the point of overriding + * them in a category, so they have to stay hidden here. + */ + +//- (NSDate *)NSDateFromNSString:(NSString *)string; +//- (NSString *)JSONObjectFromNSDate:(NSDate *)date; + +#pragma mark - number <-> date + +/** + * Transforms a number to an NSDate object + * @param number the number to convert + * @return the resulting date + */ +- (NSDate *)NSDateFromNSNumber:(NSNumber *)number; + +@end diff --git a/Pods/JSONModel/JSONModel/JSONModelTransformations/JSONValueTransformer.m b/Pods/JSONModel/JSONModel/JSONModelTransformations/JSONValueTransformer.m new file mode 100644 index 0000000..0fc5571 --- /dev/null +++ b/Pods/JSONModel/JSONModel/JSONModelTransformations/JSONValueTransformer.m @@ -0,0 +1,246 @@ +// +// JSONValueTransformer.m +// JSONModel +// + +#import "JSONValueTransformer.h" + +#pragma mark - functions +extern BOOL isNull(id value) +{ + if (!value) return YES; + if ([value isKindOfClass:[NSNull class]]) return YES; + + return NO; +} + +@implementation JSONValueTransformer + +-(id)init +{ + self = [super init]; + if (self) { + _primitivesNames = @{@"f":@"float", @"i":@"int", @"d":@"double", @"l":@"long", @"B":@"BOOL", @"s":@"short", + @"I":@"unsigned int", @"L":@"usigned long", @"q":@"long long", @"Q":@"unsigned long long", @"S":@"unsigned short", @"c":@"char", @"C":@"unsigned char", + //and some famous aliases of primitive types + // BOOL is now "B" on iOS __LP64 builds + @"I":@"NSInteger", @"Q":@"NSUInteger", @"B":@"BOOL", + + @"@?":@"Block"}; + } + return self; +} + ++(Class)classByResolvingClusterClasses:(Class)sourceClass +{ + //check for all variations of strings + if ([sourceClass isSubclassOfClass:[NSString class]]) { + return [NSString class]; + } + + //check for all variations of numbers + if ([sourceClass isSubclassOfClass:[NSNumber class]]) { + return [NSNumber class]; + } + + //check for all variations of dictionaries + if ([sourceClass isSubclassOfClass:[NSArray class]]) { + return [NSArray class]; + } + + //check for all variations of arrays + if ([sourceClass isSubclassOfClass:[NSDictionary class]]) { + return [NSDictionary class]; + } + + //check for all variations of dates + if ([sourceClass isSubclassOfClass:[NSDate class]]) { + return [NSDate class]; + } + + //no cluster parent class found + return sourceClass; +} + +#pragma mark - NSMutableString <-> NSString +-(NSMutableString*)NSMutableStringFromNSString:(NSString*)string +{ + return [NSMutableString stringWithString:string]; +} + +#pragma mark - NSMutableArray <-> NSArray +-(NSMutableArray*)NSMutableArrayFromNSArray:(NSArray*)array +{ + return [NSMutableArray arrayWithArray:array]; +} + +#pragma mark - NSMutableDictionary <-> NSDictionary +-(NSMutableDictionary*)NSMutableDictionaryFromNSDictionary:(NSDictionary*)dict +{ + return [NSMutableDictionary dictionaryWithDictionary:dict]; +} + +#pragma mark - NSSet <-> NSArray +-(NSSet*)NSSetFromNSArray:(NSArray*)array +{ + return [NSSet setWithArray:array]; +} + +-(NSMutableSet*)NSMutableSetFromNSArray:(NSArray*)array +{ + return [NSMutableSet setWithArray:array]; +} + +-(id)JSONObjectFromNSSet:(NSSet*)set +{ + return [set allObjects]; +} + +-(id)JSONObjectFromNSMutableSet:(NSMutableSet*)set +{ + return [set allObjects]; +} + +// +// 0 converts to NO, everything else converts to YES +// + +#pragma mark - BOOL <-> number/string +-(NSNumber*)BOOLFromNSNumber:(NSNumber*)number +{ + if (isNull(number)) return [NSNumber numberWithBool:NO]; + return [NSNumber numberWithBool: number.intValue==0?NO:YES]; +} + +-(NSNumber*)BOOLFromNSString:(NSString*)string +{ + if (string != nil && + ([string caseInsensitiveCompare:@"true"] == NSOrderedSame || + [string caseInsensitiveCompare:@"yes"] == NSOrderedSame)) { + return [NSNumber numberWithBool:YES]; + } + return [NSNumber numberWithBool: ([string intValue]==0)?NO:YES]; +} + +-(NSNumber*)JSONObjectFromBOOL:(NSNumber*)number +{ + return [NSNumber numberWithBool: number.intValue==0?NO:YES]; +} + +#pragma mark - string/number <-> float +-(float)floatFromObject:(id)obj +{ + return [obj floatValue]; +} + +-(float)floatFromNSString:(NSString*)string +{ + return [self floatFromObject:string]; +} + +-(float)floatFromNSNumber:(NSNumber*)number +{ + return [self floatFromObject:number]; +} + +-(NSNumber*)NSNumberFromfloat:(float)f +{ + return [NSNumber numberWithFloat:f]; +} + +#pragma mark - string <-> number +-(NSNumber*)NSNumberFromNSString:(NSString*)string +{ + return [NSNumber numberWithDouble:[string doubleValue]]; +} + +-(NSString*)NSStringFromNSNumber:(NSNumber*)number +{ + return [number stringValue]; +} + +-(NSDecimalNumber*)NSDecimalNumberFromNSString:(NSString*)string +{ + return [NSDecimalNumber decimalNumberWithString:string]; +} + +-(NSString*)NSStringFromNSDecimalNumber:(NSDecimalNumber*)number +{ + return [number stringValue]; +} + +#pragma mark - string <-> url +-(NSURL*)NSURLFromNSString:(NSString*)string +{ + // do not change this behavior - there are other ways of overriding it + // see: https://github.com/jsonmodel/jsonmodel/pull/119 + return [NSURL URLWithString:string]; +} + +-(NSString*)JSONObjectFromNSURL:(NSURL*)url +{ + return [url absoluteString]; +} + +#pragma mark - string <-> date +-(NSDateFormatter*)importDateFormatter +{ + static dispatch_once_t onceInput; + static NSDateFormatter* inputDateFormatter; + dispatch_once(&onceInput, ^{ + inputDateFormatter = [[NSDateFormatter alloc] init]; + [inputDateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]]; + [inputDateFormatter setDateFormat:@"yyyy-MM-dd'T'HHmmssZZZ"]; + }); + return inputDateFormatter; +} + +-(NSDate*)__NSDateFromNSString:(NSString*)string +{ + string = [string stringByReplacingOccurrencesOfString:@":" withString:@""]; // this is such an ugly code, is this the only way? + return [self.importDateFormatter dateFromString: string]; +} + +-(NSString*)__JSONObjectFromNSDate:(NSDate*)date +{ + static dispatch_once_t onceOutput; + static NSDateFormatter *outputDateFormatter; + dispatch_once(&onceOutput, ^{ + outputDateFormatter = [[NSDateFormatter alloc] init]; + [outputDateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]]; + [outputDateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZ"]; + }); + return [outputDateFormatter stringFromDate:date]; +} + +#pragma mark - number <-> date +- (NSDate*)NSDateFromNSNumber:(NSNumber*)number +{ + return [NSDate dateWithTimeIntervalSince1970:number.doubleValue]; +} + +#pragma mark - string <-> NSTimeZone + +- (NSTimeZone *)NSTimeZoneFromNSString:(NSString *)string { + return [NSTimeZone timeZoneWithName:string]; +} + +- (id)JSONObjectFromNSTimeZone:(NSTimeZone *)timeZone { + return [timeZone name]; +} + +#pragma mark - hidden transform for empty dictionaries +//https://github.com/jsonmodel/jsonmodel/issues/163 +-(NSDictionary*)__NSDictionaryFromNSArray:(NSArray*)array +{ + if (array.count==0) return @{}; + return (id)array; +} + +-(NSMutableDictionary*)__NSMutableDictionaryFromNSArray:(NSArray*)array +{ + if (array.count==0) return [[self __NSDictionaryFromNSArray:array] mutableCopy]; + return (id)array; +} + +@end diff --git a/Pods/JSONModel/LICENSE b/Pods/JSONModel/LICENSE new file mode 100644 index 0000000..babea51 --- /dev/null +++ b/Pods/JSONModel/LICENSE @@ -0,0 +1,18 @@ +Copyright (c) 2012-2016 Marin Todorov and JSONModel 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. diff --git a/Pods/JSONModel/README.md b/Pods/JSONModel/README.md new file mode 100644 index 0000000..67089d9 --- /dev/null +++ b/Pods/JSONModel/README.md @@ -0,0 +1,395 @@ +# JSONModel - Magical Data Modeling Framework for JSON + +JSONModel allows rapid creation of smart data models. You can use it in your +iOS, macOS, watchOS and tvOS apps. Automatic introspection of your model classes +and JSON input drastically reduces the amount of code you have to write. + +See [CHANGELOG.md](CHANGELOG.md) for details on changes. + +## Installation + +### CocoaPods + +```ruby +pod 'JSONModel' +``` + +### Carthage + +```ruby +github "jsonmodel/jsonmodel" +``` + +### Manual + +0. download the JSONModel repository +0. copy the JSONModel sub-folder into your Xcode project +0. link your app to SystemConfiguration.framework + +## Basic Usage + +Consider you have JSON like this: + +```json +{ "id": 10, "country": "Germany", "dialCode": 49, "isInEurope": true } +``` + +- create a JSONModel subclass for your data model +- declare properties in your header file with the name of the JSON keys: + +```objc +@interface CountryModel : JSONModel +@property (nonatomic) NSInteger id; +@property (nonatomic) NSString *country; +@property (nonatomic) NSString *dialCode; +@property (nonatomic) BOOL isInEurope; +@end +``` + +There's no need to do anything in the implementation (`.m`) file. + +- initialize your model with data: + +```objc +NSError *error; +CountryModel *country = [[CountryModel alloc] initWithString:myJson error:&error]; +``` + +If the validation of the JSON passes. you have all the corresponding properties +in your model populated from the JSON. JSONModel will also try to convert as +much data to the types you expect. In the example above it will: + +- convert `id` from string (in the JSON) to an `int` for your class +- copy the `country` value +- convert `dialCode` from a number (in the JSON) to an `NSString` value +- copy the `isInEurope` value + +All you have to do is define the properties and their expected types. + +## Examples + +### Automatic name based mapping + +```json +{ + "id": 123, + "name": "Product name", + "price": 12.95 +} +``` + +```objc +@interface ProductModel : JSONModel +@property (nonatomic) NSInteger id; +@property (nonatomic) NSString *name; +@property (nonatomic) float price; +@end +``` + +### Model cascading (models including other models) + +```json +{ + "orderId": 104, + "totalPrice": 13.45, + "product": { + "id": 123, + "name": "Product name", + "price": 12.95 + } +} +``` + +```objc +@interface ProductModel : JSONModel +@property (nonatomic) NSInteger id; +@property (nonatomic) NSString *name; +@property (nonatomic) float price; +@end + +@interface OrderModel : JSONModel +@property (nonatomic) NSInteger orderId; +@property (nonatomic) float totalPrice; +@property (nonatomic) ProductModel *product; +@end +``` + +### Model collections + +```json +{ + "orderId": 104, + "totalPrice": 103.45, + "products": [ + { + "id": 123, + "name": "Product #1", + "price": 12.95 + }, + { + "id": 137, + "name": "Product #2", + "price": 82.95 + } + ] +} +``` + +```objc +@protocol ProductModel; + +@interface ProductModel : JSONModel +@property (nonatomic) NSInteger id; +@property (nonatomic) NSString *name; +@property (nonatomic) float price; +@end + +@interface OrderModel : JSONModel +@property (nonatomic) NSInteger orderId; +@property (nonatomic) float totalPrice; +@property (nonatomic) NSArray *products; +@end +``` + +Note: the angle brackets after `NSArray` contain a protocol. This is not the +same as the Objective-C generics system. They are not mutually exclusive, but +for JSONModel to work, the protocol must be in place. + +Also property can have generics info for compiler +```objc +@interface OrderModel : JSONModel +@property (nonatomic) NSInteger orderId; +@property (nonatomic) float totalPrice; +@property (nonatomic) NSArray *products; +@end +``` + +### Nested key mapping + +```json +{ + "orderId": 104, + "orderDetails": { + "name": "Product #1", + "price": { + "usd": 12.95 + } + } +} +``` + +```objc +@interface OrderModel : JSONModel +@property (nonatomic) NSInteger id; +@property (nonatomic) NSString *productName; +@property (nonatomic) float price; +@end + +@implementation OrderModel + ++ (JSONKeyMapper *)keyMapper +{ + return [[JSONKeyMapper alloc] initWithModelToJSONDictionary:@{ + @"id": @"orderId", + @"productName": @"orderDetails.name", + @"price": @"orderDetails.price.usd" + }]; +} + +@end +``` + +### Map automatically to snake_case + +```json +{ + "order_id": 104, + "order_product": "Product #1", + "order_price": 12.95 +} +``` + +```objc +@interface OrderModel : JSONModel +@property (nonatomic) NSInteger orderId; +@property (nonatomic) NSString *orderProduct; +@property (nonatomic) float orderPrice; +@end + +@implementation OrderModel + ++ (JSONKeyMapper *)keyMapper +{ + return [JSONKeyMapper mapperForSnakeCase]; +} + +@end +``` + +### Optional properties (i.e. can be missing or null) + +```json +{ + "id": 123, + "name": null, + "price": 12.95 +} +``` + +```objc +@interface ProductModel : JSONModel +@property (nonatomic) NSInteger id; +@property (nonatomic) NSString *name; +@property (nonatomic) float price; +@property (nonatomic) NSNumber *uuid; +@end +``` + +### Ignored properties (i.e. JSONModel completely ignores them) + +```json +{ + "id": 123, + "name": null +} +``` + +```objc +@interface ProductModel : JSONModel +@property (nonatomic) NSInteger id; +@property (nonatomic) NSString *customProperty; +@end +``` + +### Making scalar types optional + +```json +{ + "id": null +} +``` + +```objc +@interface ProductModel : JSONModel +@property (nonatomic) NSInteger id; +@end + +@implementation ProductModel + ++ (BOOL)propertyIsOptional:(NSString *)propertyName +{ + if ([propertyName isEqualToString:@"id"]) + return YES; + + return NO; +} + +@end +``` + +### Export model to `NSDictionary` or JSON + +```objc +ProductModel *pm = [ProductModel new]; +pm.name = @"Some Name"; + +// convert to dictionary +NSDictionary *dict = [pm toDictionary]; + +// convert to json +NSString *string = [pm toJSONString]; +``` + +### Custom data transformers + +```objc +@interface JSONValueTransformer (CustomTransformer) +@end + +@implementation JSONValueTransformer (CustomTransformer) + +- (NSDate *)NSDateFromNSString:(NSString *)string +{ + NSDateFormatter *formatter = [NSDateFormatter new]; + formatter.dateFormat = APIDateFormat; + return [formatter dateFromString:string]; +} + +- (NSString *)JSONObjectFromNSDate:(NSDate *)date +{ + NSDateFormatter *formatter = [NSDateFormatter new]; + formatter.dateFormat = APIDateFormat; + return [formatter stringFromDate:date]; +} + +@end +``` + +### Custom getters/setters + +```objc +@interface ProductModel : JSONModel +@property (nonatomic) NSInteger id; +@property (nonatomic) NSString *name; +@property (nonatomic) float price; +@property (nonatomic) NSLocale *locale; +@end + +@implementation ProductModel + +- (void)setLocaleWithNSString:(NSString *)string +{ + self.locale = [NSLocale localeWithLocaleIdentifier:string]; +} + +- (void)setLocaleWithNSDictionary:(NSDictionary *)dictionary +{ + self.locale = [NSLocale localeWithLocaleIdentifier:dictionary[@"identifier"]]; +} + +- (NSString *)JSONObjectForLocale +{ + return self.locale.localeIdentifier; +} + +@end +``` + +### Custom JSON validation + +```objc + +@interface ProductModel : JSONModel +@property (nonatomic) NSInteger id; +@property (nonatomic) NSString *name; +@property (nonatomic) float price; +@property (nonatomic) NSLocale *locale; +@property (nonatomic) NSNumber *minNameLength; +@end + +@implementation ProductModel + +- (BOOL)validate:(NSError **)error +{ + if (![super validate:error]) + return NO; + + if (self.name.length < self.minNameLength.integerValue) + { + *error = [NSError errorWithDomain:@"me.mycompany.com" code:1 userInfo:nil]; + return NO; + } + + return YES; +} + +@end +``` + +## License + +MIT licensed - see [LICENSE](LICENSE) file. + +## Contributing + +We love pull requests! See [CONTRIBUTING.md](CONTRIBUTING.md) for full details. diff --git a/Pods/Manifest.lock b/Pods/Manifest.lock new file mode 100644 index 0000000..eb9f0e5 --- /dev/null +++ b/Pods/Manifest.lock @@ -0,0 +1,20 @@ +PODS: + - CocoaSecurity (1.2.4) + - JSONModel (1.8.0) + +DEPENDENCIES: + - CocoaSecurity + - JSONModel + +SPEC REPOS: + trunk: + - CocoaSecurity + - JSONModel + +SPEC CHECKSUMS: + CocoaSecurity: d288a6f87e0f363823d2cb83e753814a6944f71a + JSONModel: 02ab723958366a3fd27da57ea2af2113658762e9 + +PODFILE CHECKSUM: 8f0d15fb3bf327bd25b9de3dee5d9d3d90351b9b + +COCOAPODS: 1.8.4 diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj new file mode 100644 index 0000000..efd9d60 --- /dev/null +++ b/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,859 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXBuildFile section */ + 02E2954BD351E7B167D8F60B13208DAF /* JSONModelError.h in Headers */ = {isa = PBXBuildFile; fileRef = 15A48DB74C12FB44086B104134A79CAA /* JSONModelError.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0EFCD2DDCC31EDC876C2F6296E7EB338 /* CocoaSecurity-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C20FCBEB81BD92D14CF9CCB09422CD6 /* CocoaSecurity-dummy.m */; }; + 1071D84B6431759A11FAEBAAE29E3F32 /* JSONHTTPClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 58B34D0DA217011D96BC51AE713B0981 /* JSONHTTPClient.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 15B4F9E936BFDFFC59ACB0880A106059 /* Pods-goodpk-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4943CB5156E1F602292C19F9EADCF943 /* Pods-goodpk-dummy.m */; }; + 191126E8D5A1E26339D2B767EF3AE197 /* JSONModel+networking.h in Headers */ = {isa = PBXBuildFile; fileRef = E7AA4B684F0F58F6FDE0483595742B50 /* JSONModel+networking.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F1405DD136373408679477D78769F81 /* Pods-goodpk-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 98BE9338936E3A5D614C69419222DDB4 /* Pods-goodpk-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 230736607A4E5FECC7E5C99D37C6E9D8 /* CocoaSecurity.m in Sources */ = {isa = PBXBuildFile; fileRef = FC127B4F930B51F3627A0DFDEB5C0B0E /* CocoaSecurity.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + 26A3D3037A05E7E99AFF098D11427775 /* JSONKeyMapper.m in Sources */ = {isa = PBXBuildFile; fileRef = FDC468FF3FB8C55C8BA41D42027FF154 /* JSONKeyMapper.m */; }; + 28CC9F70EF9F2F0A22323921A5C889B5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */; }; + 30DF77E53D2E837133265614EC8BEDA8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */; }; + 3AEA2F22B88CD78E671F25B60DB66ADA /* JSONAPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 1528D8481F93150DA097108A5EFAF9F5 /* JSONAPI.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6FCDE0D44543F4DABF90A88E056D8199 /* JSONModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 1CACE6D0DABC1F1BBEBED43D1F1FBCE7 /* JSONModel.m */; }; + 70D237F541D491974978C80013B387A5 /* CocoaSecurity-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 0AB5237FB32D4339ABE7B66E77F75C0B /* CocoaSecurity-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 75C939C90205A780AB001C84A0B90C24 /* JSONModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C745D6E9AE4EC4E7413D93A75162C30 /* JSONModel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 75D5E22D948CB8F73AD803361CE3F356 /* CocoaSecurity.h in Headers */ = {isa = PBXBuildFile; fileRef = C78935900E605432CF9B1AA7E673778F /* CocoaSecurity.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 77E31081DA28761A8B84579D4576D1E9 /* Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A63C3DF4C0FA144E9CA32DA757BF052 /* Base64.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; + A52DD788A5384665F425D6A2C7493AD0 /* JSONModelError.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E3760806B68178FFCC3AB21001D1239 /* JSONModelError.m */; }; + B0BA1C31A2A3AB25BC95A4B2DE0A7B5D /* JSONValueTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = B8B67B9F6639E43B384EB1A7BBBCD32D /* JSONValueTransformer.m */; }; + B4C7BC969594EB3E9323674B7FF7C66E /* JSONHTTPClient.m in Sources */ = {isa = PBXBuildFile; fileRef = CC9D409CB377C14C151A840FF0EA5DE0 /* JSONHTTPClient.m */; }; + BD0FA932C1C6423FD199C99EA2FC712B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */; }; + C25BD96E691172D62B98B2F5F8D7F0C7 /* JSONModelLib.h in Headers */ = {isa = PBXBuildFile; fileRef = 45C4A0EE0ACFD9565AC4AF0928C2CD76 /* JSONModelLib.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C2FF8C43BAB48D67D8E6578AB9C33595 /* Base64.h in Headers */ = {isa = PBXBuildFile; fileRef = 0AC294B1EC18FE4DBDDCA3C43AFC68D4 /* Base64.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C64C8DE746D376EEA160794275302677 /* JSONModelClassProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = 09D07CAE7ED647C69F1727F23D4D03A4 /* JSONModelClassProperty.m */; }; + C65CBBF120A2DD097498BFA38119D466 /* JSONAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 285CDB1DDFB8BC8FB68EBA68E2FB2AFA /* JSONAPI.m */; }; + C7850AB3F7B5FDCA4F1F47F1EC205276 /* JSONKeyMapper.h in Headers */ = {isa = PBXBuildFile; fileRef = D57BB8F6DA69AB4496C95B8D64C943EF /* JSONKeyMapper.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CFD38BDDB48F8D35B9A858E957A933A2 /* JSONModel+networking.m in Sources */ = {isa = PBXBuildFile; fileRef = D46F66B0E7DF751256CB1C163A4E829B /* JSONModel+networking.m */; }; + D358BCEB69D2E10B9BC6504C93D7D14C /* JSONModelClassProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = AE4507E9A1D585B2EC817F1CF49F82EC /* JSONModelClassProperty.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DFF8D80125C062F6646E6EE798E6ABA3 /* JSONModel-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 4277FFB6D41E5F0851117E2F0A627E1D /* JSONModel-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E3886BA871A93B03E984D8BD7823D947 /* JSONValueTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F816875ADF178E8EDF4D31D21987E68 /* JSONValueTransformer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F442593E37B8F49398FDB1974EDF3FD6 /* JSONModel-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = AA40A3B76BCDD9DE85FA1ACD3320E1E8 /* JSONModel-dummy.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 230A159CF4863701D794C0DC94C54B7C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = E0EAF4371C6E4B30A1779D513CB4355B; + remoteInfo = JSONModel; + }; + FB4A29BF4043F9F564BC2C769CFB8497 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = EECEFE3E704A038F8532197F7F483302; + remoteInfo = CocoaSecurity; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 09D07CAE7ED647C69F1727F23D4D03A4 /* JSONModelClassProperty.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JSONModelClassProperty.m; path = JSONModel/JSONModel/JSONModelClassProperty.m; sourceTree = ""; }; + 0A8F87932A4A1E225275929C9E01EE61 /* Pods-goodpk.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-goodpk.release.xcconfig"; sourceTree = ""; }; + 0AB5237FB32D4339ABE7B66E77F75C0B /* CocoaSecurity-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "CocoaSecurity-umbrella.h"; sourceTree = ""; }; + 0AC294B1EC18FE4DBDDCA3C43AFC68D4 /* Base64.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Base64.h; path = submodules/Base64/Base64/Base64.h; sourceTree = ""; }; + 0E3760806B68178FFCC3AB21001D1239 /* JSONModelError.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JSONModelError.m; path = JSONModel/JSONModel/JSONModelError.m; sourceTree = ""; }; + 12ABEC0087651F36BF0C06AAB112F1DB /* Pods_goodpk.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_goodpk.framework; path = "Pods-goodpk.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1528D8481F93150DA097108A5EFAF9F5 /* JSONAPI.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JSONAPI.h; path = JSONModel/JSONModelNetworking/JSONAPI.h; sourceTree = ""; }; + 15A48DB74C12FB44086B104134A79CAA /* JSONModelError.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JSONModelError.h; path = JSONModel/JSONModel/JSONModelError.h; sourceTree = ""; }; + 1C745D6E9AE4EC4E7413D93A75162C30 /* JSONModel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JSONModel.h; path = JSONModel/JSONModel/JSONModel.h; sourceTree = ""; }; + 1CACE6D0DABC1F1BBEBED43D1F1FBCE7 /* JSONModel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JSONModel.m; path = JSONModel/JSONModel/JSONModel.m; sourceTree = ""; }; + 285CDB1DDFB8BC8FB68EBA68E2FB2AFA /* JSONAPI.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JSONAPI.m; path = JSONModel/JSONModelNetworking/JSONAPI.m; sourceTree = ""; }; + 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 38E173793685C2BA088C36F052956291 /* CocoaSecurity.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = CocoaSecurity.xcconfig; sourceTree = ""; }; + 4277FFB6D41E5F0851117E2F0A627E1D /* JSONModel-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "JSONModel-umbrella.h"; sourceTree = ""; }; + 45C4A0EE0ACFD9565AC4AF0928C2CD76 /* JSONModelLib.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JSONModelLib.h; path = JSONModel/JSONModelLib.h; sourceTree = ""; }; + 4943CB5156E1F602292C19F9EADCF943 /* Pods-goodpk-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-goodpk-dummy.m"; sourceTree = ""; }; + 4A262D85C20F47732E2FAD2A4231F09C /* Pods-goodpk.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-goodpk.modulemap"; sourceTree = ""; }; + 58B34D0DA217011D96BC51AE713B0981 /* JSONHTTPClient.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JSONHTTPClient.h; path = JSONModel/JSONModelNetworking/JSONHTTPClient.h; sourceTree = ""; }; + 5A63C3DF4C0FA144E9CA32DA757BF052 /* Base64.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = Base64.m; path = submodules/Base64/Base64/Base64.m; sourceTree = ""; }; + 5A7B912244E94A6ADC8F7F4CAD7F6631 /* Pods-goodpk-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-goodpk-frameworks.sh"; sourceTree = ""; }; + 5C20FCBEB81BD92D14CF9CCB09422CD6 /* CocoaSecurity-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "CocoaSecurity-dummy.m"; sourceTree = ""; }; + 5CE329E83AF8C486DD91CCC2570C5F91 /* CocoaSecurity-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "CocoaSecurity-prefix.pch"; sourceTree = ""; }; + 6F949F2EA1CA15EC1BA2F8466F026263 /* CocoaSecurity.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = CocoaSecurity.modulemap; sourceTree = ""; }; + 7697F522E1E2F8AAED486E20B7210E8D /* CocoaSecurity.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = CocoaSecurity.framework; path = CocoaSecurity.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 8220C74FDF64D404EE05DF63F0EBA6F6 /* JSONModel.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = JSONModel.modulemap; sourceTree = ""; }; + 8715A839B98B1E163E607F5DA7BFD0AF /* Pods-goodpk-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-goodpk-Info.plist"; sourceTree = ""; }; + 8D5427A534DE2A87F6A1E65C079FA0BB /* CocoaSecurity-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "CocoaSecurity-Info.plist"; sourceTree = ""; }; + 8E4D3C8ACBBE8C6EF553D3A5C6886155 /* JSONModel-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "JSONModel-prefix.pch"; sourceTree = ""; }; + 8F816875ADF178E8EDF4D31D21987E68 /* JSONValueTransformer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JSONValueTransformer.h; path = JSONModel/JSONModelTransformations/JSONValueTransformer.h; sourceTree = ""; }; + 9012AF4DE9E78E675790CDA621AF0EE0 /* Pods-goodpk.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-goodpk.debug.xcconfig"; sourceTree = ""; }; + 92902D82F72446CFEC28A3829DAC4FE3 /* Pods-goodpk-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-goodpk-acknowledgements.markdown"; sourceTree = ""; }; + 98BE9338936E3A5D614C69419222DDB4 /* Pods-goodpk-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-goodpk-umbrella.h"; sourceTree = ""; }; + 9A8292BAC1592A5218AF6726CD42C0EB /* JSONModel.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = JSONModel.xcconfig; sourceTree = ""; }; + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + AA40A3B76BCDD9DE85FA1ACD3320E1E8 /* JSONModel-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "JSONModel-dummy.m"; sourceTree = ""; }; + AE4507E9A1D585B2EC817F1CF49F82EC /* JSONModelClassProperty.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JSONModelClassProperty.h; path = JSONModel/JSONModel/JSONModelClassProperty.h; sourceTree = ""; }; + B30B11FACC8A097CC313913C72718023 /* JSONModel-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "JSONModel-Info.plist"; sourceTree = ""; }; + B8B67B9F6639E43B384EB1A7BBBCD32D /* JSONValueTransformer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JSONValueTransformer.m; path = JSONModel/JSONModelTransformations/JSONValueTransformer.m; sourceTree = ""; }; + BAACA1BF7AB3DD28402C4F9A7C2FD104 /* JSONModel.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = JSONModel.framework; path = JSONModel.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C78935900E605432CF9B1AA7E673778F /* CocoaSecurity.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = CocoaSecurity.h; path = CocoaSecurity/CocoaSecurity.h; sourceTree = ""; }; + CC9D409CB377C14C151A840FF0EA5DE0 /* JSONHTTPClient.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JSONHTTPClient.m; path = JSONModel/JSONModelNetworking/JSONHTTPClient.m; sourceTree = ""; }; + D147FD4CF26F3DBFDEC941C020AA3FAF /* Pods-goodpk-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-goodpk-acknowledgements.plist"; sourceTree = ""; }; + D46F66B0E7DF751256CB1C163A4E829B /* JSONModel+networking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "JSONModel+networking.m"; path = "JSONModel/JSONModelNetworking/JSONModel+networking.m"; sourceTree = ""; }; + D57BB8F6DA69AB4496C95B8D64C943EF /* JSONKeyMapper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = JSONKeyMapper.h; path = JSONModel/JSONModelTransformations/JSONKeyMapper.h; sourceTree = ""; }; + E7AA4B684F0F58F6FDE0483595742B50 /* JSONModel+networking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "JSONModel+networking.h"; path = "JSONModel/JSONModelNetworking/JSONModel+networking.h"; sourceTree = ""; }; + FC127B4F930B51F3627A0DFDEB5C0B0E /* CocoaSecurity.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = CocoaSecurity.m; path = CocoaSecurity/CocoaSecurity.m; sourceTree = ""; }; + FDC468FF3FB8C55C8BA41D42027FF154 /* JSONKeyMapper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = JSONKeyMapper.m; path = JSONModel/JSONModelTransformations/JSONKeyMapper.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2BC6A3AB1B11BF2B308978B9DEFC0D3F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 28CC9F70EF9F2F0A22323921A5C889B5 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 886E050E05F79FD43F2409BED7E67F73 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 30DF77E53D2E837133265614EC8BEDA8 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F179172C58DFEB7DDD4C8DFCC7E62156 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + BD0FA932C1C6423FD199C99EA2FC712B /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0D64C9CB2A93D6283F8E589EE6C04FDF /* Pods */ = { + isa = PBXGroup; + children = ( + ABD80F98383BEF06F02CB21C590D459F /* CocoaSecurity */, + 9789611F9ABF3FB620DE746F22884297 /* JSONModel */, + ); + name = Pods; + sourceTree = ""; + }; + 58858F56AA7A1C3651F09E6BFA3E1C98 /* Pods-goodpk */ = { + isa = PBXGroup; + children = ( + 4A262D85C20F47732E2FAD2A4231F09C /* Pods-goodpk.modulemap */, + 92902D82F72446CFEC28A3829DAC4FE3 /* Pods-goodpk-acknowledgements.markdown */, + D147FD4CF26F3DBFDEC941C020AA3FAF /* Pods-goodpk-acknowledgements.plist */, + 4943CB5156E1F602292C19F9EADCF943 /* Pods-goodpk-dummy.m */, + 5A7B912244E94A6ADC8F7F4CAD7F6631 /* Pods-goodpk-frameworks.sh */, + 8715A839B98B1E163E607F5DA7BFD0AF /* Pods-goodpk-Info.plist */, + 98BE9338936E3A5D614C69419222DDB4 /* Pods-goodpk-umbrella.h */, + 9012AF4DE9E78E675790CDA621AF0EE0 /* Pods-goodpk.debug.xcconfig */, + 0A8F87932A4A1E225275929C9E01EE61 /* Pods-goodpk.release.xcconfig */, + ); + name = "Pods-goodpk"; + path = "Target Support Files/Pods-goodpk"; + sourceTree = ""; + }; + 72E95A963302B0470D1D51B86D02207E /* Support Files */ = { + isa = PBXGroup; + children = ( + 8220C74FDF64D404EE05DF63F0EBA6F6 /* JSONModel.modulemap */, + 9A8292BAC1592A5218AF6726CD42C0EB /* JSONModel.xcconfig */, + AA40A3B76BCDD9DE85FA1ACD3320E1E8 /* JSONModel-dummy.m */, + B30B11FACC8A097CC313913C72718023 /* JSONModel-Info.plist */, + 8E4D3C8ACBBE8C6EF553D3A5C6886155 /* JSONModel-prefix.pch */, + 4277FFB6D41E5F0851117E2F0A627E1D /* JSONModel-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/JSONModel"; + sourceTree = ""; + }; + 8B01B1C44ECD19BC49C92C3E7A54B68D /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + 58858F56AA7A1C3651F09E6BFA3E1C98 /* Pods-goodpk */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + 93599F1D13CFE999E6AA0639E7EF7F35 /* Support Files */ = { + isa = PBXGroup; + children = ( + 6F949F2EA1CA15EC1BA2F8466F026263 /* CocoaSecurity.modulemap */, + 38E173793685C2BA088C36F052956291 /* CocoaSecurity.xcconfig */, + 5C20FCBEB81BD92D14CF9CCB09422CD6 /* CocoaSecurity-dummy.m */, + 8D5427A534DE2A87F6A1E65C079FA0BB /* CocoaSecurity-Info.plist */, + 5CE329E83AF8C486DD91CCC2570C5F91 /* CocoaSecurity-prefix.pch */, + 0AB5237FB32D4339ABE7B66E77F75C0B /* CocoaSecurity-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/CocoaSecurity"; + sourceTree = ""; + }; + 9789611F9ABF3FB620DE746F22884297 /* JSONModel */ = { + isa = PBXGroup; + children = ( + 1528D8481F93150DA097108A5EFAF9F5 /* JSONAPI.h */, + 285CDB1DDFB8BC8FB68EBA68E2FB2AFA /* JSONAPI.m */, + 58B34D0DA217011D96BC51AE713B0981 /* JSONHTTPClient.h */, + CC9D409CB377C14C151A840FF0EA5DE0 /* JSONHTTPClient.m */, + D57BB8F6DA69AB4496C95B8D64C943EF /* JSONKeyMapper.h */, + FDC468FF3FB8C55C8BA41D42027FF154 /* JSONKeyMapper.m */, + 1C745D6E9AE4EC4E7413D93A75162C30 /* JSONModel.h */, + 1CACE6D0DABC1F1BBEBED43D1F1FBCE7 /* JSONModel.m */, + E7AA4B684F0F58F6FDE0483595742B50 /* JSONModel+networking.h */, + D46F66B0E7DF751256CB1C163A4E829B /* JSONModel+networking.m */, + AE4507E9A1D585B2EC817F1CF49F82EC /* JSONModelClassProperty.h */, + 09D07CAE7ED647C69F1727F23D4D03A4 /* JSONModelClassProperty.m */, + 15A48DB74C12FB44086B104134A79CAA /* JSONModelError.h */, + 0E3760806B68178FFCC3AB21001D1239 /* JSONModelError.m */, + 45C4A0EE0ACFD9565AC4AF0928C2CD76 /* JSONModelLib.h */, + 8F816875ADF178E8EDF4D31D21987E68 /* JSONValueTransformer.h */, + B8B67B9F6639E43B384EB1A7BBBCD32D /* JSONValueTransformer.m */, + 72E95A963302B0470D1D51B86D02207E /* Support Files */, + ); + name = JSONModel; + path = JSONModel; + sourceTree = ""; + }; + ABD80F98383BEF06F02CB21C590D459F /* CocoaSecurity */ = { + isa = PBXGroup; + children = ( + 0AC294B1EC18FE4DBDDCA3C43AFC68D4 /* Base64.h */, + 5A63C3DF4C0FA144E9CA32DA757BF052 /* Base64.m */, + C78935900E605432CF9B1AA7E673778F /* CocoaSecurity.h */, + FC127B4F930B51F3627A0DFDEB5C0B0E /* CocoaSecurity.m */, + 93599F1D13CFE999E6AA0639E7EF7F35 /* Support Files */, + ); + name = CocoaSecurity; + path = CocoaSecurity; + sourceTree = ""; + }; + C0834CEBB1379A84116EF29F93051C60 /* iOS */ = { + isa = PBXGroup; + children = ( + 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */, + ); + name = iOS; + sourceTree = ""; + }; + CD7C70D112DC0E1ABC201BB2CE89F2F9 /* Products */ = { + isa = PBXGroup; + children = ( + 7697F522E1E2F8AAED486E20B7210E8D /* CocoaSecurity.framework */, + BAACA1BF7AB3DD28402C4F9A7C2FD104 /* JSONModel.framework */, + 12ABEC0087651F36BF0C06AAB112F1DB /* Pods_goodpk.framework */, + ); + name = Products; + sourceTree = ""; + }; + CF1408CF629C7361332E53B88F7BD30C = { + isa = PBXGroup; + children = ( + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, + D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */, + 0D64C9CB2A93D6283F8E589EE6C04FDF /* Pods */, + CD7C70D112DC0E1ABC201BB2CE89F2F9 /* Products */, + 8B01B1C44ECD19BC49C92C3E7A54B68D /* Targets Support Files */, + ); + sourceTree = ""; + }; + D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */ = { + isa = PBXGroup; + children = ( + C0834CEBB1379A84116EF29F93051C60 /* iOS */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 2B153DE7E7FF2E82149B9EF016B1FD45 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F1405DD136373408679477D78769F81 /* Pods-goodpk-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 581A17A1096857A659A485C6D82A5E5F /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + C2FF8C43BAB48D67D8E6578AB9C33595 /* Base64.h in Headers */, + 70D237F541D491974978C80013B387A5 /* CocoaSecurity-umbrella.h in Headers */, + 75D5E22D948CB8F73AD803361CE3F356 /* CocoaSecurity.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C10AE64316B9C31B3BB6170AF9933749 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 3AEA2F22B88CD78E671F25B60DB66ADA /* JSONAPI.h in Headers */, + 1071D84B6431759A11FAEBAAE29E3F32 /* JSONHTTPClient.h in Headers */, + C7850AB3F7B5FDCA4F1F47F1EC205276 /* JSONKeyMapper.h in Headers */, + 191126E8D5A1E26339D2B767EF3AE197 /* JSONModel+networking.h in Headers */, + DFF8D80125C062F6646E6EE798E6ABA3 /* JSONModel-umbrella.h in Headers */, + 75C939C90205A780AB001C84A0B90C24 /* JSONModel.h in Headers */, + D358BCEB69D2E10B9BC6504C93D7D14C /* JSONModelClassProperty.h in Headers */, + 02E2954BD351E7B167D8F60B13208DAF /* JSONModelError.h in Headers */, + C25BD96E691172D62B98B2F5F8D7F0C7 /* JSONModelLib.h in Headers */, + E3886BA871A93B03E984D8BD7823D947 /* JSONValueTransformer.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + E0EAF4371C6E4B30A1779D513CB4355B /* JSONModel */ = { + isa = PBXNativeTarget; + buildConfigurationList = 864246C4794538189B6310F839B9CD50 /* Build configuration list for PBXNativeTarget "JSONModel" */; + buildPhases = ( + C10AE64316B9C31B3BB6170AF9933749 /* Headers */, + 9110B95813C4D6328D3D0802138CFDE0 /* Sources */, + 886E050E05F79FD43F2409BED7E67F73 /* Frameworks */, + 33431436401EBC85BE0A907D9728DA1C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = JSONModel; + productName = JSONModel; + productReference = BAACA1BF7AB3DD28402C4F9A7C2FD104 /* JSONModel.framework */; + productType = "com.apple.product-type.framework"; + }; + EECEFE3E704A038F8532197F7F483302 /* CocoaSecurity */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0DE7D5B6B430D9F4051E5EC1C36064DF /* Build configuration list for PBXNativeTarget "CocoaSecurity" */; + buildPhases = ( + 581A17A1096857A659A485C6D82A5E5F /* Headers */, + 1C31172E21DF03C53B31D95DA6769B73 /* Sources */, + F179172C58DFEB7DDD4C8DFCC7E62156 /* Frameworks */, + 51E4B027C009DE178CB063189E3131C2 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = CocoaSecurity; + productName = CocoaSecurity; + productReference = 7697F522E1E2F8AAED486E20B7210E8D /* CocoaSecurity.framework */; + productType = "com.apple.product-type.framework"; + }; + FC07128126FC8A141CA01D3D6D4118FB /* Pods-goodpk */ = { + isa = PBXNativeTarget; + buildConfigurationList = E9C87CAFBA651A062EC8A8E4BB1665CD /* Build configuration list for PBXNativeTarget "Pods-goodpk" */; + buildPhases = ( + 2B153DE7E7FF2E82149B9EF016B1FD45 /* Headers */, + AE82C8DA4FA60F5A8DA9173B18420E8D /* Sources */, + 2BC6A3AB1B11BF2B308978B9DEFC0D3F /* Frameworks */, + DBADF56745B5073EB4949E1FDDD6BFF0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 9C5A020D69264B9CC4ADB3E9DE2522E9 /* PBXTargetDependency */, + 32A1BC581EE2E4D0C73F0300F4857F29 /* PBXTargetDependency */, + ); + name = "Pods-goodpk"; + productName = "Pods-goodpk"; + productReference = 12ABEC0087651F36BF0C06AAB112F1DB /* Pods_goodpk.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + BFDFE7DC352907FC980B868725387E98 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1100; + LastUpgradeCheck = 1100; + }; + buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 10.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = CF1408CF629C7361332E53B88F7BD30C; + productRefGroup = CD7C70D112DC0E1ABC201BB2CE89F2F9 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + EECEFE3E704A038F8532197F7F483302 /* CocoaSecurity */, + E0EAF4371C6E4B30A1779D513CB4355B /* JSONModel */, + FC07128126FC8A141CA01D3D6D4118FB /* Pods-goodpk */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 33431436401EBC85BE0A907D9728DA1C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 51E4B027C009DE178CB063189E3131C2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DBADF56745B5073EB4949E1FDDD6BFF0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1C31172E21DF03C53B31D95DA6769B73 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 77E31081DA28761A8B84579D4576D1E9 /* Base64.m in Sources */, + 0EFCD2DDCC31EDC876C2F6296E7EB338 /* CocoaSecurity-dummy.m in Sources */, + 230736607A4E5FECC7E5C99D37C6E9D8 /* CocoaSecurity.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9110B95813C4D6328D3D0802138CFDE0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C65CBBF120A2DD097498BFA38119D466 /* JSONAPI.m in Sources */, + B4C7BC969594EB3E9323674B7FF7C66E /* JSONHTTPClient.m in Sources */, + 26A3D3037A05E7E99AFF098D11427775 /* JSONKeyMapper.m in Sources */, + CFD38BDDB48F8D35B9A858E957A933A2 /* JSONModel+networking.m in Sources */, + F442593E37B8F49398FDB1974EDF3FD6 /* JSONModel-dummy.m in Sources */, + 6FCDE0D44543F4DABF90A88E056D8199 /* JSONModel.m in Sources */, + C64C8DE746D376EEA160794275302677 /* JSONModelClassProperty.m in Sources */, + A52DD788A5384665F425D6A2C7493AD0 /* JSONModelError.m in Sources */, + B0BA1C31A2A3AB25BC95A4B2DE0A7B5D /* JSONValueTransformer.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AE82C8DA4FA60F5A8DA9173B18420E8D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 15B4F9E936BFDFFC59ACB0880A106059 /* Pods-goodpk-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 32A1BC581EE2E4D0C73F0300F4857F29 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = JSONModel; + target = E0EAF4371C6E4B30A1779D513CB4355B /* JSONModel */; + targetProxy = 230A159CF4863701D794C0DC94C54B7C /* PBXContainerItemProxy */; + }; + 9C5A020D69264B9CC4ADB3E9DE2522E9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = CocoaSecurity; + target = EECEFE3E704A038F8532197F7F483302 /* CocoaSecurity */; + targetProxy = FB4A29BF4043F9F564BC2C769CFB8497 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 257497152829C177993B5EC99C1D227A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; + 33BC22F020D70C89158B327BFCEB08E9 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9A8292BAC1592A5218AF6726CD42C0EB /* JSONModel.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/JSONModel/JSONModel-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/JSONModel/JSONModel-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/JSONModel/JSONModel.modulemap"; + PRODUCT_MODULE_NAME = JSONModel; + PRODUCT_NAME = JSONModel; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 712EC6338C1EE4DF2F4D53563554EC7B /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9012AF4DE9E78E675790CDA621AF0EE0 /* Pods-goodpk.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-goodpk/Pods-goodpk-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-goodpk/Pods-goodpk.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 71424BF792029EF6EE410035F06B3B9A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 38E173793685C2BA088C36F052956291 /* CocoaSecurity.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/CocoaSecurity/CocoaSecurity-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/CocoaSecurity/CocoaSecurity-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/CocoaSecurity/CocoaSecurity.modulemap"; + PRODUCT_MODULE_NAME = CocoaSecurity; + PRODUCT_NAME = CocoaSecurity; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + C2A116C45A67EF9A7628892EDBB08724 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9A8292BAC1592A5218AF6726CD42C0EB /* JSONModel.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/JSONModel/JSONModel-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/JSONModel/JSONModel-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/JSONModel/JSONModel.modulemap"; + PRODUCT_MODULE_NAME = JSONModel; + PRODUCT_NAME = JSONModel; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + DD8F832993327D1DD8046C3CBCBD97CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + EA3567EDD37BC8B7DFBC155558581FC2 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 38E173793685C2BA088C36F052956291 /* CocoaSecurity.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/CocoaSecurity/CocoaSecurity-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/CocoaSecurity/CocoaSecurity-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/CocoaSecurity/CocoaSecurity.modulemap"; + PRODUCT_MODULE_NAME = CocoaSecurity; + PRODUCT_NAME = CocoaSecurity; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + EB861B3E53B79798361E0016432A16FC /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0A8F87932A4A1E225275929C9E01EE61 /* Pods-goodpk.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-goodpk/Pods-goodpk-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-goodpk/Pods-goodpk.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 0DE7D5B6B430D9F4051E5EC1C36064DF /* Build configuration list for PBXNativeTarget "CocoaSecurity" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EA3567EDD37BC8B7DFBC155558581FC2 /* Debug */, + 71424BF792029EF6EE410035F06B3B9A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DD8F832993327D1DD8046C3CBCBD97CD /* Debug */, + 257497152829C177993B5EC99C1D227A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 864246C4794538189B6310F839B9CD50 /* Build configuration list for PBXNativeTarget "JSONModel" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C2A116C45A67EF9A7628892EDBB08724 /* Debug */, + 33BC22F020D70C89158B327BFCEB08E9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E9C87CAFBA651A062EC8A8E4BB1665CD /* Build configuration list for PBXNativeTarget "Pods-goodpk" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 712EC6338C1EE4DF2F4D53563554EC7B /* Debug */, + EB861B3E53B79798361E0016432A16FC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */; +} diff --git a/Pods/Pods.xcodeproj/xcuserdata/outeyi.xcuserdatad/xcschemes/CocoaSecurity.xcscheme b/Pods/Pods.xcodeproj/xcuserdata/outeyi.xcuserdatad/xcschemes/CocoaSecurity.xcscheme new file mode 100644 index 0000000..fa7394f --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/outeyi.xcuserdatad/xcschemes/CocoaSecurity.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcuserdata/outeyi.xcuserdatad/xcschemes/JSONModel.xcscheme b/Pods/Pods.xcodeproj/xcuserdata/outeyi.xcuserdatad/xcschemes/JSONModel.xcscheme new file mode 100644 index 0000000..d96a27f --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/outeyi.xcuserdatad/xcschemes/JSONModel.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcuserdata/outeyi.xcuserdatad/xcschemes/Pods-goodpk.xcscheme b/Pods/Pods.xcodeproj/xcuserdata/outeyi.xcuserdatad/xcschemes/Pods-goodpk.xcscheme new file mode 100644 index 0000000..bb32e04 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/outeyi.xcuserdatad/xcschemes/Pods-goodpk.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Pods/Pods.xcodeproj/xcuserdata/outeyi.xcuserdatad/xcschemes/xcschememanagement.plist b/Pods/Pods.xcodeproj/xcuserdata/outeyi.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..217b1c1 --- /dev/null +++ b/Pods/Pods.xcodeproj/xcuserdata/outeyi.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,32 @@ + + + + + SchemeUserState + + CocoaSecurity.xcscheme + + isShown + + orderHint + 0 + + JSONModel.xcscheme + + isShown + + orderHint + 1 + + Pods-goodpk.xcscheme + + isShown + + orderHint + 2 + + + SuppressBuildableAutocreation + + + diff --git a/Pods/Target Support Files/CocoaSecurity/CocoaSecurity-Info.plist b/Pods/Target Support Files/CocoaSecurity/CocoaSecurity-Info.plist new file mode 100644 index 0000000..2e6c90d --- /dev/null +++ b/Pods/Target Support Files/CocoaSecurity/CocoaSecurity-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.2.4 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/CocoaSecurity/CocoaSecurity-dummy.m b/Pods/Target Support Files/CocoaSecurity/CocoaSecurity-dummy.m new file mode 100644 index 0000000..1f55c71 --- /dev/null +++ b/Pods/Target Support Files/CocoaSecurity/CocoaSecurity-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_CocoaSecurity : NSObject +@end +@implementation PodsDummy_CocoaSecurity +@end diff --git a/Pods/Target Support Files/CocoaSecurity/CocoaSecurity-prefix.pch b/Pods/Target Support Files/CocoaSecurity/CocoaSecurity-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Pods/Target Support Files/CocoaSecurity/CocoaSecurity-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/CocoaSecurity/CocoaSecurity-umbrella.h b/Pods/Target Support Files/CocoaSecurity/CocoaSecurity-umbrella.h new file mode 100644 index 0000000..4346683 --- /dev/null +++ b/Pods/Target Support Files/CocoaSecurity/CocoaSecurity-umbrella.h @@ -0,0 +1,18 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "CocoaSecurity.h" +#import "Base64.h" + +FOUNDATION_EXPORT double CocoaSecurityVersionNumber; +FOUNDATION_EXPORT const unsigned char CocoaSecurityVersionString[]; + diff --git a/Pods/Target Support Files/CocoaSecurity/CocoaSecurity.modulemap b/Pods/Target Support Files/CocoaSecurity/CocoaSecurity.modulemap new file mode 100644 index 0000000..02f9525 --- /dev/null +++ b/Pods/Target Support Files/CocoaSecurity/CocoaSecurity.modulemap @@ -0,0 +1,6 @@ +framework module CocoaSecurity { + umbrella header "CocoaSecurity-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/CocoaSecurity/CocoaSecurity.xcconfig b/Pods/Target Support Files/CocoaSecurity/CocoaSecurity.xcconfig new file mode 100644 index 0000000..974bea0 --- /dev/null +++ b/Pods/Target Support Files/CocoaSecurity/CocoaSecurity.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/CocoaSecurity +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/CocoaSecurity +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/JSONModel/JSONModel-Info.plist b/Pods/Target Support Files/JSONModel/JSONModel-Info.plist new file mode 100644 index 0000000..7d91f91 --- /dev/null +++ b/Pods/Target Support Files/JSONModel/JSONModel-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.8.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/JSONModel/JSONModel-dummy.m b/Pods/Target Support Files/JSONModel/JSONModel-dummy.m new file mode 100644 index 0000000..a968b12 --- /dev/null +++ b/Pods/Target Support Files/JSONModel/JSONModel-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_JSONModel : NSObject +@end +@implementation PodsDummy_JSONModel +@end diff --git a/Pods/Target Support Files/JSONModel/JSONModel-prefix.pch b/Pods/Target Support Files/JSONModel/JSONModel-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Pods/Target Support Files/JSONModel/JSONModel-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/JSONModel/JSONModel-umbrella.h b/Pods/Target Support Files/JSONModel/JSONModel-umbrella.h new file mode 100644 index 0000000..a6ea263 --- /dev/null +++ b/Pods/Target Support Files/JSONModel/JSONModel-umbrella.h @@ -0,0 +1,25 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "JSONModel.h" +#import "JSONModelClassProperty.h" +#import "JSONModelError.h" +#import "JSONModelLib.h" +#import "JSONAPI.h" +#import "JSONHTTPClient.h" +#import "JSONModel+networking.h" +#import "JSONKeyMapper.h" +#import "JSONValueTransformer.h" + +FOUNDATION_EXPORT double JSONModelVersionNumber; +FOUNDATION_EXPORT const unsigned char JSONModelVersionString[]; + diff --git a/Pods/Target Support Files/JSONModel/JSONModel.modulemap b/Pods/Target Support Files/JSONModel/JSONModel.modulemap new file mode 100644 index 0000000..ab6c3cb --- /dev/null +++ b/Pods/Target Support Files/JSONModel/JSONModel.modulemap @@ -0,0 +1,6 @@ +framework module JSONModel { + umbrella header "JSONModel-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/JSONModel/JSONModel.xcconfig b/Pods/Target Support Files/JSONModel/JSONModel.xcconfig new file mode 100644 index 0000000..61cf101 --- /dev/null +++ b/Pods/Target Support Files/JSONModel/JSONModel.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/JSONModel +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/JSONModel +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-Info.plist b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-Info.plist new file mode 100644 index 0000000..2243fe6 --- /dev/null +++ b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-acknowledgements.markdown b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-acknowledgements.markdown new file mode 100644 index 0000000..33fdcc1 --- /dev/null +++ b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-acknowledgements.markdown @@ -0,0 +1,37 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## CocoaSecurity + +The MIT License (MIT) +Copyright (c) 2013 Kelp https://github.com/kelp404 + +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. + + +## JSONModel + +Copyright (c) 2012-2016 Marin Todorov and JSONModel 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. + +Generated by CocoaPods - https://cocoapods.org diff --git a/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-acknowledgements.plist b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-acknowledgements.plist new file mode 100644 index 0000000..e5ded20 --- /dev/null +++ b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-acknowledgements.plist @@ -0,0 +1,75 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + The MIT License (MIT) +Copyright (c) 2013 Kelp https://github.com/kelp404 + +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. + + License + MIT + Title + CocoaSecurity + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2012-2016 Marin Todorov and JSONModel 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. + + License + MIT + Title + JSONModel + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-dummy.m b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-dummy.m new file mode 100644 index 0000000..19370dc --- /dev/null +++ b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_goodpk : NSObject +@end +@implementation PodsDummy_Pods_goodpk +@end diff --git a/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks-Debug-input-files.xcfilelist b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks-Debug-input-files.xcfilelist new file mode 100644 index 0000000..96a909d --- /dev/null +++ b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks-Debug-input-files.xcfilelist @@ -0,0 +1,3 @@ +${PODS_ROOT}/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks.sh +${BUILT_PRODUCTS_DIR}/CocoaSecurity/CocoaSecurity.framework +${BUILT_PRODUCTS_DIR}/JSONModel/JSONModel.framework \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks-Debug-output-files.xcfilelist b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks-Debug-output-files.xcfilelist new file mode 100644 index 0000000..40200cd --- /dev/null +++ b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks-Debug-output-files.xcfilelist @@ -0,0 +1,2 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CocoaSecurity.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JSONModel.framework \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks-Release-input-files.xcfilelist b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks-Release-input-files.xcfilelist new file mode 100644 index 0000000..96a909d --- /dev/null +++ b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks-Release-input-files.xcfilelist @@ -0,0 +1,3 @@ +${PODS_ROOT}/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks.sh +${BUILT_PRODUCTS_DIR}/CocoaSecurity/CocoaSecurity.framework +${BUILT_PRODUCTS_DIR}/JSONModel/JSONModel.framework \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks-Release-output-files.xcfilelist b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks-Release-output-files.xcfilelist new file mode 100644 index 0000000..40200cd --- /dev/null +++ b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks-Release-output-files.xcfilelist @@ -0,0 +1,2 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CocoaSecurity.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JSONModel.framework \ No newline at end of file diff --git a/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks.sh b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks.sh new file mode 100755 index 0000000..23cfce5 --- /dev/null +++ b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks.sh @@ -0,0 +1,173 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +function on_error { + echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" +} +trap 'on_error $LINENO' ERR + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + elif [ -L "${binary}" ]; then + echo "Destination binary is symlinked..." + dirname="$(dirname "${binary}")" + binary="${dirname}/$(readlink "${binary}")" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} + +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + if [ -r "$source" ]; then + # Copy the dSYM into a the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .framework.dSYM "$source")" + binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then + strip_invalid_archs "$binary" + fi + + if [[ $STRIP_BINARY_RETVAL == 1 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" + fi + fi +} + +# Copies the bcsymbolmap files of a vendored framework +install_bcsymbolmap() { + local bcsymbolmap_path="$1" + local destination="${BUILT_PRODUCTS_DIR}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identity + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + STRIP_BINARY_RETVAL=0 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=1 +} + + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/CocoaSecurity/CocoaSecurity.framework" + install_framework "${BUILT_PRODUCTS_DIR}/JSONModel/JSONModel.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/CocoaSecurity/CocoaSecurity.framework" + install_framework "${BUILT_PRODUCTS_DIR}/JSONModel/JSONModel.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-umbrella.h b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-umbrella.h new file mode 100644 index 0000000..27cd662 --- /dev/null +++ b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_goodpkVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_goodpkVersionString[]; + diff --git a/Pods/Target Support Files/Pods-goodpk/Pods-goodpk.debug.xcconfig b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk.debug.xcconfig new file mode 100644 index 0000000..329e97a --- /dev/null +++ b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk.debug.xcconfig @@ -0,0 +1,10 @@ +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/CocoaSecurity" "${PODS_CONFIGURATION_BUILD_DIR}/JSONModel" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/CocoaSecurity/CocoaSecurity.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JSONModel/JSONModel.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -framework "CocoaSecurity" -framework "JSONModel" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Pods/Target Support Files/Pods-goodpk/Pods-goodpk.modulemap b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk.modulemap new file mode 100644 index 0000000..9477643 --- /dev/null +++ b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk.modulemap @@ -0,0 +1,6 @@ +framework module Pods_goodpk { + umbrella header "Pods-goodpk-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/Pods-goodpk/Pods-goodpk.release.xcconfig b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk.release.xcconfig new file mode 100644 index 0000000..329e97a --- /dev/null +++ b/Pods/Target Support Files/Pods-goodpk/Pods-goodpk.release.xcconfig @@ -0,0 +1,10 @@ +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/CocoaSecurity" "${PODS_CONFIGURATION_BUILD_DIR}/JSONModel" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/CocoaSecurity/CocoaSecurity.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JSONModel/JSONModel.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -framework "CocoaSecurity" -framework "JSONModel" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/goodpk.xcodeproj/project.pbxproj b/goodpk.xcodeproj/project.pbxproj new file mode 100644 index 0000000..16e219f --- /dev/null +++ b/goodpk.xcodeproj/project.pbxproj @@ -0,0 +1,532 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXBuildFile section */ + 53230B4F242466AD00F372DE /* LockCar.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 53230B4E242466AD00F372DE /* LockCar.storyboard */; }; + 53230B52242466C200F372DE /* LockCarViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53230B51242466C200F372DE /* LockCarViewController.m */; }; + 53230B562424BEB500F372DE /* InquireCarModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 53230B552424BEB500F372DE /* InquireCarModel.m */; }; + 53777768249CC7F2004DF2DC /* Util.m in Sources */ = {isa = PBXBuildFile; fileRef = 53777767249CC7F2004DF2DC /* Util.m */; }; + 53850C3323F27DC40091D8C0 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 53850C3223F27DC40091D8C0 /* AppDelegate.m */; }; + 53850C3623F27DC40091D8C0 /* SceneDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 53850C3523F27DC40091D8C0 /* SceneDelegate.m */; }; + 53850C3923F27DC40091D8C0 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53850C3823F27DC40091D8C0 /* ViewController.m */; }; + 53850C3C23F27DC40091D8C0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 53850C3A23F27DC40091D8C0 /* Main.storyboard */; }; + 53850C3E23F27DC60091D8C0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 53850C3D23F27DC60091D8C0 /* Assets.xcassets */; }; + 53850C4123F27DC60091D8C0 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 53850C3F23F27DC60091D8C0 /* LaunchScreen.storyboard */; }; + 53850C4423F27DC60091D8C0 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 53850C4323F27DC60091D8C0 /* main.m */; }; + 53850C4E23F280310091D8C0 /* CarSecurityViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53850C4D23F280310091D8C0 /* CarSecurityViewController.m */; }; + 53850C5123F280470091D8C0 /* InquireCarViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53850C5023F280470091D8C0 /* InquireCarViewController.m */; }; + 53850C5423F2805D0091D8C0 /* HelpInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53850C5323F2805D0091D8C0 /* HelpInfoViewController.m */; }; + 53850C5723F2806D0091D8C0 /* PaymentViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53850C5623F2806D0091D8C0 /* PaymentViewController.m */; }; + 53850C5923F283950091D8C0 /* Help.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 53850C5823F283950091D8C0 /* Help.storyboard */; }; + 53850C5B23F284460091D8C0 /* InquireCar.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 53850C5A23F284460091D8C0 /* InquireCar.storyboard */; }; + 53850C5D23F284950091D8C0 /* CarSecurity.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 53850C5C23F284950091D8C0 /* CarSecurity.storyboard */; }; + 53850C5F23F284CC0091D8C0 /* Payment.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 53850C5E23F284CC0091D8C0 /* Payment.storyboard */; }; + 53BF5FC524518E4800E8B623 /* CarSecurityModdel.m in Sources */ = {isa = PBXBuildFile; fileRef = 53BF5FC424518E4800E8B623 /* CarSecurityModdel.m */; }; + 53BF5FC82451D3ED00E8B623 /* LockModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 53BF5FC72451D3ED00E8B623 /* LockModel.m */; }; + 53EB64CA24AF2DE4008E5101 /* server.cer in Resources */ = {isa = PBXBuildFile; fileRef = 53EB64C924AF2DE4008E5101 /* server.cer */; }; + B75B199D6FB5441056DEDE4F /* Pods_goodpk.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B5DA4EF16523C94F30CBEC3 /* Pods_goodpk.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 50222DC0D658ABDD423B5819 /* Pods-goodpk.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-goodpk.debug.xcconfig"; path = "Target Support Files/Pods-goodpk/Pods-goodpk.debug.xcconfig"; sourceTree = ""; }; + 51376D9296BE3352E05D52A0 /* Pods-goodpk.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-goodpk.release.xcconfig"; path = "Target Support Files/Pods-goodpk/Pods-goodpk.release.xcconfig"; sourceTree = ""; }; + 53230B4E242466AD00F372DE /* LockCar.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LockCar.storyboard; sourceTree = ""; }; + 53230B50242466C200F372DE /* LockCarViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LockCarViewController.h; sourceTree = ""; }; + 53230B51242466C200F372DE /* LockCarViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LockCarViewController.m; sourceTree = ""; }; + 53230B542424BEB500F372DE /* InquireCarModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InquireCarModel.h; sourceTree = ""; }; + 53230B552424BEB500F372DE /* InquireCarModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InquireCarModel.m; sourceTree = ""; }; + 53777766249CC7F2004DF2DC /* Util.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Util.h; sourceTree = ""; }; + 53777767249CC7F2004DF2DC /* Util.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Util.m; sourceTree = ""; }; + 53850C2E23F27DC40091D8C0 /* CAR IN! 智慧停車.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "CAR IN! 智慧停車.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 53850C3123F27DC40091D8C0 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 53850C3223F27DC40091D8C0 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 53850C3423F27DC40091D8C0 /* SceneDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SceneDelegate.h; sourceTree = ""; }; + 53850C3523F27DC40091D8C0 /* SceneDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SceneDelegate.m; sourceTree = ""; }; + 53850C3723F27DC40091D8C0 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + 53850C3823F27DC40091D8C0 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; + 53850C3B23F27DC40091D8C0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 53850C3D23F27DC60091D8C0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 53850C4023F27DC60091D8C0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 53850C4223F27DC60091D8C0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 53850C4323F27DC60091D8C0 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 53850C4C23F280310091D8C0 /* CarSecurityViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CarSecurityViewController.h; sourceTree = ""; }; + 53850C4D23F280310091D8C0 /* CarSecurityViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CarSecurityViewController.m; sourceTree = ""; }; + 53850C4F23F280470091D8C0 /* InquireCarViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InquireCarViewController.h; sourceTree = ""; }; + 53850C5023F280470091D8C0 /* InquireCarViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InquireCarViewController.m; sourceTree = ""; }; + 53850C5223F2805D0091D8C0 /* HelpInfoViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HelpInfoViewController.h; sourceTree = ""; }; + 53850C5323F2805D0091D8C0 /* HelpInfoViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HelpInfoViewController.m; sourceTree = ""; }; + 53850C5523F2806D0091D8C0 /* PaymentViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PaymentViewController.h; sourceTree = ""; }; + 53850C5623F2806D0091D8C0 /* PaymentViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PaymentViewController.m; sourceTree = ""; }; + 53850C5823F283950091D8C0 /* Help.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Help.storyboard; sourceTree = ""; }; + 53850C5A23F284460091D8C0 /* InquireCar.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = InquireCar.storyboard; sourceTree = ""; }; + 53850C5C23F284950091D8C0 /* CarSecurity.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = CarSecurity.storyboard; sourceTree = ""; }; + 53850C5E23F284CC0091D8C0 /* Payment.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Payment.storyboard; sourceTree = ""; }; + 53BF5FC324518E4800E8B623 /* CarSecurityModdel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CarSecurityModdel.h; sourceTree = ""; }; + 53BF5FC424518E4800E8B623 /* CarSecurityModdel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CarSecurityModdel.m; sourceTree = ""; }; + 53BF5FC62451D3ED00E8B623 /* LockModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LockModel.h; sourceTree = ""; }; + 53BF5FC72451D3ED00E8B623 /* LockModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LockModel.m; sourceTree = ""; }; + 53EB64C924AF2DE4008E5101 /* server.cer */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = server.cer; sourceTree = ""; }; + 7B5DA4EF16523C94F30CBEC3 /* Pods_goodpk.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_goodpk.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 53850C2B23F27DC40091D8C0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B75B199D6FB5441056DEDE4F /* Pods_goodpk.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 53230B532424BE7100F372DE /* Bean */ = { + isa = PBXGroup; + children = ( + 53230B542424BEB500F372DE /* InquireCarModel.h */, + 53230B552424BEB500F372DE /* InquireCarModel.m */, + 53BF5FC324518E4800E8B623 /* CarSecurityModdel.h */, + 53BF5FC424518E4800E8B623 /* CarSecurityModdel.m */, + 53BF5FC62451D3ED00E8B623 /* LockModel.h */, + 53BF5FC72451D3ED00E8B623 /* LockModel.m */, + ); + path = Bean; + sourceTree = ""; + }; + 53850C2523F27DC40091D8C0 = { + isa = PBXGroup; + children = ( + 53850C3023F27DC40091D8C0 /* goodpk */, + 53850C2F23F27DC40091D8C0 /* Products */, + 9DC7D1D2CF09743917B76036 /* Pods */, + E62B54A7E74DF9F27B1AF011 /* Frameworks */, + ); + sourceTree = ""; + }; + 53850C2F23F27DC40091D8C0 /* Products */ = { + isa = PBXGroup; + children = ( + 53850C2E23F27DC40091D8C0 /* CAR IN! 智慧停車.app */, + ); + name = Products; + sourceTree = ""; + }; + 53850C3023F27DC40091D8C0 /* goodpk */ = { + isa = PBXGroup; + children = ( + 53EB64C924AF2DE4008E5101 /* server.cer */, + 53230B532424BE7100F372DE /* Bean */, + 53850C6023F28D6A0091D8C0 /* Util */, + 53850C4B23F27EB20091D8C0 /* StoryBoard */, + 53850C4A23F27E980091D8C0 /* ViewController */, + 53850C3123F27DC40091D8C0 /* AppDelegate.h */, + 53850C3223F27DC40091D8C0 /* AppDelegate.m */, + 53850C3423F27DC40091D8C0 /* SceneDelegate.h */, + 53850C3523F27DC40091D8C0 /* SceneDelegate.m */, + 53850C3D23F27DC60091D8C0 /* Assets.xcassets */, + 53850C3F23F27DC60091D8C0 /* LaunchScreen.storyboard */, + 53850C4223F27DC60091D8C0 /* Info.plist */, + 53850C4323F27DC60091D8C0 /* main.m */, + ); + path = goodpk; + sourceTree = ""; + }; + 53850C4A23F27E980091D8C0 /* ViewController */ = { + isa = PBXGroup; + children = ( + 53850C3723F27DC40091D8C0 /* ViewController.h */, + 53850C3823F27DC40091D8C0 /* ViewController.m */, + 53850C4C23F280310091D8C0 /* CarSecurityViewController.h */, + 53850C4D23F280310091D8C0 /* CarSecurityViewController.m */, + 53850C4F23F280470091D8C0 /* InquireCarViewController.h */, + 53850C5023F280470091D8C0 /* InquireCarViewController.m */, + 53850C5223F2805D0091D8C0 /* HelpInfoViewController.h */, + 53850C5323F2805D0091D8C0 /* HelpInfoViewController.m */, + 53850C5523F2806D0091D8C0 /* PaymentViewController.h */, + 53850C5623F2806D0091D8C0 /* PaymentViewController.m */, + 53230B50242466C200F372DE /* LockCarViewController.h */, + 53230B51242466C200F372DE /* LockCarViewController.m */, + ); + path = ViewController; + sourceTree = ""; + }; + 53850C4B23F27EB20091D8C0 /* StoryBoard */ = { + isa = PBXGroup; + children = ( + 53850C3A23F27DC40091D8C0 /* Main.storyboard */, + 53850C5823F283950091D8C0 /* Help.storyboard */, + 53850C5A23F284460091D8C0 /* InquireCar.storyboard */, + 53850C5C23F284950091D8C0 /* CarSecurity.storyboard */, + 53850C5E23F284CC0091D8C0 /* Payment.storyboard */, + 53230B4E242466AD00F372DE /* LockCar.storyboard */, + ); + path = StoryBoard; + sourceTree = ""; + }; + 53850C6023F28D6A0091D8C0 /* Util */ = { + isa = PBXGroup; + children = ( + 53777766249CC7F2004DF2DC /* Util.h */, + 53777767249CC7F2004DF2DC /* Util.m */, + ); + path = Util; + sourceTree = ""; + }; + 9DC7D1D2CF09743917B76036 /* Pods */ = { + isa = PBXGroup; + children = ( + 50222DC0D658ABDD423B5819 /* Pods-goodpk.debug.xcconfig */, + 51376D9296BE3352E05D52A0 /* Pods-goodpk.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + E62B54A7E74DF9F27B1AF011 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 7B5DA4EF16523C94F30CBEC3 /* Pods_goodpk.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 53850C2D23F27DC40091D8C0 /* goodpk */ = { + isa = PBXNativeTarget; + buildConfigurationList = 53850C4723F27DC60091D8C0 /* Build configuration list for PBXNativeTarget "goodpk" */; + buildPhases = ( + 5E1D96517A85F53895056B7A /* [CP] Check Pods Manifest.lock */, + 53850C2A23F27DC40091D8C0 /* Sources */, + 53850C2B23F27DC40091D8C0 /* Frameworks */, + 53850C2C23F27DC40091D8C0 /* Resources */, + CF6B61D1A98EE52F601A710A /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = goodpk; + productName = goodpk; + productReference = 53850C2E23F27DC40091D8C0 /* CAR IN! 智慧停車.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 53850C2623F27DC40091D8C0 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1130; + ORGANIZATIONNAME = Altob; + TargetAttributes = { + 53850C2D23F27DC40091D8C0 = { + CreatedOnToolsVersion = 11.3.1; + }; + }; + }; + buildConfigurationList = 53850C2923F27DC40091D8C0 /* Build configuration list for PBXProject "goodpk" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 53850C2523F27DC40091D8C0; + productRefGroup = 53850C2F23F27DC40091D8C0 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 53850C2D23F27DC40091D8C0 /* goodpk */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 53850C2C23F27DC40091D8C0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 53230B4F242466AD00F372DE /* LockCar.storyboard in Resources */, + 53850C4123F27DC60091D8C0 /* LaunchScreen.storyboard in Resources */, + 53850C5F23F284CC0091D8C0 /* Payment.storyboard in Resources */, + 53850C5923F283950091D8C0 /* Help.storyboard in Resources */, + 53850C3E23F27DC60091D8C0 /* Assets.xcassets in Resources */, + 53EB64CA24AF2DE4008E5101 /* server.cer in Resources */, + 53850C3C23F27DC40091D8C0 /* Main.storyboard in Resources */, + 53850C5B23F284460091D8C0 /* InquireCar.storyboard in Resources */, + 53850C5D23F284950091D8C0 /* CarSecurity.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 5E1D96517A85F53895056B7A /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-goodpk-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + CF6B61D1A98EE52F601A710A /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-goodpk/Pods-goodpk-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 53850C2A23F27DC40091D8C0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 53777768249CC7F2004DF2DC /* Util.m in Sources */, + 53BF5FC82451D3ED00E8B623 /* LockModel.m in Sources */, + 53850C4E23F280310091D8C0 /* CarSecurityViewController.m in Sources */, + 53230B52242466C200F372DE /* LockCarViewController.m in Sources */, + 53230B562424BEB500F372DE /* InquireCarModel.m in Sources */, + 53850C5123F280470091D8C0 /* InquireCarViewController.m in Sources */, + 53850C3923F27DC40091D8C0 /* ViewController.m in Sources */, + 53850C3323F27DC40091D8C0 /* AppDelegate.m in Sources */, + 53850C4423F27DC60091D8C0 /* main.m in Sources */, + 53850C5423F2805D0091D8C0 /* HelpInfoViewController.m in Sources */, + 53850C3623F27DC40091D8C0 /* SceneDelegate.m in Sources */, + 53BF5FC524518E4800E8B623 /* CarSecurityModdel.m in Sources */, + 53850C5723F2806D0091D8C0 /* PaymentViewController.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 53850C3A23F27DC40091D8C0 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 53850C3B23F27DC40091D8C0 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 53850C3F23F27DC60091D8C0 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 53850C4023F27DC60091D8C0 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 53850C4523F27DC60091D8C0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 53850C4623F27DC60091D8C0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 53850C4823F27DC60091D8C0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 50222DC0D658ABDD423B5819 /* Pods-goodpk.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 10; + DEVELOPMENT_TEAM = GL452P8MRA; + INFOPLIST_FILE = goodpk/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.54; + PRODUCT_BUNDLE_IDENTIFIER = tw.com.altob.goodpk.carin; + PRODUCT_NAME = "CAR IN! 智慧停車"; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; + 53850C4923F27DC60091D8C0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 51376D9296BE3352E05D52A0 /* Pods-goodpk.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 10; + DEVELOPMENT_TEAM = GL452P8MRA; + INFOPLIST_FILE = goodpk/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.54; + PRODUCT_BUNDLE_IDENTIFIER = tw.com.altob.goodpk.carin; + PRODUCT_NAME = "CAR IN! 智慧停車"; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 53850C2923F27DC40091D8C0 /* Build configuration list for PBXProject "goodpk" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 53850C4523F27DC60091D8C0 /* Debug */, + 53850C4623F27DC60091D8C0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 53850C4723F27DC60091D8C0 /* Build configuration list for PBXNativeTarget "goodpk" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 53850C4823F27DC60091D8C0 /* Debug */, + 53850C4923F27DC60091D8C0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 53850C2623F27DC40091D8C0 /* Project object */; +} diff --git a/goodpk.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/goodpk.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..a6cd03a --- /dev/null +++ b/goodpk.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/goodpk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/goodpk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/goodpk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/goodpk.xcodeproj/project.xcworkspace/xcuserdata/outeyi.xcuserdatad/IDEFindNavigatorScopes.plist b/goodpk.xcodeproj/project.xcworkspace/xcuserdata/outeyi.xcuserdatad/IDEFindNavigatorScopes.plist new file mode 100644 index 0000000..5dd5da8 --- /dev/null +++ b/goodpk.xcodeproj/project.xcworkspace/xcuserdata/outeyi.xcuserdatad/IDEFindNavigatorScopes.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/goodpk.xcodeproj/project.xcworkspace/xcuserdata/outeyi.xcuserdatad/UserInterfaceState.xcuserstate b/goodpk.xcodeproj/project.xcworkspace/xcuserdata/outeyi.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..e335a2e Binary files /dev/null and b/goodpk.xcodeproj/project.xcworkspace/xcuserdata/outeyi.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/goodpk.xcodeproj/xcuserdata/outeyi.xcuserdatad/xcschemes/xcschememanagement.plist b/goodpk.xcodeproj/xcuserdata/outeyi.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..3d24fd6 --- /dev/null +++ b/goodpk.xcodeproj/xcuserdata/outeyi.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + goodpk.xcscheme_^#shared#^_ + + orderHint + 3 + + + + diff --git a/goodpk.xcworkspace/contents.xcworkspacedata b/goodpk.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..eb3af07 --- /dev/null +++ b/goodpk.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/goodpk.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/goodpk.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/goodpk.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/goodpk.xcworkspace/xcuserdata/outeyi.xcuserdatad/IDEFindNavigatorScopes.plist b/goodpk.xcworkspace/xcuserdata/outeyi.xcuserdatad/IDEFindNavigatorScopes.plist new file mode 100644 index 0000000..5dd5da8 --- /dev/null +++ b/goodpk.xcworkspace/xcuserdata/outeyi.xcuserdatad/IDEFindNavigatorScopes.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/goodpk.xcworkspace/xcuserdata/outeyi.xcuserdatad/UserInterfaceState.xcuserstate b/goodpk.xcworkspace/xcuserdata/outeyi.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..1908dd1 Binary files /dev/null and b/goodpk.xcworkspace/xcuserdata/outeyi.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/goodpk.xcworkspace/xcuserdata/outeyi.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/goodpk.xcworkspace/xcuserdata/outeyi.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..3d960a7 --- /dev/null +++ b/goodpk.xcworkspace/xcuserdata/outeyi.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/goodpk/AppDelegate.h b/goodpk/AppDelegate.h new file mode 100644 index 0000000..cefdf25 --- /dev/null +++ b/goodpk/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// goodpk +// +// Created by 歐特儀 on 2020/2/11. +// Copyright © 2020 Altob. All rights reserved. +// + +#import + +@interface AppDelegate : UIResponder +@property (strong, nonatomic) UIWindow * window; + +@end + diff --git a/goodpk/AppDelegate.m b/goodpk/AppDelegate.m new file mode 100644 index 0000000..11dcfc0 --- /dev/null +++ b/goodpk/AppDelegate.m @@ -0,0 +1,82 @@ +// +// AppDelegate.m +// goodpk +// +// Created by 歐特儀 on 2020/2/11. +// Copyright © 2020 Altob. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () +@property NSUserDefaults* defaults; + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + + return YES; +} + + +#pragma mark - UISceneSession lifecycle + + +- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role]; +} + + +- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet *)sceneSessions { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. +} + +- (void)applicationDidBecomeActive:(UIScene *)scene { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + self.defaults = [NSUserDefaults standardUserDefaults]; + if ([self.defaults boolForKey:@"notFirstRun"]) { + [self.window.rootViewController dismissViewControllerAnimated:YES completion:NULL]; + } +} + + +- (void)applicationWillResignActive:(UIScene *)scene { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + self.defaults = [NSUserDefaults standardUserDefaults]; + if ([self.defaults boolForKey:@"notFirstRun"]) { + UIViewController *blankViewController = [UIViewController new]; + blankViewController.view.backgroundColor = [UIColor blackColor]; + + [self.window.rootViewController presentViewController:blankViewController animated:YES completion:NULL]; + } +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + self.defaults = [NSUserDefaults standardUserDefaults]; + if ([self.defaults boolForKey:@"notFirstRun"]) { + UIViewController *blankViewController = [UIViewController new]; + blankViewController.view.backgroundColor = [UIColor blackColor]; + + [self.window.rootViewController presentViewController:blankViewController animated:YES completion:NULL]; + } +} + +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + self.defaults = [NSUserDefaults standardUserDefaults]; + if ([self.defaults boolForKey:@"notFirstRun"]) { + [self.window.rootViewController dismissViewControllerAnimated:YES completion:NULL]; + } +} +@end diff --git a/goodpk/Assets.xcassets/AppIcon.appiconset/Contents.json b/goodpk/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..728e6c3 --- /dev/null +++ b/goodpk/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images": [ + { + "size": "20x20", + "idiom": "iphone", + "filename": "icon-20@2x.png", + "scale": "2x" + }, + { + "size": "20x20", + "idiom": "iphone", + "filename": "icon-20@3x.png", + "scale": "3x" + }, + { + "size": "29x29", + "idiom": "iphone", + "filename": "icon-29.png", + "scale": "1x" + }, + { + "size": "29x29", + "idiom": "iphone", + "filename": "icon-29@2x.png", + "scale": "2x" + }, + { + "size": "29x29", + "idiom": "iphone", + "filename": "icon-29@3x.png", + "scale": "3x" + }, + { + "size": "40x40", + "idiom": "iphone", + "filename": "icon-40@2x.png", + "scale": "2x" + }, + { + "size": "40x40", + "idiom": "iphone", + "filename": "icon-40@3x.png", + "scale": "3x" + }, + { + "size": "60x60", + "idiom": "iphone", + "filename": "icon-60@2x.png", + "scale": "2x" + }, + { + "size": "60x60", + "idiom": "iphone", + "filename": "icon-60@3x.png", + "scale": "3x" + }, + { + "size": "20x20", + "idiom": "ipad", + "filename": "icon-20-ipad.png", + "scale": "1x" + }, + { + "size": "20x20", + "idiom": "ipad", + "filename": "icon-20@2x-ipad.png", + "scale": "2x" + }, + { + "size": "29x29", + "idiom": "ipad", + "filename": "icon-29-ipad.png", + "scale": "1x" + }, + { + "size": "29x29", + "idiom": "ipad", + "filename": "icon-29@2x-ipad.png", + "scale": "2x" + }, + { + "size": "40x40", + "idiom": "ipad", + "filename": "icon-40.png", + "scale": "1x" + }, + { + "size": "40x40", + "idiom": "ipad", + "filename": "icon-40@2x.png", + "scale": "2x" + }, + { + "size": "76x76", + "idiom": "ipad", + "filename": "icon-76.png", + "scale": "1x" + }, + { + "size": "76x76", + "idiom": "ipad", + "filename": "icon-76@2x.png", + "scale": "2x" + }, + { + "size": "83.5x83.5", + "idiom": "ipad", + "filename": "icon-83.5@2x.png", + "scale": "2x" + }, + { + "size": "1024x1024", + "idiom": "ios-marketing", + "filename": "icon-1024.png", + "scale": "1x" + } + ], + "info": { + "version": 1, + "author": "icon.wuruihong.com" + } +} \ No newline at end of file diff --git a/goodpk/Assets.xcassets/AppIcon.appiconset/icon-1024.png b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-1024.png new file mode 100644 index 0000000..d220fba Binary files /dev/null and b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-1024.png differ diff --git a/goodpk/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png new file mode 100644 index 0000000..8d9e82c Binary files /dev/null and b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png differ diff --git a/goodpk/Assets.xcassets/AppIcon.appiconset/icon-20@2x-ipad.png b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-20@2x-ipad.png new file mode 100644 index 0000000..86d381b Binary files /dev/null and b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-20@2x-ipad.png differ diff --git a/goodpk/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png new file mode 100644 index 0000000..86d381b Binary files /dev/null and b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png differ diff --git a/goodpk/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png new file mode 100644 index 0000000..de1d620 Binary files /dev/null and b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png differ diff --git a/goodpk/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png new file mode 100644 index 0000000..8256815 Binary files /dev/null and b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png differ diff --git a/goodpk/Assets.xcassets/AppIcon.appiconset/icon-29.png b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-29.png new file mode 100644 index 0000000..8256815 Binary files /dev/null and b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-29.png differ diff --git a/goodpk/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png new file mode 100644 index 0000000..49a8c5b Binary files /dev/null and b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png differ diff --git a/goodpk/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png new file mode 100644 index 0000000..49a8c5b Binary files /dev/null and b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png differ diff --git a/goodpk/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png new file mode 100644 index 0000000..66687e4 Binary files /dev/null and b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png differ diff --git a/goodpk/Assets.xcassets/AppIcon.appiconset/icon-40.png b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-40.png new file mode 100644 index 0000000..86d381b Binary files /dev/null and b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-40.png differ diff --git a/goodpk/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png new file mode 100644 index 0000000..9002b72 Binary files /dev/null and b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png differ diff --git a/goodpk/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png new file mode 100644 index 0000000..7bdbeb7 Binary files /dev/null and b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png differ diff --git a/goodpk/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png new file mode 100644 index 0000000..7bdbeb7 Binary files /dev/null and b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png differ diff --git a/goodpk/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png new file mode 100644 index 0000000..2312c47 Binary files /dev/null and b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png differ diff --git a/goodpk/Assets.xcassets/AppIcon.appiconset/icon-76.png b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-76.png new file mode 100644 index 0000000..41b218d Binary files /dev/null and b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-76.png differ diff --git a/goodpk/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png new file mode 100644 index 0000000..e578b23 Binary files /dev/null and b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png differ diff --git a/goodpk/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png new file mode 100644 index 0000000..459b963 Binary files /dev/null and b/goodpk/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png differ diff --git a/goodpk/Assets.xcassets/BackGround.imageset/Contents.json b/goodpk/Assets.xcassets/BackGround.imageset/Contents.json new file mode 100644 index 0000000..b554705 --- /dev/null +++ b/goodpk/Assets.xcassets/BackGround.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "bg_home.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/goodpk/Assets.xcassets/BackGround.imageset/bg_home.jpg b/goodpk/Assets.xcassets/BackGround.imageset/bg_home.jpg new file mode 100644 index 0000000..4a19d95 Binary files /dev/null and b/goodpk/Assets.xcassets/BackGround.imageset/bg_home.jpg differ diff --git a/goodpk/Assets.xcassets/CarIn.imageset/Contents.json b/goodpk/Assets.xcassets/CarIn.imageset/Contents.json new file mode 100644 index 0000000..d9a1eec --- /dev/null +++ b/goodpk/Assets.xcassets/CarIn.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "icon-1024.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/goodpk/Assets.xcassets/CarIn.imageset/icon-1024.png b/goodpk/Assets.xcassets/CarIn.imageset/icon-1024.png new file mode 100644 index 0000000..d220fba Binary files /dev/null and b/goodpk/Assets.xcassets/CarIn.imageset/icon-1024.png differ diff --git a/goodpk/Assets.xcassets/Contents.json b/goodpk/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/goodpk/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/goodpk/Assets.xcassets/Lock_off.imageset/Contents.json b/goodpk/Assets.xcassets/Lock_off.imageset/Contents.json new file mode 100644 index 0000000..5717b98 --- /dev/null +++ b/goodpk/Assets.xcassets/Lock_off.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "page_security_off.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/goodpk/Assets.xcassets/Lock_off.imageset/page_security_off.png b/goodpk/Assets.xcassets/Lock_off.imageset/page_security_off.png new file mode 100644 index 0000000..967106d Binary files /dev/null and b/goodpk/Assets.xcassets/Lock_off.imageset/page_security_off.png differ diff --git a/goodpk/Assets.xcassets/Lock_on.imageset/Contents.json b/goodpk/Assets.xcassets/Lock_on.imageset/Contents.json new file mode 100644 index 0000000..2f79b3f --- /dev/null +++ b/goodpk/Assets.xcassets/Lock_on.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "page_security_on.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/goodpk/Assets.xcassets/Lock_on.imageset/page_security_on.png b/goodpk/Assets.xcassets/Lock_on.imageset/page_security_on.png new file mode 100644 index 0000000..164bad9 Binary files /dev/null and b/goodpk/Assets.xcassets/Lock_on.imageset/page_security_on.png differ diff --git a/goodpk/Assets.xcassets/Lunch.imageset/Contents.json b/goodpk/Assets.xcassets/Lunch.imageset/Contents.json new file mode 100644 index 0000000..110e177 --- /dev/null +++ b/goodpk/Assets.xcassets/Lunch.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "bg_landingpage.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/goodpk/Assets.xcassets/Lunch.imageset/bg_landingpage.jpg b/goodpk/Assets.xcassets/Lunch.imageset/bg_landingpage.jpg new file mode 100644 index 0000000..cd46a42 Binary files /dev/null and b/goodpk/Assets.xcassets/Lunch.imageset/bg_landingpage.jpg differ diff --git a/goodpk/Assets.xcassets/bg.imageset/Contents.json b/goodpk/Assets.xcassets/bg.imageset/Contents.json new file mode 100644 index 0000000..a7f2726 --- /dev/null +++ b/goodpk/Assets.xcassets/bg.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "bg_page.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/goodpk/Assets.xcassets/bg.imageset/bg_page.jpg b/goodpk/Assets.xcassets/bg.imageset/bg_page.jpg new file mode 100644 index 0000000..47d84cf Binary files /dev/null and b/goodpk/Assets.xcassets/bg.imageset/bg_page.jpg differ diff --git a/goodpk/Assets.xcassets/help_background.imageset/Contents.json b/goodpk/Assets.xcassets/help_background.imageset/Contents.json new file mode 100644 index 0000000..b8e5fb7 --- /dev/null +++ b/goodpk/Assets.xcassets/help_background.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "bg_password_02.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/goodpk/Assets.xcassets/help_background.imageset/bg_password_02.png b/goodpk/Assets.xcassets/help_background.imageset/bg_password_02.png new file mode 100644 index 0000000..fb90fc6 Binary files /dev/null and b/goodpk/Assets.xcassets/help_background.imageset/bg_password_02.png differ diff --git a/goodpk/Assets.xcassets/help_icon.imageset/Contents.json b/goodpk/Assets.xcassets/help_icon.imageset/Contents.json new file mode 100644 index 0000000..26dffb9 --- /dev/null +++ b/goodpk/Assets.xcassets/help_icon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "page_help_sos.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/goodpk/Assets.xcassets/help_icon.imageset/page_help_sos.png b/goodpk/Assets.xcassets/help_icon.imageset/page_help_sos.png new file mode 100644 index 0000000..58db71a Binary files /dev/null and b/goodpk/Assets.xcassets/help_icon.imageset/page_help_sos.png differ diff --git a/goodpk/Assets.xcassets/icon_home_nav_member.imageset/Contents.json b/goodpk/Assets.xcassets/icon_home_nav_member.imageset/Contents.json new file mode 100644 index 0000000..2094592 --- /dev/null +++ b/goodpk/Assets.xcassets/icon_home_nav_member.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "icon_home_nav_member.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/goodpk/Assets.xcassets/icon_home_nav_member.imageset/icon_home_nav_member.png b/goodpk/Assets.xcassets/icon_home_nav_member.imageset/icon_home_nav_member.png new file mode 100644 index 0000000..4042ead Binary files /dev/null and b/goodpk/Assets.xcassets/icon_home_nav_member.imageset/icon_home_nav_member.png differ diff --git a/goodpk/Assets.xcassets/icon_home_nav_payment.imageset/Contents.json b/goodpk/Assets.xcassets/icon_home_nav_payment.imageset/Contents.json new file mode 100644 index 0000000..6642fb5 --- /dev/null +++ b/goodpk/Assets.xcassets/icon_home_nav_payment.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "icon_home_nav_payment.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/goodpk/Assets.xcassets/icon_home_nav_payment.imageset/icon_home_nav_payment.png b/goodpk/Assets.xcassets/icon_home_nav_payment.imageset/icon_home_nav_payment.png new file mode 100644 index 0000000..bae21b3 Binary files /dev/null and b/goodpk/Assets.xcassets/icon_home_nav_payment.imageset/icon_home_nav_payment.png differ diff --git a/goodpk/Assets.xcassets/icon_home_nav_search.imageset/Contents.json b/goodpk/Assets.xcassets/icon_home_nav_search.imageset/Contents.json new file mode 100644 index 0000000..3f21cb4 --- /dev/null +++ b/goodpk/Assets.xcassets/icon_home_nav_search.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "icon_home_nav_search.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/goodpk/Assets.xcassets/icon_home_nav_search.imageset/icon_home_nav_search.png b/goodpk/Assets.xcassets/icon_home_nav_search.imageset/icon_home_nav_search.png new file mode 100644 index 0000000..f922966 Binary files /dev/null and b/goodpk/Assets.xcassets/icon_home_nav_search.imageset/icon_home_nav_search.png differ diff --git a/goodpk/Assets.xcassets/icon_home_nav_sos.imageset/Contents.json b/goodpk/Assets.xcassets/icon_home_nav_sos.imageset/Contents.json new file mode 100644 index 0000000..bcecbee --- /dev/null +++ b/goodpk/Assets.xcassets/icon_home_nav_sos.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "icon_home_nav_sos.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/goodpk/Assets.xcassets/icon_home_nav_sos.imageset/icon_home_nav_sos.png b/goodpk/Assets.xcassets/icon_home_nav_sos.imageset/icon_home_nav_sos.png new file mode 100644 index 0000000..c818bb6 Binary files /dev/null and b/goodpk/Assets.xcassets/icon_home_nav_sos.imageset/icon_home_nav_sos.png differ diff --git a/goodpk/Assets.xcassets/title_icon.imageset/Contents.json b/goodpk/Assets.xcassets/title_icon.imageset/Contents.json new file mode 100644 index 0000000..e1ee207 --- /dev/null +++ b/goodpk/Assets.xcassets/title_icon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "page_home_title.9.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/goodpk/Assets.xcassets/title_icon.imageset/page_home_title.9.png b/goodpk/Assets.xcassets/title_icon.imageset/page_home_title.9.png new file mode 100644 index 0000000..a65da9a Binary files /dev/null and b/goodpk/Assets.xcassets/title_icon.imageset/page_home_title.9.png differ diff --git a/goodpk/Base.lproj/LaunchScreen.storyboard b/goodpk/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..db91d6e --- /dev/null +++ b/goodpk/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/goodpk/Bean/CarSecurityModdel.h b/goodpk/Bean/CarSecurityModdel.h new file mode 100644 index 0000000..c61000f --- /dev/null +++ b/goodpk/Bean/CarSecurityModdel.h @@ -0,0 +1,23 @@ +// +// CarSecurityModdel.h +// goodpk +// +// Created by 歐特儀 on 2020/4/23. +// Copyright © 2020 Altob. All rights reserved. +// + +#import +#import "JSONModel.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface CarSecurityModdel : JSONModel +@property NSString *result_code; +@property NSString *result_msg; + +@end + +@implementation CarSecurityModdel +@end + +NS_ASSUME_NONNULL_END diff --git a/goodpk/Bean/CarSecurityModdel.m b/goodpk/Bean/CarSecurityModdel.m new file mode 100644 index 0000000..9d8579b --- /dev/null +++ b/goodpk/Bean/CarSecurityModdel.m @@ -0,0 +1,7 @@ +// +// CarSecurityModdel.m +// goodpk +// +// Created by 歐特儀 on 2020/4/23. +// Copyright © 2020 Altob. All rights reserved. +// diff --git a/goodpk/Bean/InquireCarModel.h b/goodpk/Bean/InquireCarModel.h new file mode 100644 index 0000000..6d9ae5c --- /dev/null +++ b/goodpk/Bean/InquireCarModel.h @@ -0,0 +1,29 @@ +// +// InquireCarModel.h +// goodpk +// +// Created by 歐特儀 on 2020/3/20. +// Copyright © 2020 Altob. All rights reserved. +// + +#import +#import "JSONModel.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface InquireCarModel : JSONModel +@property NSString *num; +@property NSString *in_time; +@property NSString *station_no; +@property NSString *station_name; +@property NSString *image_url; +@property NSString *image_url2; +@property NSString *location_no; +@property NSString *location_name; +@property NSString *result_code; +@end + +@implementation InquireCarModel +@end + +NS_ASSUME_NONNULL_END diff --git a/goodpk/Bean/InquireCarModel.m b/goodpk/Bean/InquireCarModel.m new file mode 100644 index 0000000..3a6f112 --- /dev/null +++ b/goodpk/Bean/InquireCarModel.m @@ -0,0 +1,8 @@ +// +// InquireCarModel.m +// goodpk +// +// Created by 歐特儀 on 2020/3/20. +// Copyright © 2020 Altob. All rights reserved. +// + diff --git a/goodpk/Bean/LockModel.h b/goodpk/Bean/LockModel.h new file mode 100644 index 0000000..9cc592a --- /dev/null +++ b/goodpk/Bean/LockModel.h @@ -0,0 +1,22 @@ +// +// LockModel.h +// goodpk +// +// Created by 歐特儀 on 2020/4/23. +// Copyright © 2020 Altob. All rights reserved. +// + +#import +#import "JSONModel.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface LockModel : JSONModel +@property NSString *result_code; +@property NSString *result_msg; +@end + +@implementation LockModel +@end + +NS_ASSUME_NONNULL_END diff --git a/goodpk/Bean/LockModel.m b/goodpk/Bean/LockModel.m new file mode 100644 index 0000000..606d946 --- /dev/null +++ b/goodpk/Bean/LockModel.m @@ -0,0 +1,8 @@ +// +// LockModel.m +// goodpk +// +// Created by 歐特儀 on 2020/4/23. +// Copyright © 2020 Altob. All rights reserved. +// + diff --git a/goodpk/Info.plist b/goodpk/Info.plist new file mode 100644 index 0000000..5a47ae3 --- /dev/null +++ b/goodpk/Info.plist @@ -0,0 +1,64 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + SceneDelegate + UISceneStoryboardFile + Main + + + + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/goodpk/SceneDelegate.h b/goodpk/SceneDelegate.h new file mode 100644 index 0000000..e099d5a --- /dev/null +++ b/goodpk/SceneDelegate.h @@ -0,0 +1,16 @@ +// +// SceneDelegate.h +// goodpk +// +// Created by 歐特儀 on 2020/2/11. +// Copyright © 2020 Altob. All rights reserved. +// + +#import + +@interface SceneDelegate : UIResponder + +@property (strong, nonatomic) UIWindow * window; + +@end + diff --git a/goodpk/SceneDelegate.m b/goodpk/SceneDelegate.m new file mode 100644 index 0000000..93a814a --- /dev/null +++ b/goodpk/SceneDelegate.m @@ -0,0 +1,77 @@ +#import "SceneDelegate.h" + +@interface SceneDelegate () +@property NSUserDefaults* defaults; + +@end + +@implementation SceneDelegate + + +- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { + // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. + // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. + // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). +} + + +- (void)sceneDidDisconnect:(UIScene *)scene { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). +} + + +- (void)sceneDidBecomeActive:(UIScene *)scene { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + self.defaults = [NSUserDefaults standardUserDefaults]; + if ([self.defaults boolForKey:@"notFirstRun"]) { + [self.window.rootViewController dismissViewControllerAnimated:YES completion:NULL]; + } +} + + +- (void)sceneWillResignActive:(UIScene *)scene { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + + self.defaults = [NSUserDefaults standardUserDefaults]; + + if ([self.defaults boolForKey:@"notFirstRun"]) { + UIViewController *blankViewController = [UIViewController new]; + blankViewController.view.backgroundColor = [UIColor blackColor]; + + [self.window.rootViewController presentViewController:blankViewController animated:YES completion:NULL]; + } +} + + +- (void)sceneWillEnterForeground:(UIScene *)scene { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + self.defaults = [NSUserDefaults standardUserDefaults]; + if ([self.defaults boolForKey:@"notFirstRun"]) { + [self.window.rootViewController dismissViewControllerAnimated:YES completion:NULL]; + } +} + + +- (void)sceneDidEnterBackground:(UIScene *)scene { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. + self.defaults = [NSUserDefaults standardUserDefaults]; + + if ([self.defaults boolForKey:@"notFirstRun"]) { + + UIViewController *blankViewController = [UIViewController new]; + blankViewController.view.backgroundColor = [UIColor blackColor]; + + [self.window.rootViewController presentViewController:blankViewController animated:YES completion:NULL]; + } +} + + +@end diff --git a/goodpk/StoryBoard/Base.lproj/Main.storyboard b/goodpk/StoryBoard/Base.lproj/Main.storyboard new file mode 100644 index 0000000..1180479 --- /dev/null +++ b/goodpk/StoryBoard/Base.lproj/Main.storyboard @@ -0,0 +1,311 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/goodpk/StoryBoard/CarSecurity.storyboard b/goodpk/StoryBoard/CarSecurity.storyboard new file mode 100644 index 0000000..ea97cd0 --- /dev/null +++ b/goodpk/StoryBoard/CarSecurity.storyboard @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/goodpk/StoryBoard/Help.storyboard b/goodpk/StoryBoard/Help.storyboard new file mode 100644 index 0000000..44b5f68 --- /dev/null +++ b/goodpk/StoryBoard/Help.storyboard @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/goodpk/StoryBoard/InquireCar.storyboard b/goodpk/StoryBoard/InquireCar.storyboard new file mode 100644 index 0000000..f39407f --- /dev/null +++ b/goodpk/StoryBoard/InquireCar.storyboard @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/goodpk/StoryBoard/LockCar.storyboard b/goodpk/StoryBoard/LockCar.storyboard new file mode 100644 index 0000000..a269bc6 --- /dev/null +++ b/goodpk/StoryBoard/LockCar.storyboard @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/goodpk/StoryBoard/Payment.storyboard b/goodpk/StoryBoard/Payment.storyboard new file mode 100644 index 0000000..c107043 --- /dev/null +++ b/goodpk/StoryBoard/Payment.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/goodpk/Util/Util.h b/goodpk/Util/Util.h new file mode 100644 index 0000000..134ab55 --- /dev/null +++ b/goodpk/Util/Util.h @@ -0,0 +1,18 @@ +// +// Util.h +// goodpk +// +// Created by 歐特儀 on 2020/6/19. +// Copyright © 2020 Altob. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface Util : NSObject + ++ (NSString*) sha256HashFor:(NSString *)input; +@end + +NS_ASSUME_NONNULL_END diff --git a/goodpk/Util/Util.m b/goodpk/Util/Util.m new file mode 100644 index 0000000..6f56667 --- /dev/null +++ b/goodpk/Util/Util.m @@ -0,0 +1,29 @@ +// +// Util.m +// goodpk +// +// Created by 歐特儀 on 2020/6/19. +// Copyright © 2020 Altob. All rights reserved. +// + +#import "Util.h" +#include + +@implementation Util + ++(NSString*)sha256HashFor:(NSString*)input +{ + const char* str = [input UTF8String]; + unsigned char result[CC_SHA256_DIGEST_LENGTH]; + CC_SHA256(str, strlen(str), result); + + NSMutableString *ret = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH*2]; + for(int i = 0; i + +NS_ASSUME_NONNULL_BEGIN + +@interface CarSecurityViewController : UIViewController +@property NSString* station; +@end + +NS_ASSUME_NONNULL_END diff --git a/goodpk/ViewController/CarSecurityViewController.m b/goodpk/ViewController/CarSecurityViewController.m new file mode 100644 index 0000000..d46bc79 --- /dev/null +++ b/goodpk/ViewController/CarSecurityViewController.m @@ -0,0 +1,246 @@ +// +// CarSecurityViewController.m +// goodpk +// +// Created by 歐特儀 on 2020/2/11. +// Copyright © 2020 Altob. All rights reserved. +// + +#import "CarSecurityViewController.h" +#import +#import "CarSecurityModdel.h" +#import "LockCarViewController.h" +#import "CocoaSecurity.h" +#import "Util.h" + +#define APIURL @"https://cloudservice.altob.com.tw/LockCarSerivce/api/JumpApi" +#define CARSECURITY @"/CARSECURITY?" +#define ALPHANUM @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + +@interface CarSecurityViewController () +@property (weak, nonatomic) IBOutlet UITextField *AcctInput; +@property (weak, nonatomic) IBOutlet UITextField *PwdInput; +@property (weak, nonatomic) IBOutlet UIButton *okBtn; + +@end + +@implementation CarSecurityViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + self.title = @"會員防竊車"; + + [self.okBtn addTarget:self + action:@selector(okButtonClicked:) + forControlEvents:UIControlEventTouchUpInside + ]; + + //注册截圖通知 + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(userDidTakeScreenshot:) + name:UIApplicationUserDidTakeScreenshotNotification object:nil]; + + self.AcctInput.delegate = self; + self.PwdInput.delegate = self; + self.AcctInput.keyboardType = UIKeyboardTypeASCIICapable; + self.PwdInput.keyboardType = UIKeyboardTypeASCIICapable; + +} + +- (BOOL)textField:(UITextField* )textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString* )string +{ + if (textField == self.AcctInput) + { + NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:ALPHANUM] invertedSet]; + NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""]; + if([string isEqualToString:filtered]){ + NSUInteger newLength = [textField.text length] + [string length] - range.length; + return (newLength > 10 ) ? NO : YES; + }else{ + return NO; + } + }else if(textField == self.PwdInput){ + NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:ALPHANUM] invertedSet]; + NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""]; + if([string isEqualToString:filtered]){ + NSUInteger newLength = [textField.text length] + [string length] - range.length; + return (newLength > 20 ) ? NO : YES; + }else{ + return NO; + } + } + else + { + return true; + } + +} + +- (void) okButtonClicked:(id)sender { + if([self.AcctInput.text length] == 0){ + [self showAlert:@"錯誤" :@"請輸入帳號" :nil]; + }else if([self.PwdInput.text length] == 0){ + [self showAlert:@"錯誤" :@"請輸入密碼" :nil]; + }else{ + //打API + [self Login:self.AcctInput.text :self.PwdInput.text]; + } +} + +-(void)showAlert:(NSString *)title :(NSString *)text: (NSInteger *)type{ + + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title + message:text + preferredStyle:UIAlertControllerStyleAlert ]; + + UIAlertAction *sinupAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){ + + }]; + [alertController addAction:sinupAction]; + + [self presentViewController:alertController animated:YES completion:nil]; +} + +-(void) Login:(NSString *)acct :(NSString *)pwd { + + CocoaSecurityResult *Nacct = [CocoaSecurity aesEncrypt:acct key:[Util sha256HashFor:@"Altob"]]; + + NSString *mPwd = [self md5:pwd]; + NSString *status = @"2"; + //NSLog(@"加密字串:%@", [NSString stringWithFormat:@"%@%@%@%@%@", acct, @"i", mPwd, @"iii", status]); + NSString *key = [self md5: [NSString stringWithFormat:@"%@%@%@%@%@", acct, @"i", mPwd, @"iii", status]]; + NSString *carUrl = [NSString stringWithFormat:@"%@%@acct=%@&pwd=%@&status=%@&key=%@&station=%@", APIURL, CARSECURITY, Nacct.base64, mPwd, status, key, self.station]; + + //第一步,创建URL + NSURL *url = [NSURL URLWithString:carUrl]; + //NSDictionary *jsonBodyDict = @{}; + + //NSLog(@"URL: %@", url); + + //第二步,创建请求 + NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10]; + //设置请求方式为POST,默认为GET + [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; + [request setValue:@"Bearer 9a406a82bd551e6ef8e845f42f788af4" forHTTPHeaderField:@"Authorization"]; + [request setHTTPMethod:@"GET"]; + + //设置参数 + //NSData *jsonBodyData = [NSJSONSerialization dataWithJSONObject:jsonBodyDict options:kNilOptions error:nil]; + //[request setHTTPBody:jsonBodyData]; + + //新作法 + NSURLSession *sesson = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil]; + + // 2.创建 NSURLSessionDataTask + NSURLSessionDataTask *dataTask = [sesson dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { + if (error) { + NSLog(@"%@", error); + // error + dispatch_async(dispatch_get_main_queue(), ^{ + [self showAlert: @"注意" : @"您所使用的連線加密(SSL)異常,基於安全考量不提供相關功能。請確認您的連線環境及App下載來源安全。" : 0]; + }); + }else { + // 获得数据后,返回到主线程更新 UI + dispatch_async(dispatch_get_main_queue(), ^{ + NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + CarSecurityModdel *CS = [[CarSecurityModdel alloc] initWithString:responseString error:nil]; + if([CS.result_code isEqual:@"OK"]){ + //鎖車頁面 + UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"LockCar" bundle:[NSBundle mainBundle]]; + LockCarViewController *HelpController = [storyboard instantiateViewControllerWithIdentifier:@"LockCar"]; + HelpController.status = CS.result_msg; + HelpController.acct = acct; + HelpController.pwd = mPwd; + HelpController.station = self.station; + [self.navigationController pushViewController:HelpController animated:YES]; + }else{ + [self showAlert:@"錯誤" :@"登入失敗,請稍後再試" :nil]; + } + }); + } + }]; + // 3.执行 Task + [dataTask resume]; + + /* + //第三步,连接服务器 + NSData *received = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; + + NSString *jsonString = [[NSString alloc]initWithData:received encoding:NSUTF8StringEncoding]; + //NSLog(@"CAR LOGIN:%@", jsonString); + + CarSecurityModdel *CS = [[CarSecurityModdel alloc] initWithString:jsonString error:nil]; + if([CS.result_code isEqual:@"OK"]){ + //鎖車頁面 + UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"LockCar" bundle:[NSBundle mainBundle]]; + LockCarViewController *HelpController = [storyboard instantiateViewControllerWithIdentifier:@"LockCar"]; + HelpController.status = CS.result_msg; + HelpController.acct = acct; + HelpController.pwd = mPwd; + [self.navigationController pushViewController:HelpController animated:YES]; + }else{ + [self showAlert:@"錯誤" :@"登入失敗,請稍後再試" :nil]; + } + */ +} + +- (NSString *) md5:(NSString *) input +{ + const char *cStr = [input UTF8String]; + unsigned char digest[16]; + CC_MD5( cStr, strlen(cStr), digest ); // This is the md5 call + + NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2]; + + for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) + [output appendFormat:@"%02x", digest[i]]; + + return output; + +} + +//截屏响应 +- (void)userDidTakeScreenshot:(NSNotification *)notification +{ + [self showAlert: @"注意" : @"偵測到截圖,請妥善保管截圖,避免重要資訊外流" : 0]; +} + +- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler//通过调用block,来告诉NSURLSession要不要收到这个证书 +{ + // Get remote certificate + SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; + SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0); + + // Set SSL policies for domain name check + NSMutableArray *policies = [NSMutableArray array]; + [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)challenge.protectionSpace.host)]; + SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies); + + // Evaluate server certificate + SecTrustResultType result; + SecTrustEvaluate(serverTrust, &result); + + BOOL certificateIsValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed); + + // Get local and remote cert data + NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate)); + + NSString *hash = [[self doSha256:remoteCertificateData] base64EncodedStringWithOptions:0]; + + // The pinnning check + if ([hash isEqualToString:@"FHloZIw4i6+30lmxrUujLieHlIDpxHySL1niMxvgmpU="] && certificateIsValid) { + NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; + completionHandler(NSURLSessionAuthChallengeUseCredential, credential); + } else { + completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, NULL); + } +} + +- (NSData *)doSha256:(NSData *)dataIn { + NSMutableData *macOut = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH]; + CC_SHA256(dataIn.bytes, dataIn.length, macOut.mutableBytes); + return macOut; +} + +@end diff --git a/goodpk/ViewController/HelpInfoViewController.h b/goodpk/ViewController/HelpInfoViewController.h new file mode 100644 index 0000000..340fad3 --- /dev/null +++ b/goodpk/ViewController/HelpInfoViewController.h @@ -0,0 +1,17 @@ +// +// HelpInfoViewController.h +// goodpk +// +// Created by 歐特儀 on 2020/2/11. +// Copyright © 2020 Altob. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface HelpInfoViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/goodpk/ViewController/HelpInfoViewController.m b/goodpk/ViewController/HelpInfoViewController.m new file mode 100644 index 0000000..4875e8a --- /dev/null +++ b/goodpk/ViewController/HelpInfoViewController.m @@ -0,0 +1,77 @@ +// +// HelpInfoViewController.m +// goodpk +// +// Created by 歐特儀 on 2020/2/11. +// Copyright © 2020 Altob. All rights reserved. +// + +#import "HelpInfoViewController.h" + +@interface HelpInfoViewController () +@property (weak, nonatomic) IBOutlet UIButton *helpBtn; + +@end + +@implementation HelpInfoViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + self.title = @"緊急協助"; + + [self.helpBtn addTarget:self + action:@selector(handleButtonClicked:) + forControlEvents:UIControlEventTouchUpInside + ]; +} + +- (void) handleButtonClicked:(id)sender { + + [self showAlert:@"重要" :@"確定撥打管理室電話?" :nil]; +} + +-(void) callNumber:(NSString *)phoneNum{ + + NSString *telephoneNumber = phoneNum; + NSMutableString * str=[[NSMutableString alloc] initWithFormat:@"tel:%@",telephoneNumber]; + + UIApplication *application = [UIApplication sharedApplication]; + NSURL *URL = [NSURL URLWithString:str]; + + [application openURL:URL options:@{} completionHandler:^(BOOL success) { + //OpenSuccess=选择 呼叫 为 1 选择 取消 为0 + //NSLog(@"OpenSuccess=%d",success); + }]; +} + +-(void)showAlert:(NSString *)title :(NSString *)text: (NSInteger *)type{ + + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title + message:text + preferredStyle:UIAlertControllerStyleAlert ]; + + UIAlertAction *sinupAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){ + [self callNumber:@"0229647078"]; + }]; + [alertController addAction:sinupAction]; + + UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){ + + }]; + [alertController addAction:cancelAction]; + + [self presentViewController:alertController animated:YES completion:nil]; +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/goodpk/ViewController/InquireCarViewController.h b/goodpk/ViewController/InquireCarViewController.h new file mode 100644 index 0000000..fb6c09d --- /dev/null +++ b/goodpk/ViewController/InquireCarViewController.h @@ -0,0 +1,17 @@ +// +// InquireCarViewController.h +// goodpk +// +// Created by 歐特儀 on 2020/2/11. +// Copyright © 2020 Altob. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface InquireCarViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/goodpk/ViewController/InquireCarViewController.m b/goodpk/ViewController/InquireCarViewController.m new file mode 100644 index 0000000..31a9634 --- /dev/null +++ b/goodpk/ViewController/InquireCarViewController.m @@ -0,0 +1,285 @@ +// +// InquireCarViewController.m +// goodpk +// +// Created by 歐特儀 on 2020/2/11. +// Copyright © 2020 Altob. All rights reserved. +// + +#import "InquireCarViewController.h" +#import "InquireCarModel.h" +#import "CocoaSecurity.h" +#import "Util.h" +#import + +#define APIURL @"https://cloudservice.altob.com.tw/LockCarSerivce/api/JumpApi" +#define CARWHERE @"/CARWHERE?carNo=" +#define ALPHANUM @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + +@interface InquireCarViewController () +@property (weak, nonatomic) IBOutlet UIButton *okBtn; +@property (weak, nonatomic) IBOutlet UITextField *inputText; +@property (weak, nonatomic) IBOutlet UIImageView *ImgView; +@property (weak, nonatomic) IBOutlet UILabel *stationName; +@property (weak, nonatomic) IBOutlet UILabel *inTime; +@property (weak, nonatomic) IBOutlet UIView *FootView; + +@end + +@implementation InquireCarViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + self.title = @"車輛位置查詢"; + + [self.okBtn addTarget:self + action:@selector(okButtonClicked:) + forControlEvents:UIControlEventTouchUpInside + ]; + + //注册截圖通知 + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(userDidTakeScreenshot:) + name:UIApplicationUserDidTakeScreenshotNotification object:nil]; + + self.inputText.delegate = self; + self.inputText.keyboardType = UIKeyboardTypeASCIICapable; +} + +- (BOOL)textField:(UITextField* )textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString* )string +{ + if (textField == self.inputText) + { + NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:ALPHANUM] invertedSet]; + NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""]; + if([string isEqualToString:filtered]){ + NSUInteger newLength = [textField.text length] + [string length] - range.length; + return (newLength > 10 ) ? NO : YES; + }else{ + return NO; + } + } + else + { + return true; + } + +} + +- (void) okButtonClicked:(id)sender { + if([self.inputText.text length] > 0){ + [self posCarNo:[self.inputText.text uppercaseStringWithLocale:[NSLocale currentLocale]]]; + [[[UIApplication sharedApplication] keyWindow] endEditing: YES]; + }else{ + [self showAlert:@"錯誤" :@"請輸入車牌" :nil]; + } +} + +-(void) posCarNo:(NSString*)carNo{ + + CocoaSecurityResult *NcarNo = [CocoaSecurity aesEncrypt:carNo key:[Util sha256HashFor:@"Altob"]]; + NSString *carUrl = [NSString stringWithFormat:@"%@%@%@", APIURL,CARWHERE, NcarNo.base64]; + + //第一步,创建URL + NSURL *url = [NSURL URLWithString:carUrl]; + //NSDictionary *jsonBodyDict = @{}; + + //第二步,创建请求 + NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10]; + //设置请求方式为POST,默认为GET + [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; + [request setValue:@"Bearer 9a406a82bd551e6ef8e845f42f788af4" forHTTPHeaderField:@"Authorization"]; + [request setHTTPMethod:@"GET"]; + + //设置参数 + //NSData *jsonBodyData = [NSJSONSerialization dataWithJSONObject:jsonBodyDict options:kNilOptions error:nil]; + //[request setHTTPBody:jsonBodyData]; + + //新作法 + NSURLSession *sesson = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil]; + + // 2.创建 NSURLSessionDataTask + NSURLSessionDataTask *dataTask = [sesson dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { + if (error) { + // error + dispatch_async(dispatch_get_main_queue(), ^{ + [self showAlert: @"注意" : @"您所使用的連線加密(SSL)異常,基於安全考量不提供相關功能。請確認您的連線環境及App下載來源安全。" : 0]; + }); + }else { + // 获得数据后,返回到主线程更新 UI + dispatch_async(dispatch_get_main_queue(), ^{ + NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + InquireCarModel *ICM = [[InquireCarModel alloc] initWithString:responseString error:nil]; + if([ICM.result_code isEqual:@"OK"]){ + + //NSLog(@"參數查詢:%@", ICM.station_name); + //NSLog(@"參數查詢:%@", ICM.in_time); + //NSLog(@"參數查詢:%@", ICM.image_url); + + //顯示UI + [self.FootView setHidden:NO]; + //放資料 + [self.stationName setText:ICM.station_name]; + [self.inTime setText:ICM.in_time]; + + if(ICM.image_url2 != nil && ![ICM.image_url2 isEqualToString:@""]){ + //下載圖片_非同步 + dispatch_async(dispatch_get_global_queue(0,0), ^{ + NSData * data = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:ICM.image_url2]]; + //NSLog(@"參數查詢:%@", data); + if ( data == nil ) + return; + dispatch_async(dispatch_get_main_queue(), ^{ + // WARNING: is the cell still using the same data by this point?? + self.ImgView.image = [UIImage imageWithData: data]; + }); + + }); + }else{ + + //下載圖片_非同步 + dispatch_async(dispatch_get_global_queue(0,0), ^{ + NSData * data = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:ICM.image_url]]; + //NSLog(@"參數查詢:%@", data); + if ( data == nil ) + return; + dispatch_async(dispatch_get_main_queue(), ^{ + // WARNING: is the cell still using the same data by this point?? + self.ImgView.image = [UIImage imageWithData: data]; + }); + + }); + } + + }else { + [self showAlert:@"錯誤" :@"沒有資料,請確認車牌輸入正確或網路連接正常" :nil]; + } + }); + } + }]; + // 3.执行 Task + [dataTask resume]; + + /* + //第三步,连接服务器 + NSData *received = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; + + NSString *jsonString = [[NSString alloc]initWithData:received encoding:NSUTF8StringEncoding]; + //NSLog(@"ticket:%@", jsonString); + + InquireCarModel *ICM = [[InquireCarModel alloc] initWithString:jsonString error:nil]; + if([ICM.result_code isEqual:@"OK"]){ + + //NSLog(@"參數查詢:%@", ICM.station_name); + //NSLog(@"參數查詢:%@", ICM.in_time); + //NSLog(@"參數查詢:%@", ICM.image_url); + + //顯示UI + [self.FootView setHidden:NO]; + //放資料 + [self.stationName setText:ICM.station_name]; + [self.inTime setText:ICM.in_time]; + + if(ICM.image_url2 != nil && ![ICM.image_url2 isEqualToString:@""]){ + //下載圖片_非同步 + dispatch_async(dispatch_get_global_queue(0,0), ^{ + NSData * data = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:ICM.image_url2]]; + //NSLog(@"參數查詢:%@", data); + if ( data == nil ) + return; + dispatch_async(dispatch_get_main_queue(), ^{ + // WARNING: is the cell still using the same data by this point?? + self.ImgView.image = [UIImage imageWithData: data]; + }); + + }); + }else{ + + //下載圖片_非同步 + dispatch_async(dispatch_get_global_queue(0,0), ^{ + NSData * data = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:ICM.image_url]]; + //NSLog(@"參數查詢:%@", data); + if ( data == nil ) + return; + dispatch_async(dispatch_get_main_queue(), ^{ + // WARNING: is the cell still using the same data by this point?? + self.ImgView.image = [UIImage imageWithData: data]; + }); + + }); + } + + }else { + [self showAlert:@"錯誤" :@"沒有資料,請確認車牌輸入正確或網路連接正常" :nil]; + } + */ +} + +-(void)showAlert:(NSString *)title :(NSString *)text: (NSInteger *)type{ + + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title + message:text + preferredStyle:UIAlertControllerStyleAlert ]; + + UIAlertAction *sinupAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){ + + }]; + [alertController addAction:sinupAction]; + + [self presentViewController:alertController animated:YES completion:nil]; +} + +//截屏响应 +- (void)userDidTakeScreenshot:(NSNotification *)notification +{ + [self showAlert: @"注意" : @"偵測到截圖,請妥善保管截圖,避免重要資訊外流" : 0]; +} + +- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler//通过调用block,来告诉NSURLSession要不要收到这个证书 +{ + // Get remote certificate + SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; + SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0); + SecKeyRef serverPublicKey = SecCertificateCopyPublicKey(certificate); + + + // Set SSL policies for domain name check + NSMutableArray *policies = [NSMutableArray array]; + [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)challenge.protectionSpace.host)]; + SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies); + + // Evaluate server certificate + SecTrustResultType result; + SecTrustEvaluate(serverTrust, &result); + + BOOL certificateIsValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed); + + // Get local and remote cert data + NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate)); + SecCertificateRef cer = SecCertificateCreateWithData ( NULL, (__bridge CFDataRef) remoteCertificateData); + NSLog(@"%@", cer); + + NSString *certPath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"]; + NSData *certData = [NSData dataWithContentsOfFile:certPath]; + SecCertificateRef localCertificate = SecCertificateCreateWithData(nil, (CFDataRef)certData); + NSLog(@"localCertificate: %@", localCertificate); + + NSString *hash = [[self doSha256:remoteCertificateData] base64EncodedStringWithOptions:0]; + + // The pinnning check + if ([hash isEqualToString:@"FHloZIw4i6+30lmxrUujLieHlIDpxHySL1niMxvgmpU="] && certificateIsValid) { + NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; + completionHandler(NSURLSessionAuthChallengeUseCredential, credential); + } else { + completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, NULL); + } +} + +- (NSData *)doSha256:(NSData *)dataIn { + NSMutableData *macOut = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH]; + CC_SHA256(dataIn.bytes, dataIn.length, macOut.mutableBytes); + return macOut; +} + +@end diff --git a/goodpk/ViewController/LockCarViewController.h b/goodpk/ViewController/LockCarViewController.h new file mode 100644 index 0000000..dc552f7 --- /dev/null +++ b/goodpk/ViewController/LockCarViewController.h @@ -0,0 +1,20 @@ +// +// LockCarViewController.h +// goodpk +// +// Created by 歐特儀 on 2020/3/20. +// Copyright © 2020 Altob. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface LockCarViewController : UIViewController +@property(nonatomic,strong)NSString * status; +@property(nonatomic,strong)NSString * acct; +@property(nonatomic,strong)NSString * pwd; +@property(nonatomic,strong)NSString * station; +@end + +NS_ASSUME_NONNULL_END diff --git a/goodpk/ViewController/LockCarViewController.m b/goodpk/ViewController/LockCarViewController.m new file mode 100644 index 0000000..5632976 --- /dev/null +++ b/goodpk/ViewController/LockCarViewController.m @@ -0,0 +1,298 @@ +// +// LockCarViewController.m +// goodpk +// +// Created by 歐特儀 on 2020/3/20. +// Copyright © 2020 Altob. All rights reserved. +// + +#import "LockCarViewController.h" +#import +#import "LockModel.h" +#import "CocoaSecurity.h" +#import "Util.h" +#import + +#define APIURL @"https://cloudservice.altob.com.tw/LockCarSerivce/api/JumpApi" +#define CARSECURITY @"/CARSECURITY?" + +@interface LockCarViewController () +@property (weak, nonatomic) IBOutlet UIImageView *Image; +@property (weak, nonatomic) IBOutlet UIButton *LockBtn; +@property (weak, nonatomic) IBOutlet UIButton *nLockBtn; + +@end + +@implementation LockCarViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + //NSLog(@"傳值:%@", self.status); + //NSLog(@"傳值:%@", self.acct); + //NSLog(@"傳值:%@", self.pwd); + + if([self.status containsString:@"unlocked"]){ + self.nLockBtn.userInteractionEnabled = NO; + self.nLockBtn.alpha = 0.4; + }else{ + self.LockBtn.userInteractionEnabled = NO; + self.LockBtn.alpha = 0.4; + self.Image.image = [UIImage imageNamed:@"Lock_on"]; + } + + [self.LockBtn setTag:0]; + [self.nLockBtn setTag:1]; + + [self.LockBtn addTarget:self + action:@selector(handleButtonClicked:) + forControlEvents:UIControlEventTouchUpInside + ]; + + [self.nLockBtn addTarget:self + action:@selector(handleButtonClicked:) + forControlEvents:UIControlEventTouchUpInside + ]; +} + +- (void) handleButtonClicked:(id)sender { + switch ([sender tag]) { + case 0: + //API 鎖車 + [self Lock_api:self.acct :self.pwd]; + break; + case 1: + //API 解鎖 + [self nLock_api:self.acct :self.pwd]; + break; + } +} + +//鎖車 +-(void) Lock_api:(NSString *)acct :(NSString *)pwd { + + CocoaSecurityResult *Nacct = [CocoaSecurity aesEncrypt:acct key:[Util sha256HashFor:@"Altob"]]; + NSString *status = @"1"; + //NSLog(@"加密字串:%@", [NSString stringWithFormat:@"%@%@%@%@%@", acct, @"i", pwd, @"iii", status]); + NSString *key = [self md5: [NSString stringWithFormat:@"%@%@%@%@%@", acct, @"i", pwd, @"iii", status]]; + NSString *carUrl = [NSString stringWithFormat:@"%@%@acct=%@&pwd=%@&status=%@&key=%@&station=%@", APIURL, CARSECURITY, Nacct.base64, pwd, status, key, self.station]; + + //第一步,创建URL + NSURL *url = [NSURL URLWithString:carUrl]; + //NSDictionary *jsonBodyDict = @{}; + + //NSLog(@"URL: %@", url); + + //第二步,创建请求 + NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10]; + //设置请求方式为POST,默认为GET + [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; + [request setValue:@"Bearer 9a406a82bd551e6ef8e845f42f788af4" forHTTPHeaderField:@"Authorization"]; + [request setHTTPMethod:@"GET"]; + + //设置参数 + //NSData *jsonBodyData = [NSJSONSerialization dataWithJSONObject:jsonBodyDict options:kNilOptions error:nil]; + //[request setHTTPBody:jsonBodyData]; + + //新作法 + NSURLSession *sesson = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil]; + + // 2.创建 NSURLSessionDataTask + NSURLSessionDataTask *dataTask = [sesson dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { + if (error) { + // error + dispatch_async(dispatch_get_main_queue(), ^{ + [self showAlert: @"注意" : @"您所使用的連線加密(SSL)異常,基於安全考量不提供相關功能。請確認您的連線環境及App下載來源安全。" : 0]; + }); + }else { + // 获得数据后,返回到主线程更新 UI + dispatch_async(dispatch_get_main_queue(), ^{ + NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + LockModel *LK= [[LockModel alloc] initWithString:responseString error:nil]; + if([LK.result_code isEqual:@"OK"]){ + + self.LockBtn.userInteractionEnabled = NO; + self.LockBtn.alpha = 0.4; + self.Image.image = [UIImage imageNamed:@"Lock_on"]; + + self.nLockBtn.userInteractionEnabled = YES; + self.nLockBtn.alpha = 1; + + }else{ + [self showAlert:@"錯誤" :@"鎖車失敗,請稍後再試" :nil]; + } + }); + } + }]; + // 3.执行 Task + [dataTask resume]; + + /* + //第三步,连接服务器 + NSData *received = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; + + NSString *jsonString = [[NSString alloc]initWithData:received encoding:NSUTF8StringEncoding]; + //NSLog(@"CAR LOGIN:%@", jsonString); + + LockModel *LK= [[LockModel alloc] initWithString:jsonString error:nil]; + if([LK.result_code isEqual:@"OK"]){ + + self.LockBtn.userInteractionEnabled = NO; + self.LockBtn.alpha = 0.4; + self.Image.image = [UIImage imageNamed:@"Lock_on"]; + + self.nLockBtn.userInteractionEnabled = YES; + self.nLockBtn.alpha = 1; + + }else{ + [self showAlert:@"錯誤" :@"鎖車失敗,請稍後再試" :nil]; + } + */ +} + +//解鎖 +-(void) nLock_api:(NSString *)acct :(NSString *)pwd { + + CocoaSecurityResult *Nacct = [CocoaSecurity aesEncrypt:acct key:[Util sha256HashFor:@"Altob"]]; + NSString *status = @"0"; + //NSLog(@"加密字串:%@", [NSString stringWithFormat:@"%@%@%@%@%@", acct, @"i", pwd, @"iii", status]); + NSString *key = [self md5: [NSString stringWithFormat:@"%@%@%@%@%@", acct, @"i", pwd, @"iii", status]]; + NSString *carUrl = [NSString stringWithFormat:@"%@%@acct=%@&pwd=%@&status=%@&key=%@&station=%@", APIURL, CARSECURITY, Nacct.base64, pwd, status, key, self.station]; + + //第一步,创建URL + NSURL *url = [NSURL URLWithString:carUrl]; + //NSDictionary *jsonBodyDict = @{}; + + //NSLog(@"URL: %@", url); + + //第二步,创建请求 + NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10]; + //设置请求方式为POST,默认为GET + [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; + [request setValue:@"Bearer 9a406a82bd551e6ef8e845f42f788af4" forHTTPHeaderField:@"Authorization"]; + [request setHTTPMethod:@"GET"]; + + //设置参数 + //NSData *jsonBodyData = [NSJSONSerialization dataWithJSONObject:jsonBodyDict options:kNilOptions error:nil]; + //[request setHTTPBody:jsonBodyData]; + + //新作法 + NSURLSession *sesson = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil]; + + // 2.创建 NSURLSessionDataTask + NSURLSessionDataTask *dataTask = [sesson dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { + if (error) { + // error + dispatch_async(dispatch_get_main_queue(), ^{ + [self showAlert: @"注意" : @"您所使用的連線加密(SSL)異常,基於安全考量不提供相關功能。請確認您的連線環境及App下載來源安全。" : 0]; + }); + }else { + // 获得数据后,返回到主线程更新 UI + dispatch_async(dispatch_get_main_queue(), ^{ + NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + LockModel *LK= [[LockModel alloc] initWithString:responseString error:nil]; + if([LK.result_code isEqual:@"OK"]){ + self.nLockBtn.userInteractionEnabled = NO; + self.nLockBtn.alpha = 0.4; + self.Image.image = [UIImage imageNamed:@"Lock_off"]; + + self.LockBtn.userInteractionEnabled = YES; + self.LockBtn.alpha = 1; + }else{ + [self showAlert:@"錯誤" :@"解鎖失敗,請稍後再試" :nil]; + } + }); + } + }]; + // 3.执行 Task + [dataTask resume]; + + /* + //第三步,连接服务器 + NSData *received = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; + + NSString *jsonString = [[NSString alloc]initWithData:received encoding:NSUTF8StringEncoding]; + //NSLog(@"CAR LOGIN:%@", jsonString); + + LockModel *LK= [[LockModel alloc] initWithString:jsonString error:nil]; + if([LK.result_code isEqual:@"OK"]){ + self.nLockBtn.userInteractionEnabled = NO; + self.nLockBtn.alpha = 0.4; + self.Image.image = [UIImage imageNamed:@"Lock_off"]; + + self.LockBtn.userInteractionEnabled = YES; + self.LockBtn.alpha = 1; + }else{ + [self showAlert:@"錯誤" :@"解鎖失敗,請稍後再試" :nil]; + } + */ +} + + +- (NSString *) md5:(NSString *) input +{ + const char *cStr = [input UTF8String]; + unsigned char digest[16]; + CC_MD5( cStr, strlen(cStr), digest ); // This is the md5 call + + NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2]; + + for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) + [output appendFormat:@"%02x", digest[i]]; + + return output; + +} + +-(void)showAlert:(NSString *)title :(NSString *)text: (NSInteger *)type{ + + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title + message:text + preferredStyle:UIAlertControllerStyleAlert ]; + + UIAlertAction *sinupAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){ + + }]; + [alertController addAction:sinupAction]; + + [self presentViewController:alertController animated:YES completion:nil]; +} + +- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler//通过调用block,来告诉NSURLSession要不要收到这个证书 +{ + // Get remote certificate + SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; + SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0); + + // Set SSL policies for domain name check + NSMutableArray *policies = [NSMutableArray array]; + [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)challenge.protectionSpace.host)]; + SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies); + + // Evaluate server certificate + SecTrustResultType result; + SecTrustEvaluate(serverTrust, &result); + + BOOL certificateIsValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed); + + // Get local and remote cert data + NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate)); + + NSString *hash = [[self doSha256:remoteCertificateData] base64EncodedStringWithOptions:0]; + + // The pinnning check + if ([hash isEqualToString:@"FHloZIw4i6+30lmxrUujLieHlIDpxHySL1niMxvgmpU="] && certificateIsValid) { + NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; + completionHandler(NSURLSessionAuthChallengeUseCredential, credential); + } else { + completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, NULL); + } +} + +- (NSData *)doSha256:(NSData *)dataIn { + NSMutableData *macOut = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH]; + CC_SHA256(dataIn.bytes, dataIn.length, macOut.mutableBytes); + return macOut; +} + +@end diff --git a/goodpk/ViewController/PaymentViewController.h b/goodpk/ViewController/PaymentViewController.h new file mode 100644 index 0000000..eb9caf2 --- /dev/null +++ b/goodpk/ViewController/PaymentViewController.h @@ -0,0 +1,17 @@ +// +// PaymentViewController.h +// goodpk +// +// Created by 歐特儀 on 2020/2/11. +// Copyright © 2020 Altob. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface PaymentViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/goodpk/ViewController/PaymentViewController.m b/goodpk/ViewController/PaymentViewController.m new file mode 100644 index 0000000..666b705 --- /dev/null +++ b/goodpk/ViewController/PaymentViewController.m @@ -0,0 +1,34 @@ +// +// PaymentViewController.m +// goodpk +// +// Created by 歐特儀 on 2020/2/11. +// Copyright © 2020 Altob. All rights reserved. +// + +#import "PaymentViewController.h" + +@interface PaymentViewController () + +@end + +@implementation PaymentViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + self.title = @"付款"; + +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/goodpk/ViewController/ViewController.h b/goodpk/ViewController/ViewController.h new file mode 100644 index 0000000..10c28ee --- /dev/null +++ b/goodpk/ViewController/ViewController.h @@ -0,0 +1,15 @@ +// +// ViewController.h +// goodpk +// +// Created by 歐特儀 on 2020/2/11. +// Copyright © 2020 Altob. All rights reserved. +// + +#import + +@interface ViewController : UIViewController +@property (strong, nonatomic) UIWindow * window; + +@end + diff --git a/goodpk/ViewController/ViewController.m b/goodpk/ViewController/ViewController.m new file mode 100644 index 0000000..fd71e00 --- /dev/null +++ b/goodpk/ViewController/ViewController.m @@ -0,0 +1,227 @@ +// +// ViewController.m +// goodpk +// +// Created by 歐特儀 on 2020/2/11. +// Copyright © 2020 Altob. All rights reserved. +// + +#import "ViewController.h" +#import "HelpInfoViewController.h" +#import "InquireCarViewController.h" +#import "CarSecurityViewController.h" +#import "PaymentViewController.h" + +@interface ViewController () +@property (weak, nonatomic) IBOutlet UIButton *b1; +@property (weak, nonatomic) IBOutlet UIButton *b2; +@property (weak, nonatomic) IBOutlet UIButton *b3; +@property (weak, nonatomic) IBOutlet UIButton *b4; +@property (weak, nonatomic) IBOutlet UIButton *stationBtn; +@property (weak, nonatomic) IBOutlet UILabel *stationName; +@property (weak, nonatomic) IBOutlet UIImageView *EndBg; +@property NSUserDefaults* defaults; +@property NSMutableArray *StationData; +@property NSString* station; + +@end + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + [self setTitle:@"CAR IN! 智慧停車"]; + + //注册截圖通知 + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(userDidTakeScreenshot:) + name:UIApplicationUserDidTakeScreenshotNotification object:nil]; + + self.StationData = @[ + @{@"name":@"市民廣場", @"code":@"40808"}, + @{@"name":@"新體", @"code":@"12143"}, + @{@"name":@"二重公園", @"code":@"40806"}, + @{@"name":@"金城", @"code":@"12117"}, + @{@"name":@"澳底", @"code":@"12145"} + ]; + + [self setBtnListener]; +} + +- (void)viewDidAppear:(BOOL)animated{ + [super viewDidAppear:animated]; + + self.defaults = [NSUserDefaults standardUserDefaults]; + + if (! [self.defaults boolForKey:@"notFirstRun"]) { + //App初次啟動 + [self showAlert]; + } +} + +-(void) setBtnListener{ + + [self.b1 setTag:0]; + [self.b2 setTag:1]; + [self.b3 setTag:2]; + [self.b4 setTag:3]; + + [self.b1 addTarget:self + action:@selector(handleButtonClicked:) + forControlEvents:UIControlEventTouchUpInside + ]; + + [self.b2 addTarget:self + action:@selector(handleButtonClicked:) + forControlEvents:UIControlEventTouchUpInside + ]; + + [self.b3 addTarget:self + action:@selector(handleButtonClicked:) + forControlEvents:UIControlEventTouchUpInside + ]; + + [self.b4 addTarget:self + action:@selector(handleButtonClicked:) + forControlEvents:UIControlEventTouchUpInside + ]; + + [self.stationBtn addTarget:self + action:@selector(stationButtonClicked:) + forControlEvents:UIControlEventTouchUpInside + ]; +} + +- (void) stationButtonClicked:(id)sender { + [self showStationSheetAlert]; +} + +- (void) handleButtonClicked:(id)sender { + + if(self.station != nil && self.station.length > 0){ + //NSLog(@"test: %@", self.station); + switch ([sender tag]) { + case 0: + //NSLog(@"button1 have been clicked."); + { + //查車 + UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"InquireCar" bundle:[NSBundle mainBundle]]; + InquireCarViewController *InquireCarController = [storyboard instantiateViewControllerWithIdentifier:@"InquireCar"]; + [self.navigationController popViewControllerAnimated: YES]; + [self.navigationController pushViewController:InquireCarController animated:YES]; + } + break; + + case 1: + //NSLog(@"button2 have been clicked."); + { + //鎖車 + UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"CarSecurity" bundle:[NSBundle mainBundle]]; + CarSecurityViewController *CarSecurityController = [storyboard instantiateViewControllerWithIdentifier:@"CarSecurity"]; + [self.navigationController popViewControllerAnimated: YES]; + CarSecurityController.station = self.station; + [self.navigationController pushViewController:CarSecurityController animated:YES]; + } + break; + + case 2: + //NSLog(@"button3 have been clicked."); + { + //求助 + UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Help" bundle:[NSBundle mainBundle]]; + HelpInfoViewController *HelpController = [storyboard instantiateViewControllerWithIdentifier:@"Help"]; + [self.navigationController popViewControllerAnimated: YES]; + [self.navigationController pushViewController:HelpController animated:YES]; + } + break; + + case 3: + //NSLog(@"button4 have been clicked."); + { + /* + UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Payment" bundle:[NSBundle mainBundle]]; + PaymentViewController *PaymentController = [storyboard instantiateViewControllerWithIdentifier:@"Payment"]; + [self.navigationController popViewControllerAnimated: YES]; + [self.navigationController pushViewController:PaymentController animated:YES]; + */ + [[UIApplication sharedApplication] openURL: [NSURL URLWithString:@"https://parks.altob.com.tw/opay.html"] options:nil completionHandler:nil]; + } + break; + default: + break; + } + }else{ + [self showAlert2: @"注意" : @"請先選擇場站" : 0]; + } +} + +-(void)showAlert{ + + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"重要" + message:@"本APP將會使用您的網路連線功能和電話權限於緊急協助中撥打電話給場站。在任何傳輸的過程中也會對您的資料進行加密。如不同意的話則無法使用完整的App功能" + preferredStyle:UIAlertControllerStyleAlert ]; + + //添加确定到UIAlertController中 + UIAlertAction *sinupAction = [UIAlertAction actionWithTitle:@"同意" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){ + [self.defaults setBool:YES forKey:@"notFirstRun"]; + }]; + + [alertController addAction:sinupAction]; + + UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"不同意" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){ + [self.defaults setBool:NO forKey:@"notFirstRun"]; + exit(0); + }]; + + [alertController addAction:cancelAction]; + + [self presentViewController:alertController animated:YES completion:nil]; +} + +-(void)showAlert2:(NSString *)title :(NSString *)text: (NSInteger *)type{ + + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title + message:text + preferredStyle:UIAlertControllerStyleAlert ]; + + UIAlertAction *sinupAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){ + + }]; + [alertController addAction:sinupAction]; + + [self presentViewController:alertController animated:YES completion:nil]; +} + +-(void) showStationSheetAlert{ + // 創建一個UIAlertController, 命名為alertThree, preferredStyle 設置為 UIAlertControllerStyleActionSheet + UIAlertController *alertThree = [UIAlertController alertControllerWithTitle:@"場站" message:@"請選擇所在場站:" preferredStyle:UIAlertControllerStyleActionSheet]; + // 創建一個“取消”按鈕 + UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]; + // 將按鈕添加到alertThree上 + [alertThree addAction:cancelAction]; + + // 根據陣列資料創建選項按鈕 + for(int i = 0 ; i < self.StationData.count; i++){ + UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:[[self.StationData objectAtIndex:i] valueForKey:@"name"] style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action){ + [self.stationName setText:[[self.StationData objectAtIndex:i] valueForKey:@"name"]]; + self.station = [[self.StationData objectAtIndex:i] valueForKey:@"code"]; + }]; + // 將按鈕添加到alertThree上 + [alertThree addAction:confirmAction]; + } + + alertThree.popoverPresentationController.sourceView = self.view; + alertThree.popoverPresentationController.sourceRect = CGRectMake(self.view.frame.size.width/2, self.view.frame.size.height/2, 1.0, 1.0); + + // 彈出alertThree + [self presentViewController:alertThree animated:YES completion:nil]; +} + +//截屏响应 +- (void)userDidTakeScreenshot:(NSNotification *)notification +{ + [self showAlert2: @"注意" : @"偵測到截圖,請妥善保管截圖,避免重要資訊外流" : 0]; +} + +@end diff --git a/goodpk/main.m b/goodpk/main.m new file mode 100644 index 0000000..2735f0c --- /dev/null +++ b/goodpk/main.m @@ -0,0 +1,19 @@ +// +// main.m +// goodpk +// +// Created by 歐特儀 on 2020/2/11. +// Copyright © 2020 Altob. All rights reserved. +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + NSString * appDelegateClassName; + @autoreleasepool { + // Setup code that might create autoreleased objects goes here. + appDelegateClassName = NSStringFromClass([AppDelegate class]); + } + return UIApplicationMain(argc, argv, nil, appDelegateClassName); +} diff --git a/goodpk/server.cer b/goodpk/server.cer new file mode 100644 index 0000000..409e8ac --- /dev/null +++ b/goodpk/server.cer @@ -0,0 +1,40 @@ +-----BEGIN CERTIFICATE----- +MIIHEDCCBfigAwIBAgIQR+QAAAACEEEpAqPIUUztyTANBgkqhkiG9w0BAQsFADBv +MQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRowGAYDVQQLExFTZWN1 +cmUgU1NMIFN1Yi1DQTEwMC4GA1UEAxMnVFdDQSBTZWN1cmUgU1NMIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MB4XDTIwMDQyODAzNTIxMloXDTIyMDQyODE1NTk1OVow +eTELMAkGA1UEBhMCVFcxDzANBgNVBAgTBlRBSVdBTjEPMA0GA1UEBxMGVEFJUEVJ +MRMwEQYDVQQKEwpBTFRPQiBJTkMuMQ8wDQYDVQQLEwZTWVNURU0xIjAgBgNVBAMT +GWNsb3Vkc2VydmljZS5hbHRvYi5jb20udHcwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQCmcD/M9BM7WHBL7R0WXoyr8LfMwwzSNE9UdMM5+3+TVlcez+Oj +AVPKb2+dWxu/vO1ogSY4dQvDkN0kVVtWwuaC/XdulF/B3Bb3o6LAxYj/FDNyLEUh +eKJb9msvcxtNT42J/ydWuQ5uBlAYa2ooqBlh4ExyJbmKKI22OmzGp4sNlZneOAeP +lWhqSbUkeHK3+ZxrTSph9kuRJTZVlYYxHJSfbO7FN6/E44gkTlbm7riuJ+KPViXn +sQ6Ifwm4DDQxQDiVoMzf4rLBDVBuz3RbNSg6CIFN9b/yn65R5aPA2dri9c1vzLLw +xQLbsdpulhcWUHTDgoG6EYfeqcY41EWqlCw1AgMBAAGjggOcMIIDmDAfBgNVHSME +GDAWgBT4B8JoJP+FlcvbHuMznCpPlyBWezApBgNVHQ4EIgQg0RgivMDsQPLkrS+A +a5W1A8Qh45mLi32hqkhMWfuU4hEwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL3Nz +bHNlcnZlci50d2NhLmNvbS50dy9zc2xzZXJ2ZXIvU2VjdXJlc3NsX3Jldm9rZV9z +aGEyXzIwMTQuY3JsMHgGA1UdEQRxMG+CGWNsb3Vkc2VydmljZS5hbHRvYi5jb20u +dHeCFHJzc21hcnQuYWx0b2IuY29tLnR3ghtwYXJraW5nc2VydmljZS5hbHRvYi5j +b20udHeCH3RyYW5zYWN0aW9uc2VydmljZS5hbHRvYi5jb20udHcwgYEGCCsGAQUF +BwEBBHUwczBEBggrBgEFBQcwAoY4aHR0cDovL3NzbHNlcnZlci50d2NhLmNvbS50 +dy9jYWNlcnQvc2VjdXJlX3NoYTJfMjAxNC5jcnQwKwYIKwYBBQUHMAGGH2h0dHA6 +Ly90d2Nhc3Nsb2NzcC50d2NhLmNvbS50dy8wNwYDVR0gBDAwLjAsBgsrBgEEAYK/ +JQEBGTAdMBsGCCsGAQUFBwIBFg93d3cudHdjYS5jb20udHcwCQYDVR0TBAIwADAO +BgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMIIB +fwYKKwYBBAHWeQIEAgSCAW8EggFrAWkAdwBVgdTCFpA2AUrqC5tXPFPwwOQ4eHAl +CBcvo6odBxPTDAAAAXG+6eyBAAAEAwBIMEYCIQDDIbAIImfRI0mKrpvDTq4B+MJV +7Gh+6DnecKQEFRmkDgIhAOVVrlXq1koOuKAFIQW6Sc6xqy+rGmNpVFjiCrOnPjqu +AHYAKXm+8J45OSHwVnOfY6V35b5XfZxgCvj5TV0mXCVdx4QAAAFxvunsSAAABAMA +RzBFAiEAoBj0fOXj/0Fkim//kOIcOMGZ2BeIACVs67MYF6K0T0MCIBPA4ejfVwe6 +QiXD+eawb0T0xfK7nGgpwTJsA0EGJqGvAHYAb1N2rDHwMRnYmQCkURX/dxUcEdkC +wQApBo2yCJo32RMAAAFxvunttwAABAMARzBFAiAoeKIklR6aef0Fx6jnkvbTyOvV +X4QqlaW3TPqypJq5FAIhAKb8L46SmflpIUm/3TFk3nWxNPCAUzGHWBKsVOQ8qGBt +MA0GCSqGSIb3DQEBCwUAA4IBAQDCjMp4zvIhnI7cRBrpQops1l7RxZhSFYCv9dT6 +9y8oEMR3NUTbelhQMJqyYiuAsaFRhcfJ7B5557nO68xEf4xQT3tlf5gPndtgDgi9 +TZGWKo/X3i7bTY3oHc3HE0xD87WbdOLrAgnejTfW5S4Pfh9P/qFrzNJ9YwKxk2rV +2mL+RSTxa8Vifjjwtt6P4mp018h3w1RHo8b7GiPH92ik1MY6YpGUfWmXUImp+hum +BWxD4W3h5Zt9Vt9geoOAvJEDUOrbKuT6FznLMq6VjKe2AUohCE/R8opqSU36jHzD +AnVGvqxeNdy5HwUhKaS58xVjlrJWhzQZMwIhQT4tlGyuKSuT +-----END CERTIFICATE-----