As of iOS 13.3.1, apps installed with free developer accounts that contain embedded frameworks fail to launch. To work around this, we now link all dependencies via Cocoapods as static libraries.
314 lines
10 KiB
Objective-C
314 lines
10 KiB
Objective-C
/* Copyright (c) 2011 Google Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#if !__has_feature(objc_arc)
|
|
#error "This file needs to be compiled with ARC enabled."
|
|
#endif
|
|
|
|
#include <objc/runtime.h>
|
|
|
|
#import "GTLRQuery.h"
|
|
#import "GTLRRuntimeCommon.h"
|
|
#import "GTLRService.h"
|
|
#import "GTLRUtilities.h"
|
|
|
|
@interface GTLRQuery () <GTLRRuntimeCommon>
|
|
@end
|
|
|
|
@implementation GTLRQuery {
|
|
NSMutableDictionary *_childCache;
|
|
GTLRServiceExecutionParameters *_executionParameters;
|
|
}
|
|
|
|
@synthesize additionalURLQueryParameters = _additionalURLQueryParameters,
|
|
additionalHTTPHeaders = _additionalHTTPHeaders,
|
|
bodyObject = _bodyObject,
|
|
completionBlock = _completionBlock,
|
|
downloadAsDataObjectType = _downloadAsDataObjectType,
|
|
expectedObjectClass = _expectedObjectClass,
|
|
httpMethod = _httpMethod,
|
|
JSON = _json,
|
|
loggingName = _loggingName,
|
|
pathParameterNames = _pathParameterNames,
|
|
pathURITemplate = _pathURITemplate,
|
|
queryInvalid = _queryInvalid,
|
|
requestID = _requestID,
|
|
resumableUploadPathURITemplateOverride = _resumableUploadPathURITemplateOverride,
|
|
shouldSkipAuthorization = _shouldSkipAuthorization,
|
|
simpleUploadPathURITemplateOverride = _simpleUploadPathURITemplateOverride,
|
|
uploadParameters = _uploadParameters,
|
|
useMediaDownloadService = _useMediaDownloadService;
|
|
|
|
#if DEBUG
|
|
- (instancetype)init {
|
|
[self doesNotRecognizeSelector:_cmd];
|
|
self = nil;
|
|
return self;
|
|
}
|
|
#endif
|
|
|
|
- (instancetype)initWithPathURITemplate:(NSString *)pathURITemplate
|
|
HTTPMethod:(nullable NSString *)httpMethod
|
|
pathParameterNames:(nullable NSArray<NSString *> *)pathParameterNames {
|
|
self = [super init];
|
|
if (self) {
|
|
_requestID = [[self class] nextRequestID];
|
|
|
|
_pathURITemplate = [pathURITemplate copy];
|
|
_httpMethod = [httpMethod copy];
|
|
_pathParameterNames = [pathParameterNames copy];
|
|
|
|
if (_pathURITemplate.length == 0) {
|
|
self = nil;
|
|
}
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (id)copyWithZone:(NSZone *)zone {
|
|
GTLR_DEBUG_ASSERT(!self.queryInvalid, @"Cannot copy an executed query: %@", self);
|
|
|
|
GTLRQuery *query =
|
|
[[[self class] allocWithZone:zone] initWithPathURITemplate:self.pathURITemplate
|
|
HTTPMethod:self.httpMethod
|
|
pathParameterNames:self.pathParameterNames];
|
|
|
|
if (_json.count > 0) {
|
|
// Deep copy the parameters
|
|
CFPropertyListRef ref = CFPropertyListCreateDeepCopy(kCFAllocatorDefault,
|
|
(__bridge CFPropertyListRef)(_json),
|
|
kCFPropertyListMutableContainers);
|
|
query.JSON = CFBridgingRelease(ref);
|
|
}
|
|
|
|
// Using the executionParameters ivar avoids creating the object.
|
|
query.executionParameters = self.executionParameters;
|
|
|
|
// Copied in the same order as synthesized above.
|
|
query.additionalHTTPHeaders = self.additionalHTTPHeaders;
|
|
query.additionalURLQueryParameters = self.additionalURLQueryParameters;
|
|
query.bodyObject = self.bodyObject;
|
|
query.completionBlock = self.completionBlock;
|
|
query.downloadAsDataObjectType = self.downloadAsDataObjectType;
|
|
query.expectedObjectClass = self.expectedObjectClass;
|
|
// http method passed to init above.
|
|
// JSON copied above.
|
|
query.loggingName = self.loggingName;
|
|
// pathParameterNames passed to init above.
|
|
// pathURITemplate passed to init above.
|
|
query.queryInvalid = self.queryInvalid;
|
|
query.requestID = self.requestID;
|
|
query.resumableUploadPathURITemplateOverride = self.resumableUploadPathURITemplateOverride;
|
|
query.shouldSkipAuthorization = self.shouldSkipAuthorization;
|
|
query.simpleUploadPathURITemplateOverride = self.simpleUploadPathURITemplateOverride;
|
|
query.uploadParameters = self.uploadParameters;
|
|
query.useMediaDownloadService = self.useMediaDownloadService;
|
|
|
|
return query;
|
|
}
|
|
|
|
#if DEBUG
|
|
- (NSString *)description {
|
|
NSArray *keys = self.JSON.allKeys;
|
|
NSArray *params = [keys sortedArrayUsingSelector:@selector(compare:)];
|
|
NSString *paramsSummary = @"";
|
|
if (params.count > 0) {
|
|
paramsSummary = [NSString stringWithFormat:@" params:(%@)",
|
|
[params componentsJoinedByString:@","]];
|
|
}
|
|
|
|
NSString *invalidStr = @"";
|
|
if (self.queryInvalid) {
|
|
invalidStr = @" [callbacks released]";
|
|
}
|
|
|
|
keys = self.additionalURLQueryParameters.allKeys;
|
|
NSArray *urlQParams = [keys sortedArrayUsingSelector:@selector(compare:)];
|
|
NSString *urlQParamsSummary = @"";
|
|
if (urlQParams.count > 0) {
|
|
urlQParamsSummary = [NSString stringWithFormat:@" urlQParams:(%@)",
|
|
[urlQParams componentsJoinedByString:@","]];
|
|
}
|
|
|
|
GTLRObject *bodyObj = self.bodyObject;
|
|
NSString *bodyObjSummary = @"";
|
|
if (bodyObj != nil) {
|
|
bodyObjSummary = [NSString stringWithFormat:@" bodyObject:%@", [bodyObj class]];
|
|
}
|
|
|
|
NSString *uploadStr = @"";
|
|
GTLRUploadParameters *uploadParams = self.uploadParameters;
|
|
if (uploadParams) {
|
|
uploadStr = [NSString stringWithFormat:@" %@", uploadParams];
|
|
}
|
|
|
|
NSString *httpMethod = self.httpMethod;
|
|
if (httpMethod == nil) {
|
|
httpMethod = @"GET";
|
|
}
|
|
|
|
NSString *dataObjectType = self.downloadAsDataObjectType;
|
|
NSString *downloadStr = @"";
|
|
if (dataObjectType.length > 0) {
|
|
downloadStr =
|
|
[NSString stringWithFormat:@" downloadDataAs:%@", dataObjectType];
|
|
}
|
|
|
|
return [NSString stringWithFormat:@"%@ %p:%@%@ {%@ pathTemplate:%@%@%@%@%@}",
|
|
[self class], self, invalidStr, downloadStr,
|
|
httpMethod, self.pathURITemplate,
|
|
paramsSummary, urlQParamsSummary, bodyObjSummary, uploadStr];
|
|
}
|
|
#endif // DEBUG
|
|
|
|
- (BOOL)isBatchQuery {
|
|
return NO;
|
|
}
|
|
|
|
- (void)invalidateQuery {
|
|
self.queryInvalid = YES;
|
|
self.completionBlock = nil;
|
|
self.executionParameters = nil;
|
|
}
|
|
|
|
- (GTLRServiceExecutionParameters *)executionParameters {
|
|
@synchronized(self) {
|
|
if (!_executionParameters) {
|
|
_executionParameters = [[GTLRServiceExecutionParameters alloc] init];
|
|
}
|
|
return _executionParameters;
|
|
}
|
|
}
|
|
|
|
- (void)setExecutionParameters:(nullable GTLRServiceExecutionParameters *)executionParameters {
|
|
@synchronized(self) {
|
|
_executionParameters = executionParameters;
|
|
}
|
|
}
|
|
|
|
- (BOOL)hasExecutionParameters {
|
|
return self.executionParameters.hasParameters;
|
|
}
|
|
|
|
+ (NSString *)nextRequestID {
|
|
static NSUInteger lastRequestID = 0;
|
|
NSString *result;
|
|
|
|
@synchronized([GTLRQuery class]) {
|
|
++lastRequestID;
|
|
result = [NSString stringWithFormat:@"gtlr_%lu", (unsigned long)lastRequestID];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
#pragma mark GTLRRuntimeCommon Support
|
|
|
|
- (void)setJSONValue:(id)obj forKey:(NSString *)key {
|
|
NSMutableDictionary *dict = self.JSON;
|
|
if (dict == nil && obj != nil) {
|
|
dict = [NSMutableDictionary dictionaryWithCapacity:1];
|
|
self.JSON = dict;
|
|
}
|
|
[dict setValue:obj forKey:key];
|
|
}
|
|
|
|
- (id)JSONValueForKey:(NSString *)key {
|
|
id obj = [self.JSON objectForKey:key];
|
|
return obj;
|
|
}
|
|
|
|
// There is no property for _childCache as there shouldn't be KVC/KVO
|
|
// support for it, since it's an implementation detail.
|
|
|
|
- (void)setCacheChild:(id)obj forKey:(NSString *)key {
|
|
if (_childCache == nil && obj != nil) {
|
|
_childCache = [[NSMutableDictionary alloc] initWithObjectsAndKeys:obj, key, nil];
|
|
} else {
|
|
[_childCache setValue:obj forKey:key];
|
|
}
|
|
}
|
|
|
|
- (id)cacheChildForKey:(NSString *)key {
|
|
id obj = [_childCache objectForKey:key];
|
|
return obj;
|
|
}
|
|
|
|
#pragma mark Methods for Subclasses to Override
|
|
|
|
+ (NSDictionary<NSString *, NSString *> *)parameterNameMap {
|
|
return nil;
|
|
}
|
|
|
|
+ (NSDictionary<NSString *, Class> *)arrayPropertyToClassMap {
|
|
return nil;
|
|
}
|
|
|
|
#pragma mark Runtime Utilities
|
|
|
|
static NSMutableDictionary *gQueryParameterNameMapCache = nil;
|
|
static NSMutableDictionary *gQueryArrayPropertyToClassMapCache = nil;
|
|
|
|
+ (void)initialize {
|
|
// Note that +initialize is guaranteed by the runtime to be called in a thread-safe manner.
|
|
if (gQueryParameterNameMapCache == nil) {
|
|
gQueryParameterNameMapCache = [[NSMutableDictionary alloc] init];
|
|
}
|
|
if (gQueryArrayPropertyToClassMapCache == nil) {
|
|
gQueryArrayPropertyToClassMapCache = [[NSMutableDictionary alloc] init];
|
|
}
|
|
}
|
|
|
|
+ (NSDictionary *)propertyToJSONKeyMapForClass:(Class<GTLRRuntimeCommon>)aClass {
|
|
NSDictionary *resultMap =
|
|
[GTLRRuntimeCommon mergedClassDictionaryForSelector:@selector(parameterNameMap)
|
|
startClass:aClass
|
|
ancestorClass:[GTLRQuery class]
|
|
cache:gQueryParameterNameMapCache];
|
|
return resultMap;
|
|
}
|
|
|
|
+ (NSDictionary *)arrayPropertyToClassMapForClass:(Class<GTLRRuntimeCommon>)aClass {
|
|
NSDictionary *resultMap =
|
|
[GTLRRuntimeCommon mergedClassDictionaryForSelector:@selector(arrayPropertyToClassMap)
|
|
startClass:aClass
|
|
ancestorClass:[GTLRQuery class]
|
|
cache:gQueryArrayPropertyToClassMapCache];
|
|
return resultMap;
|
|
}
|
|
|
|
#pragma mark Runtime Support
|
|
|
|
- (id<GTLRObjectClassResolver>)objectClassResolver {
|
|
// Stub method just needed for RuntimeCommon.
|
|
return nil;
|
|
}
|
|
|
|
+ (Class<GTLRRuntimeCommon>)ancestorClass {
|
|
return [GTLRQuery class];
|
|
}
|
|
|
|
+ (BOOL)resolveInstanceMethod:(SEL)sel {
|
|
BOOL resolved = [GTLRRuntimeCommon resolveInstanceMethod:sel onClass:self];
|
|
if (resolved) return YES;
|
|
|
|
return [super resolveInstanceMethod:sel];
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation GTLRQueryCollectionImpl
|
|
@dynamic pageToken;
|
|
@end
|