├── .DS_Store ├── .gitignore ├── LICENSE ├── README.md ├── confuse.png ├── resCustom.txt ├── reskeys.txt ├── shakefun ├── .DS_Store ├── LICENSE ├── README.md ├── shakefun.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── shakefun │ ├── AFNetworking │ │ ├── AFHTTPRequestOperation.h │ │ ├── AFHTTPRequestOperation.m │ │ ├── AFHTTPRequestOperationManager.h │ │ ├── AFHTTPRequestOperationManager.m │ │ ├── AFHTTPSessionManager.h │ │ ├── AFHTTPSessionManager.m │ │ ├── AFNetworkReachabilityManager.h │ │ ├── AFNetworkReachabilityManager.m │ │ ├── AFNetworking.h │ │ ├── AFSecurityPolicy.h │ │ ├── AFSecurityPolicy.m │ │ ├── AFURLConnectionOperation.h │ │ ├── AFURLConnectionOperation.m │ │ ├── AFURLRequestSerialization.h │ │ ├── AFURLRequestSerialization.m │ │ ├── AFURLResponseSerialization.h │ │ ├── AFURLResponseSerialization.m │ │ ├── AFURLSessionManager.h │ │ └── AFURLSessionManager.m │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── CollectViewController.h │ ├── CollectViewController.m │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Info.plist │ ├── MagicalRecord │ │ ├── Categories │ │ │ ├── DataImport │ │ │ │ ├── MagicalImportFunctions.h │ │ │ │ ├── MagicalImportFunctions.m │ │ │ │ ├── NSAttributeDescription+MagicalDataImport.h │ │ │ │ ├── NSAttributeDescription+MagicalDataImport.m │ │ │ │ ├── NSEntityDescription+MagicalDataImport.h │ │ │ │ ├── NSEntityDescription+MagicalDataImport.m │ │ │ │ ├── NSNumber+MagicalDataImport.h │ │ │ │ ├── NSNumber+MagicalDataImport.m │ │ │ │ ├── NSObject+MagicalDataImport.h │ │ │ │ ├── NSObject+MagicalDataImport.m │ │ │ │ ├── NSRelationshipDescription+MagicalDataImport.h │ │ │ │ ├── NSRelationshipDescription+MagicalDataImport.m │ │ │ │ ├── NSString+MagicalDataImport.h │ │ │ │ └── NSString+MagicalDataImport.m │ │ │ ├── NSManagedObject │ │ │ │ ├── NSManagedObject+MagicalAggregation.h │ │ │ │ ├── NSManagedObject+MagicalAggregation.m │ │ │ │ ├── NSManagedObject+MagicalDataImport.h │ │ │ │ ├── NSManagedObject+MagicalDataImport.m │ │ │ │ ├── NSManagedObject+MagicalFinders.h │ │ │ │ ├── NSManagedObject+MagicalFinders.m │ │ │ │ ├── NSManagedObject+MagicalRecord.h │ │ │ │ ├── NSManagedObject+MagicalRecord.m │ │ │ │ ├── NSManagedObject+MagicalRequests.h │ │ │ │ └── NSManagedObject+MagicalRequests.m │ │ │ ├── NSManagedObjectContext │ │ │ │ ├── NSManagedObjectContext+MagicalObserving.h │ │ │ │ ├── NSManagedObjectContext+MagicalObserving.m │ │ │ │ ├── NSManagedObjectContext+MagicalRecord.h │ │ │ │ ├── NSManagedObjectContext+MagicalRecord.m │ │ │ │ ├── NSManagedObjectContext+MagicalSaves.h │ │ │ │ ├── NSManagedObjectContext+MagicalSaves.m │ │ │ │ ├── NSManagedObjectContext+MagicalThreading.h │ │ │ │ └── NSManagedObjectContext+MagicalThreading.m │ │ │ ├── NSManagedObjectModel+MagicalRecord.h │ │ │ ├── NSManagedObjectModel+MagicalRecord.m │ │ │ ├── NSPersistentStore+MagicalRecord.h │ │ │ ├── NSPersistentStore+MagicalRecord.m │ │ │ ├── NSPersistentStoreCoordinator+MagicalRecord.h │ │ │ └── NSPersistentStoreCoordinator+MagicalRecord.m │ │ ├── Core │ │ │ ├── MagicalRecord+Actions.h │ │ │ ├── MagicalRecord+Actions.m │ │ │ ├── MagicalRecord+ErrorHandling.h │ │ │ ├── MagicalRecord+ErrorHandling.m │ │ │ ├── MagicalRecord+Options.h │ │ │ ├── MagicalRecord+Options.m │ │ │ ├── MagicalRecord+Setup.h │ │ │ ├── MagicalRecord+Setup.m │ │ │ ├── MagicalRecord+ShorthandSupport.h │ │ │ ├── MagicalRecord+ShorthandSupport.m │ │ │ ├── MagicalRecord+iCloud.h │ │ │ ├── MagicalRecord+iCloud.m │ │ │ ├── MagicalRecord.h │ │ │ ├── MagicalRecord.m │ │ │ └── MagicalRecordShorthand.h │ │ └── CoreData+MagicalRecord.h │ ├── PrefixHeader.pch │ ├── SVProgressHUD │ │ ├── .DS_Store │ │ ├── SVProgressHUD.bundle │ │ │ ├── error.png │ │ │ ├── error@2x.png │ │ │ ├── success.png │ │ │ └── success@2x.png │ │ ├── SVProgressHUD.h │ │ └── SVProgressHUD.m │ ├── URLEntity.h │ ├── URLEntity.m │ ├── ViewController.h │ ├── ViewController.m │ ├── main.m │ └── shakefun.xcdatamodeld │ │ ├── .xccurrentversion │ │ └── shakefun.xcdatamodel │ │ └── contents └── shakefunTests │ ├── Info.plist │ └── shakefunTests.m ├── zmconfuse.sh ├── zmreplacewords.run └── zmreplacewords ├── .DS_Store ├── zmreplacewords.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata └── zmreplacewords └── main.c /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongcup/ZMConfuse/5409be7b310a301aa726a1ee0e3e98c9241090e4/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | #Pods/ 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 kongcup 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ZMConfuse 2 | ZMConfuse 是一个命令行脚本。用于对使用Objective-C为开发语言的应用进行代码混淆。混淆的内容包括文件名、类名、协议名、函数名。 3 | 混淆实际是对上述内容的关键字提取之后进行md5加密,使得工程的可读性降低,已达到增加应用安全性的目的。 4 | 5 | 欢迎联系交流 6 | Email:zm53373581@163.com 7 | QQGroup:175070221 8 | 9 | 混淆效果图: 10 | ![image](https://github.com/kongcup/ZMConfuse/raw/master/confuse.png) 11 | -------------------------------------------------------------------------------- /confuse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongcup/ZMConfuse/5409be7b310a301aa726a1ee0e3e98c9241090e4/confuse.png -------------------------------------------------------------------------------- /resCustom.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongcup/ZMConfuse/5409be7b310a301aa726a1ee0e3e98c9241090e4/resCustom.txt -------------------------------------------------------------------------------- /shakefun/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongcup/ZMConfuse/5409be7b310a301aa726a1ee0e3e98c9241090e4/shakefun/.DS_Store -------------------------------------------------------------------------------- /shakefun/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 kongcup 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /shakefun/README.md: -------------------------------------------------------------------------------- 1 | # shakefun 2 | 在ios设备中,采集hao123上的搞笑图片或gif,然后通过摇动设备来更换显示的内容。又好玩,又锻炼身体!呵呵 3 | 4 | 本工程主要使用AFNetworking来访问网络,下载资源;使用SVProgressHUD来显示进度和用户提示。 5 | 6 | 本工程主要目的在于学习~ -------------------------------------------------------------------------------- /shakefun/shakefun.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /shakefun/shakefun/AFNetworking/AFHTTPRequestOperation.h: -------------------------------------------------------------------------------- 1 | // AFHTTPRequestOperation.h 2 | // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | #import "AFURLConnectionOperation.h" 24 | 25 | NS_ASSUME_NONNULL_BEGIN 26 | 27 | /** 28 | `AFHTTPRequestOperation` is a subclass of `AFURLConnectionOperation` for requests using the HTTP or HTTPS protocols. It encapsulates the concept of acceptable status codes and content types, which determine the success or failure of a request. 29 | */ 30 | @interface AFHTTPRequestOperation : AFURLConnectionOperation 31 | 32 | ///------------------------------------------------ 33 | /// @name Getting HTTP URL Connection Information 34 | ///------------------------------------------------ 35 | 36 | /** 37 | The last HTTP response received by the operation's connection. 38 | */ 39 | @property (readonly, nonatomic, strong, nullable) NSHTTPURLResponse *response; 40 | 41 | /** 42 | Responses sent from the server in data tasks created with `dataTaskWithRequest:success:failure:` and run using the `GET` / `POST` / et al. convenience methods are automatically validated and serialized by the response serializer. By default, this property is set to an AFHTTPResponse serializer, which uses the raw data as its response object. The serializer validates the status code to be in the `2XX` range, denoting success. If the response serializer generates an error in `-responseObjectForResponse:data:error:`, the `failure` callback of the session task or request operation will be executed; otherwise, the `success` callback will be executed. 43 | 44 | @warning `responseSerializer` must not be `nil`. Setting a response serializer will clear out any cached value 45 | */ 46 | @property (nonatomic, strong) AFHTTPResponseSerializer * responseSerializer; 47 | 48 | /** 49 | An object constructed by the `responseSerializer` from the response and response data. Returns `nil` unless the operation `isFinished`, has a `response`, and has `responseData` with non-zero content length. If an error occurs during serialization, `nil` will be returned, and the `error` property will be populated with the serialization error. 50 | */ 51 | @property (readonly, nonatomic, strong, nullable) id responseObject; 52 | 53 | ///----------------------------------------------------------- 54 | /// @name Setting Completion Block Success / Failure Callbacks 55 | ///----------------------------------------------------------- 56 | 57 | /** 58 | Sets the `completionBlock` property with a block that executes either the specified success or failure block, depending on the state of the request on completion. If `error` returns a value, which can be caused by an unacceptable status code or content type, then `failure` is executed. Otherwise, `success` is executed. 59 | 60 | This method should be overridden in subclasses in order to specify the response object passed into the success block. 61 | 62 | @param success The block to be executed on the completion of a successful request. This block has no return value and takes two arguments: the receiver operation and the object constructed from the response data of the request. 63 | @param failure The block to be executed on the completion of an unsuccessful request. This block has no return value and takes two arguments: the receiver operation and the error that occurred during the request. 64 | */ 65 | - (void)setCompletionBlockWithSuccess:(nullable void (^)(AFHTTPRequestOperation *operation, id responseObject))success 66 | failure:(nullable void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; 67 | 68 | @end 69 | 70 | NS_ASSUME_NONNULL_END 71 | -------------------------------------------------------------------------------- /shakefun/shakefun/AFNetworking/AFHTTPRequestOperation.m: -------------------------------------------------------------------------------- 1 | // AFHTTPRequestOperation.m 2 | // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import "AFHTTPRequestOperation.h" 23 | 24 | static dispatch_queue_t http_request_operation_processing_queue() { 25 | static dispatch_queue_t af_http_request_operation_processing_queue; 26 | static dispatch_once_t onceToken; 27 | dispatch_once(&onceToken, ^{ 28 | af_http_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.http-request.processing", DISPATCH_QUEUE_CONCURRENT); 29 | }); 30 | 31 | return af_http_request_operation_processing_queue; 32 | } 33 | 34 | static dispatch_group_t http_request_operation_completion_group() { 35 | static dispatch_group_t af_http_request_operation_completion_group; 36 | static dispatch_once_t onceToken; 37 | dispatch_once(&onceToken, ^{ 38 | af_http_request_operation_completion_group = dispatch_group_create(); 39 | }); 40 | 41 | return af_http_request_operation_completion_group; 42 | } 43 | 44 | #pragma mark - 45 | 46 | @interface AFURLConnectionOperation () 47 | @property (readwrite, nonatomic, strong) NSURLRequest *request; 48 | @property (readwrite, nonatomic, strong) NSURLResponse *response; 49 | @end 50 | 51 | @interface AFHTTPRequestOperation () 52 | @property (readwrite, nonatomic, strong) NSHTTPURLResponse *response; 53 | @property (readwrite, nonatomic, strong) id responseObject; 54 | @property (readwrite, nonatomic, strong) NSError *responseSerializationError; 55 | @property (readwrite, nonatomic, strong) NSRecursiveLock *lock; 56 | @end 57 | 58 | @implementation AFHTTPRequestOperation 59 | @dynamic response; 60 | @dynamic lock; 61 | 62 | - (instancetype)initWithRequest:(NSURLRequest *)urlRequest { 63 | self = [super initWithRequest:urlRequest]; 64 | if (!self) { 65 | return nil; 66 | } 67 | 68 | self.responseSerializer = [AFHTTPResponseSerializer serializer]; 69 | 70 | return self; 71 | } 72 | 73 | - (void)setResponseSerializer:(AFHTTPResponseSerializer *)responseSerializer { 74 | NSParameterAssert(responseSerializer); 75 | 76 | [self.lock lock]; 77 | _responseSerializer = responseSerializer; 78 | self.responseObject = nil; 79 | self.responseSerializationError = nil; 80 | [self.lock unlock]; 81 | } 82 | 83 | - (id)responseObject { 84 | [self.lock lock]; 85 | if (!_responseObject && [self isFinished] && !self.error) { 86 | NSError *error = nil; 87 | self.responseObject = [self.responseSerializer responseObjectForResponse:self.response data:self.responseData error:&error]; 88 | if (error) { 89 | self.responseSerializationError = error; 90 | } 91 | } 92 | [self.lock unlock]; 93 | 94 | return _responseObject; 95 | } 96 | 97 | - (NSError *)error { 98 | if (_responseSerializationError) { 99 | return _responseSerializationError; 100 | } else { 101 | return [super error]; 102 | } 103 | } 104 | 105 | #pragma mark - AFHTTPRequestOperation 106 | 107 | - (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 108 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure 109 | { 110 | // completionBlock is manually nilled out in AFURLConnectionOperation to break the retain cycle. 111 | #pragma clang diagnostic push 112 | #pragma clang diagnostic ignored "-Warc-retain-cycles" 113 | #pragma clang diagnostic ignored "-Wgnu" 114 | self.completionBlock = ^{ 115 | if (self.completionGroup) { 116 | dispatch_group_enter(self.completionGroup); 117 | } 118 | 119 | dispatch_async(http_request_operation_processing_queue(), ^{ 120 | if (self.error) { 121 | if (failure) { 122 | dispatch_group_async(self.completionGroup ?: http_request_operation_completion_group(), self.completionQueue ?: dispatch_get_main_queue(), ^{ 123 | failure(self, self.error); 124 | }); 125 | } 126 | } else { 127 | id responseObject = self.responseObject; 128 | if (self.error) { 129 | if (failure) { 130 | dispatch_group_async(self.completionGroup ?: http_request_operation_completion_group(), self.completionQueue ?: dispatch_get_main_queue(), ^{ 131 | failure(self, self.error); 132 | }); 133 | } 134 | } else { 135 | if (success) { 136 | dispatch_group_async(self.completionGroup ?: http_request_operation_completion_group(), self.completionQueue ?: dispatch_get_main_queue(), ^{ 137 | success(self, responseObject); 138 | }); 139 | } 140 | } 141 | } 142 | 143 | if (self.completionGroup) { 144 | dispatch_group_leave(self.completionGroup); 145 | } 146 | }); 147 | }; 148 | #pragma clang diagnostic pop 149 | } 150 | 151 | #pragma mark - AFURLRequestOperation 152 | 153 | - (void)pause { 154 | [super pause]; 155 | 156 | u_int64_t offset = 0; 157 | if ([self.outputStream propertyForKey:NSStreamFileCurrentOffsetKey]) { 158 | offset = [(NSNumber *)[self.outputStream propertyForKey:NSStreamFileCurrentOffsetKey] unsignedLongLongValue]; 159 | } else { 160 | offset = [(NSData *)[self.outputStream propertyForKey:NSStreamDataWrittenToMemoryStreamKey] length]; 161 | } 162 | 163 | NSMutableURLRequest *mutableURLRequest = [self.request mutableCopy]; 164 | if ([self.response respondsToSelector:@selector(allHeaderFields)] && [[self.response allHeaderFields] valueForKey:@"ETag"]) { 165 | [mutableURLRequest setValue:[[self.response allHeaderFields] valueForKey:@"ETag"] forHTTPHeaderField:@"If-Range"]; 166 | } 167 | [mutableURLRequest setValue:[NSString stringWithFormat:@"bytes=%llu-", offset] forHTTPHeaderField:@"Range"]; 168 | self.request = mutableURLRequest; 169 | } 170 | 171 | #pragma mark - NSSecureCoding 172 | 173 | + (BOOL)supportsSecureCoding { 174 | return YES; 175 | } 176 | 177 | - (id)initWithCoder:(NSCoder *)decoder { 178 | self = [super initWithCoder:decoder]; 179 | if (!self) { 180 | return nil; 181 | } 182 | 183 | self.responseSerializer = [decoder decodeObjectOfClass:[AFHTTPResponseSerializer class] forKey:NSStringFromSelector(@selector(responseSerializer))]; 184 | 185 | return self; 186 | } 187 | 188 | - (void)encodeWithCoder:(NSCoder *)coder { 189 | [super encodeWithCoder:coder]; 190 | 191 | [coder encodeObject:self.responseSerializer forKey:NSStringFromSelector(@selector(responseSerializer))]; 192 | } 193 | 194 | #pragma mark - NSCopying 195 | 196 | - (id)copyWithZone:(NSZone *)zone { 197 | AFHTTPRequestOperation *operation = [super copyWithZone:zone]; 198 | 199 | operation.responseSerializer = [self.responseSerializer copyWithZone:zone]; 200 | operation.completionQueue = self.completionQueue; 201 | operation.completionGroup = self.completionGroup; 202 | 203 | return operation; 204 | } 205 | 206 | @end 207 | -------------------------------------------------------------------------------- /shakefun/shakefun/AFNetworking/AFNetworkReachabilityManager.h: -------------------------------------------------------------------------------- 1 | // AFNetworkReachabilityManager.h 2 | // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | #import 24 | 25 | #ifndef NS_DESIGNATED_INITIALIZER 26 | #if __has_attribute(objc_designated_initializer) 27 | #define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) 28 | #else 29 | #define NS_DESIGNATED_INITIALIZER 30 | #endif 31 | #endif 32 | 33 | typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { 34 | AFNetworkReachabilityStatusUnknown = -1, 35 | AFNetworkReachabilityStatusNotReachable = 0, 36 | AFNetworkReachabilityStatusReachableViaWWAN = 1, 37 | AFNetworkReachabilityStatusReachableViaWiFi = 2, 38 | }; 39 | 40 | NS_ASSUME_NONNULL_BEGIN 41 | 42 | /** 43 | `AFNetworkReachabilityManager` monitors the reachability of domains, and addresses for both WWAN and WiFi network interfaces. 44 | 45 | Reachability can be used to determine background information about why a network operation failed, or to trigger a network operation retrying when a connection is established. It should not be used to prevent a user from initiating a network request, as it's possible that an initial request may be required to establish reachability. 46 | 47 | See Apple's Reachability Sample Code (https://developer.apple.com/library/ios/samplecode/reachability/) 48 | 49 | @warning Instances of `AFNetworkReachabilityManager` must be started with `-startMonitoring` before reachability status can be determined. 50 | */ 51 | @interface AFNetworkReachabilityManager : NSObject 52 | 53 | /** 54 | The current network reachability status. 55 | */ 56 | @property (readonly, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus; 57 | 58 | /** 59 | Whether or not the network is currently reachable. 60 | */ 61 | @property (readonly, nonatomic, assign, getter = isReachable) BOOL reachable; 62 | 63 | /** 64 | Whether or not the network is currently reachable via WWAN. 65 | */ 66 | @property (readonly, nonatomic, assign, getter = isReachableViaWWAN) BOOL reachableViaWWAN; 67 | 68 | /** 69 | Whether or not the network is currently reachable via WiFi. 70 | */ 71 | @property (readonly, nonatomic, assign, getter = isReachableViaWiFi) BOOL reachableViaWiFi; 72 | 73 | ///--------------------- 74 | /// @name Initialization 75 | ///--------------------- 76 | 77 | /** 78 | Returns the shared network reachability manager. 79 | */ 80 | + (instancetype)sharedManager; 81 | 82 | /** 83 | Creates and returns a network reachability manager for the specified domain. 84 | 85 | @param domain The domain used to evaluate network reachability. 86 | 87 | @return An initialized network reachability manager, actively monitoring the specified domain. 88 | */ 89 | + (instancetype)managerForDomain:(NSString *)domain; 90 | 91 | /** 92 | Creates and returns a network reachability manager for the socket address. 93 | 94 | @param address The socket address (`sockaddr_in`) used to evaluate network reachability. 95 | 96 | @return An initialized network reachability manager, actively monitoring the specified socket address. 97 | */ 98 | + (instancetype)managerForAddress:(const void *)address; 99 | 100 | /** 101 | Initializes an instance of a network reachability manager from the specified reachability object. 102 | 103 | @param reachability The reachability object to monitor. 104 | 105 | @return An initialized network reachability manager, actively monitoring the specified reachability. 106 | */ 107 | - (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability NS_DESIGNATED_INITIALIZER; 108 | 109 | ///-------------------------------------------------- 110 | /// @name Starting & Stopping Reachability Monitoring 111 | ///-------------------------------------------------- 112 | 113 | /** 114 | Starts monitoring for changes in network reachability status. 115 | */ 116 | - (void)startMonitoring; 117 | 118 | /** 119 | Stops monitoring for changes in network reachability status. 120 | */ 121 | - (void)stopMonitoring; 122 | 123 | ///------------------------------------------------- 124 | /// @name Getting Localized Reachability Description 125 | ///------------------------------------------------- 126 | 127 | /** 128 | Returns a localized string representation of the current network reachability status. 129 | */ 130 | - (NSString *)localizedNetworkReachabilityStatusString; 131 | 132 | ///--------------------------------------------------- 133 | /// @name Setting Network Reachability Change Callback 134 | ///--------------------------------------------------- 135 | 136 | /** 137 | Sets a callback to be executed when the network availability of the `baseURL` host changes. 138 | 139 | @param block A block object to be executed when the network availability of the `baseURL` host changes.. This block has no return value and takes a single argument which represents the various reachability states from the device to the `baseURL`. 140 | */ 141 | - (void)setReachabilityStatusChangeBlock:(nullable void (^)(AFNetworkReachabilityStatus status))block; 142 | 143 | @end 144 | 145 | ///---------------- 146 | /// @name Constants 147 | ///---------------- 148 | 149 | /** 150 | ## Network Reachability 151 | 152 | The following constants are provided by `AFNetworkReachabilityManager` as possible network reachability statuses. 153 | 154 | enum { 155 | AFNetworkReachabilityStatusUnknown, 156 | AFNetworkReachabilityStatusNotReachable, 157 | AFNetworkReachabilityStatusReachableViaWWAN, 158 | AFNetworkReachabilityStatusReachableViaWiFi, 159 | } 160 | 161 | `AFNetworkReachabilityStatusUnknown` 162 | The `baseURL` host reachability is not known. 163 | 164 | `AFNetworkReachabilityStatusNotReachable` 165 | The `baseURL` host cannot be reached. 166 | 167 | `AFNetworkReachabilityStatusReachableViaWWAN` 168 | The `baseURL` host can be reached via a cellular connection, such as EDGE or GPRS. 169 | 170 | `AFNetworkReachabilityStatusReachableViaWiFi` 171 | The `baseURL` host can be reached via a Wi-Fi connection. 172 | 173 | ### Keys for Notification UserInfo Dictionary 174 | 175 | Strings that are used as keys in a `userInfo` dictionary in a network reachability status change notification. 176 | 177 | `AFNetworkingReachabilityNotificationStatusItem` 178 | A key in the userInfo dictionary in a `AFNetworkingReachabilityDidChangeNotification` notification. 179 | The corresponding value is an `NSNumber` object representing the `AFNetworkReachabilityStatus` value for the current reachability status. 180 | */ 181 | 182 | ///-------------------- 183 | /// @name Notifications 184 | ///-------------------- 185 | 186 | /** 187 | Posted when network reachability changes. 188 | This notification assigns no notification object. The `userInfo` dictionary contains an `NSNumber` object under the `AFNetworkingReachabilityNotificationStatusItem` key, representing the `AFNetworkReachabilityStatus` value for the current network reachability. 189 | 190 | @warning In order for network reachability to be monitored, include the `SystemConfiguration` framework in the active target's "Link Binary With Library" build phase, and add `#import ` to the header prefix of the project (`Prefix.pch`). 191 | */ 192 | extern NSString * const AFNetworkingReachabilityDidChangeNotification; 193 | extern NSString * const AFNetworkingReachabilityNotificationStatusItem; 194 | 195 | ///-------------------- 196 | /// @name Functions 197 | ///-------------------- 198 | 199 | /** 200 | Returns a localized string representation of an `AFNetworkReachabilityStatus` value. 201 | */ 202 | extern NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status); 203 | 204 | NS_ASSUME_NONNULL_END 205 | -------------------------------------------------------------------------------- /shakefun/shakefun/AFNetworking/AFNetworkReachabilityManager.m: -------------------------------------------------------------------------------- 1 | // AFNetworkReachabilityManager.m 2 | // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import "AFNetworkReachabilityManager.h" 23 | 24 | #import 25 | #import 26 | #import 27 | #import 28 | #import 29 | 30 | NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire.networking.reachability.change"; 31 | NSString * const AFNetworkingReachabilityNotificationStatusItem = @"AFNetworkingReachabilityNotificationStatusItem"; 32 | 33 | typedef void (^AFNetworkReachabilityStatusBlock)(AFNetworkReachabilityStatus status); 34 | 35 | typedef NS_ENUM(NSUInteger, AFNetworkReachabilityAssociation) { 36 | AFNetworkReachabilityForAddress = 1, 37 | AFNetworkReachabilityForAddressPair = 2, 38 | AFNetworkReachabilityForName = 3, 39 | }; 40 | 41 | NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status) { 42 | switch (status) { 43 | case AFNetworkReachabilityStatusNotReachable: 44 | return NSLocalizedStringFromTable(@"Not Reachable", @"AFNetworking", nil); 45 | case AFNetworkReachabilityStatusReachableViaWWAN: 46 | return NSLocalizedStringFromTable(@"Reachable via WWAN", @"AFNetworking", nil); 47 | case AFNetworkReachabilityStatusReachableViaWiFi: 48 | return NSLocalizedStringFromTable(@"Reachable via WiFi", @"AFNetworking", nil); 49 | case AFNetworkReachabilityStatusUnknown: 50 | default: 51 | return NSLocalizedStringFromTable(@"Unknown", @"AFNetworking", nil); 52 | } 53 | } 54 | 55 | static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags(SCNetworkReachabilityFlags flags) { 56 | BOOL isReachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0); 57 | BOOL needsConnection = ((flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0); 58 | BOOL canConnectionAutomatically = (((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || ((flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)); 59 | BOOL canConnectWithoutUserInteraction = (canConnectionAutomatically && (flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0); 60 | BOOL isNetworkReachable = (isReachable && (!needsConnection || canConnectWithoutUserInteraction)); 61 | 62 | AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusUnknown; 63 | if (isNetworkReachable == NO) { 64 | status = AFNetworkReachabilityStatusNotReachable; 65 | } 66 | #if TARGET_OS_IPHONE 67 | else if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) { 68 | status = AFNetworkReachabilityStatusReachableViaWWAN; 69 | } 70 | #endif 71 | else { 72 | status = AFNetworkReachabilityStatusReachableViaWiFi; 73 | } 74 | 75 | return status; 76 | } 77 | 78 | static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) { 79 | AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags); 80 | AFNetworkReachabilityStatusBlock block = (__bridge AFNetworkReachabilityStatusBlock)info; 81 | if (block) { 82 | block(status); 83 | } 84 | 85 | 86 | dispatch_async(dispatch_get_main_queue(), ^{ 87 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 88 | NSDictionary *userInfo = @{ AFNetworkingReachabilityNotificationStatusItem: @(status) }; 89 | [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:userInfo]; 90 | }); 91 | 92 | } 93 | 94 | static const void * AFNetworkReachabilityRetainCallback(const void *info) { 95 | return Block_copy(info); 96 | } 97 | 98 | static void AFNetworkReachabilityReleaseCallback(const void *info) { 99 | if (info) { 100 | Block_release(info); 101 | } 102 | } 103 | 104 | @interface AFNetworkReachabilityManager () 105 | @property (readwrite, nonatomic, strong) id networkReachability; 106 | @property (readwrite, nonatomic, assign) AFNetworkReachabilityAssociation networkReachabilityAssociation; 107 | @property (readwrite, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus; 108 | @property (readwrite, nonatomic, copy) AFNetworkReachabilityStatusBlock networkReachabilityStatusBlock; 109 | @end 110 | 111 | @implementation AFNetworkReachabilityManager 112 | 113 | + (instancetype)sharedManager { 114 | static AFNetworkReachabilityManager *_sharedManager = nil; 115 | static dispatch_once_t onceToken; 116 | dispatch_once(&onceToken, ^{ 117 | struct sockaddr_in address; 118 | bzero(&address, sizeof(address)); 119 | address.sin_len = sizeof(address); 120 | address.sin_family = AF_INET; 121 | 122 | _sharedManager = [self managerForAddress:&address]; 123 | }); 124 | 125 | return _sharedManager; 126 | } 127 | 128 | + (instancetype)managerForDomain:(NSString *)domain { 129 | SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [domain UTF8String]); 130 | 131 | AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability]; 132 | manager.networkReachabilityAssociation = AFNetworkReachabilityForName; 133 | 134 | return manager; 135 | } 136 | 137 | + (instancetype)managerForAddress:(const void *)address { 138 | SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)address); 139 | 140 | AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability]; 141 | manager.networkReachabilityAssociation = AFNetworkReachabilityForAddress; 142 | 143 | return manager; 144 | } 145 | 146 | - (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability { 147 | self = [super init]; 148 | if (!self) { 149 | return nil; 150 | } 151 | 152 | self.networkReachability = CFBridgingRelease(reachability); 153 | self.networkReachabilityStatus = AFNetworkReachabilityStatusUnknown; 154 | 155 | return self; 156 | } 157 | 158 | - (instancetype)init NS_UNAVAILABLE 159 | { 160 | return nil; 161 | } 162 | 163 | - (void)dealloc { 164 | [self stopMonitoring]; 165 | } 166 | 167 | #pragma mark - 168 | 169 | - (BOOL)isReachable { 170 | return [self isReachableViaWWAN] || [self isReachableViaWiFi]; 171 | } 172 | 173 | - (BOOL)isReachableViaWWAN { 174 | return self.networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWWAN; 175 | } 176 | 177 | - (BOOL)isReachableViaWiFi { 178 | return self.networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWiFi; 179 | } 180 | 181 | #pragma mark - 182 | 183 | - (void)startMonitoring { 184 | [self stopMonitoring]; 185 | 186 | if (!self.networkReachability) { 187 | return; 188 | } 189 | 190 | __weak __typeof(self)weakSelf = self; 191 | AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) { 192 | __strong __typeof(weakSelf)strongSelf = weakSelf; 193 | 194 | strongSelf.networkReachabilityStatus = status; 195 | if (strongSelf.networkReachabilityStatusBlock) { 196 | strongSelf.networkReachabilityStatusBlock(status); 197 | } 198 | 199 | }; 200 | 201 | id networkReachability = self.networkReachability; 202 | SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL}; 203 | SCNetworkReachabilitySetCallback((__bridge SCNetworkReachabilityRef)networkReachability, AFNetworkReachabilityCallback, &context); 204 | SCNetworkReachabilityScheduleWithRunLoop((__bridge SCNetworkReachabilityRef)networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); 205 | 206 | switch (self.networkReachabilityAssociation) { 207 | case AFNetworkReachabilityForName: 208 | break; 209 | case AFNetworkReachabilityForAddress: 210 | case AFNetworkReachabilityForAddressPair: 211 | default: { 212 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{ 213 | SCNetworkReachabilityFlags flags; 214 | SCNetworkReachabilityGetFlags((__bridge SCNetworkReachabilityRef)networkReachability, &flags); 215 | AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags); 216 | dispatch_async(dispatch_get_main_queue(), ^{ 217 | callback(status); 218 | 219 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 220 | [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:@{ AFNetworkingReachabilityNotificationStatusItem: @(status) }]; 221 | 222 | 223 | }); 224 | }); 225 | } 226 | break; 227 | } 228 | } 229 | 230 | - (void)stopMonitoring { 231 | if (!self.networkReachability) { 232 | return; 233 | } 234 | 235 | SCNetworkReachabilityUnscheduleFromRunLoop((__bridge SCNetworkReachabilityRef)self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); 236 | } 237 | 238 | #pragma mark - 239 | 240 | - (NSString *)localizedNetworkReachabilityStatusString { 241 | return AFStringFromNetworkReachabilityStatus(self.networkReachabilityStatus); 242 | } 243 | 244 | #pragma mark - 245 | 246 | - (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block { 247 | self.networkReachabilityStatusBlock = block; 248 | } 249 | 250 | #pragma mark - NSKeyValueObserving 251 | 252 | + (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { 253 | if ([key isEqualToString:@"reachable"] || [key isEqualToString:@"reachableViaWWAN"] || [key isEqualToString:@"reachableViaWiFi"]) { 254 | return [NSSet setWithObject:@"networkReachabilityStatus"]; 255 | } 256 | 257 | return [super keyPathsForValuesAffectingValueForKey:key]; 258 | } 259 | 260 | @end 261 | -------------------------------------------------------------------------------- /shakefun/shakefun/AFNetworking/AFNetworking.h: -------------------------------------------------------------------------------- 1 | // AFNetworking.h 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com/) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import 25 | 26 | #ifndef _AFNETWORKING_ 27 | #define _AFNETWORKING_ 28 | 29 | #import "AFURLRequestSerialization.h" 30 | #import "AFURLResponseSerialization.h" 31 | #import "AFSecurityPolicy.h" 32 | #import "AFNetworkReachabilityManager.h" 33 | 34 | #import "AFURLConnectionOperation.h" 35 | #import "AFHTTPRequestOperation.h" 36 | #import "AFHTTPRequestOperationManager.h" 37 | 38 | #if ( ( defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090) || \ 39 | ( defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 ) ) 40 | #import "AFURLSessionManager.h" 41 | #import "AFHTTPSessionManager.h" 42 | #endif 43 | 44 | #endif /* _AFNETWORKING_ */ 45 | -------------------------------------------------------------------------------- /shakefun/shakefun/AFNetworking/AFSecurityPolicy.h: -------------------------------------------------------------------------------- 1 | // AFSecurityPolicy.h 2 | // Copyright (c) 2011–2015 Alamofire Software Foundation (http://alamofire.org/) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | #import 24 | 25 | typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { 26 | AFSSLPinningModeNone, 27 | AFSSLPinningModePublicKey, 28 | AFSSLPinningModeCertificate, 29 | }; 30 | 31 | /** 32 | `AFSecurityPolicy` evaluates server trust against pinned X.509 certificates and public keys over secure connections. 33 | 34 | Adding pinned SSL certificates to your app helps prevent man-in-the-middle attacks and other vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged to route all communication over an HTTPS connection with SSL pinning configured and enabled. 35 | */ 36 | 37 | NS_ASSUME_NONNULL_BEGIN 38 | 39 | @interface AFSecurityPolicy : NSObject 40 | 41 | /** 42 | The criteria by which server trust should be evaluated against the pinned SSL certificates. Defaults to `AFSSLPinningModeNone`. 43 | */ 44 | @property (readonly, nonatomic, assign) AFSSLPinningMode SSLPinningMode; 45 | 46 | /** 47 | The certificates used to evaluate server trust according to the SSL pinning mode. By default, this property is set to any (`.cer`) certificates included in the app bundle. Note that if you create an array with duplicate certificates, the duplicate certificates will be removed. Note that if pinning is enabled, `evaluateServerTrust:forDomain:` will return true if any pinned certificate matches. 48 | */ 49 | @property (nonatomic, strong, nullable) NSArray *pinnedCertificates; 50 | 51 | /** 52 | Whether or not to trust servers with an invalid or expired SSL certificates. Defaults to `NO`. 53 | */ 54 | @property (nonatomic, assign) BOOL allowInvalidCertificates; 55 | 56 | /** 57 | Whether or not to validate the domain name in the certificate's CN field. Defaults to `YES`. 58 | */ 59 | @property (nonatomic, assign) BOOL validatesDomainName; 60 | 61 | ///----------------------------------------- 62 | /// @name Getting Specific Security Policies 63 | ///----------------------------------------- 64 | 65 | /** 66 | Returns the shared default security policy, which does not allow invalid certificates, validates domain name, and does not validate against pinned certificates or public keys. 67 | 68 | @return The default security policy. 69 | */ 70 | + (instancetype)defaultPolicy; 71 | 72 | ///--------------------- 73 | /// @name Initialization 74 | ///--------------------- 75 | 76 | /** 77 | Creates and returns a security policy with the specified pinning mode. 78 | 79 | @param pinningMode The SSL pinning mode. 80 | 81 | @return A new security policy. 82 | */ 83 | + (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode; 84 | 85 | ///------------------------------ 86 | /// @name Evaluating Server Trust 87 | ///------------------------------ 88 | 89 | /** 90 | Whether or not the specified server trust should be accepted, based on the security policy. 91 | 92 | This method should be used when responding to an authentication challenge from a server. 93 | 94 | @param serverTrust The X.509 certificate trust of the server. 95 | 96 | @return Whether or not to trust the server. 97 | 98 | @warning This method has been deprecated in favor of `-evaluateServerTrust:forDomain:`. 99 | */ 100 | - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust DEPRECATED_ATTRIBUTE; 101 | 102 | /** 103 | Whether or not the specified server trust should be accepted, based on the security policy. 104 | 105 | This method should be used when responding to an authentication challenge from a server. 106 | 107 | @param serverTrust The X.509 certificate trust of the server. 108 | @param domain The domain of serverTrust. If `nil`, the domain will not be validated. 109 | 110 | @return Whether or not to trust the server. 111 | */ 112 | - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust 113 | forDomain:(nullable NSString *)domain; 114 | 115 | @end 116 | 117 | NS_ASSUME_NONNULL_END 118 | 119 | ///---------------- 120 | /// @name Constants 121 | ///---------------- 122 | 123 | /** 124 | ## SSL Pinning Modes 125 | 126 | The following constants are provided by `AFSSLPinningMode` as possible SSL pinning modes. 127 | 128 | enum { 129 | AFSSLPinningModeNone, 130 | AFSSLPinningModePublicKey, 131 | AFSSLPinningModeCertificate, 132 | } 133 | 134 | `AFSSLPinningModeNone` 135 | Do not used pinned certificates to validate servers. 136 | 137 | `AFSSLPinningModePublicKey` 138 | Validate host certificates against public keys of pinned certificates. 139 | 140 | `AFSSLPinningModeCertificate` 141 | Validate host certificates against pinned certificates. 142 | */ 143 | -------------------------------------------------------------------------------- /shakefun/shakefun/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // shakefun 4 | // 5 | // Created by zm on 15/9/9. 6 | // Copyright (c) 2015年 zm. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (strong, nonatomic) UIWindow *window; 15 | 16 | @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext; 17 | @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel; 18 | @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator; 19 | 20 | - (void)saveContext; 21 | - (NSURL *)applicationDocumentsDirectory; 22 | 23 | 24 | @end 25 | 26 | -------------------------------------------------------------------------------- /shakefun/shakefun/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // shakefun 4 | // 5 | // Created by zm on 15/9/9. 6 | // Copyright (c) 2015年 zm. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "ViewController.h" 11 | #import "CoreData+MagicalRecord.h" 12 | 13 | @interface AppDelegate () 14 | 15 | @end 16 | 17 | @implementation AppDelegate 18 | 19 | 20 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 21 | // Override point for customization after application launch. 22 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 23 | [MagicalRecord setupAutoMigratingCoreDataStack]; 24 | 25 | ViewController *rootview = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"ViewController"]; 26 | UINavigationController *naviController = [[UINavigationController alloc] initWithRootViewController:rootview]; 27 | self.window.rootViewController = naviController; 28 | [self.window makeKeyAndVisible]; 29 | return YES; 30 | } 31 | 32 | - (void)applicationWillResignActive:(UIApplication *)application { 33 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 34 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 35 | } 36 | 37 | - (void)applicationDidEnterBackground:(UIApplication *)application { 38 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 39 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 40 | } 41 | 42 | - (void)applicationWillEnterForeground:(UIApplication *)application { 43 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 44 | } 45 | 46 | - (void)applicationDidBecomeActive:(UIApplication *)application { 47 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 48 | } 49 | 50 | - (void)applicationWillTerminate:(UIApplication *)application { 51 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 52 | // Saves changes in the application's managed object context before the application terminates. 53 | [self saveContext]; 54 | } 55 | 56 | #pragma mark - Core Data stack 57 | 58 | @synthesize managedObjectContext = _managedObjectContext; 59 | @synthesize managedObjectModel = _managedObjectModel; 60 | @synthesize persistentStoreCoordinator = _persistentStoreCoordinator; 61 | 62 | - (NSURL *)applicationDocumentsDirectory { 63 | // The directory the application uses to store the Core Data store file. This code uses a directory named "zm.shakefun" in the application's documents directory. 64 | return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 65 | } 66 | 67 | - (NSManagedObjectModel *)managedObjectModel { 68 | // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model. 69 | if (_managedObjectModel != nil) { 70 | return _managedObjectModel; 71 | } 72 | NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"shakefun" withExtension:@"momd"]; 73 | _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 74 | return _managedObjectModel; 75 | } 76 | 77 | - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 78 | // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. 79 | if (_persistentStoreCoordinator != nil) { 80 | return _persistentStoreCoordinator; 81 | } 82 | 83 | // Create the coordinator and store 84 | 85 | _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 86 | NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"shakefun.sqlite"]; 87 | NSError *error = nil; 88 | NSString *failureReason = @"There was an error creating or loading the application's saved data."; 89 | if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { 90 | // Report any error we got. 91 | NSMutableDictionary *dict = [NSMutableDictionary dictionary]; 92 | dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data"; 93 | dict[NSLocalizedFailureReasonErrorKey] = failureReason; 94 | dict[NSUnderlyingErrorKey] = error; 95 | error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict]; 96 | // Replace this with code to handle the error appropriately. 97 | // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 98 | NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 99 | abort(); 100 | } 101 | 102 | return _persistentStoreCoordinator; 103 | } 104 | 105 | 106 | - (NSManagedObjectContext *)managedObjectContext { 107 | // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) 108 | if (_managedObjectContext != nil) { 109 | return _managedObjectContext; 110 | } 111 | 112 | NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 113 | if (!coordinator) { 114 | return nil; 115 | } 116 | _managedObjectContext = [[NSManagedObjectContext alloc] init]; 117 | [_managedObjectContext setPersistentStoreCoordinator:coordinator]; 118 | return _managedObjectContext; 119 | } 120 | 121 | #pragma mark - Core Data Saving support 122 | 123 | - (void)saveContext { 124 | NSManagedObjectContext *managedObjectContext = self.managedObjectContext; 125 | if (managedObjectContext != nil) { 126 | NSError *error = nil; 127 | if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { 128 | // Replace this implementation with code to handle the error appropriately. 129 | // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 130 | NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 131 | abort(); 132 | } 133 | } 134 | } 135 | 136 | @end 137 | -------------------------------------------------------------------------------- /shakefun/shakefun/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /shakefun/shakefun/CollectViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CollectViewController.h 3 | // shakefun 4 | // 5 | // Created by zm on 15/9/9. 6 | // Copyright (c) 2015年 zm. All rights reserved. 7 | // 8 | 9 | #ifndef shakefun_CollectViewController_h 10 | #define shakefun_CollectViewController_h 11 | #import 12 | 13 | @interface CollectViewController : UIViewController 14 | { 15 | 16 | } 17 | - (IBAction)buttonStartCollectToggle:(id)sender; 18 | @property (weak, nonatomic) IBOutlet UITextView *textViewLogInfo; 19 | @property (weak, nonatomic) IBOutlet UITextField *textfieldPageNum; 20 | 21 | @end 22 | #endif 23 | -------------------------------------------------------------------------------- /shakefun/shakefun/CollectViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CollectViewController.m 3 | // shakefun 4 | // 5 | // Created by zm on 15/9/9. 6 | // Copyright (c) 2015年 zm. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CollectViewController.h" 11 | #import "URLEntity.h" 12 | #import "ViewController.h" 13 | #import "AFNetworking.h" 14 | 15 | @implementation CollectViewController 16 | { 17 | 18 | } 19 | -(void)viewDidLoad 20 | { 21 | [super viewDidLoad]; 22 | [self.navigationController setNavigationBarHidden:NO animated:YES]; 23 | self.textViewLogInfo.text = @""; 24 | } 25 | 26 | - (IBAction)buttonStartCollectToggle:(id)sender { 27 | //http://www.hao123.com/gaoxiao?pn=2 28 | 29 | [self.view endEditing:YES]; 30 | 31 | if (self.textfieldPageNum.text.length <= 0) { 32 | return; 33 | } 34 | NSInteger page = [self.textfieldPageNum.text integerValue]; 35 | NSString *pageurl = [NSString stringWithFormat:@"http://www.hao123.com/gaoxiao?pn=%ld", (long)page]; 36 | AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 37 | manager.responseSerializer = [AFHTTPResponseSerializer serializer]; 38 | 39 | manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"]; 40 | //发送请求 41 | [manager POST:pageurl parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { 42 | NSString *result = [[NSString alloc]initWithData:operation.responseData encoding:NSUTF8StringEncoding]; 43 | 44 | NSArray *urls = [result componentsSeparatedFromString:@" 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | zm.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSAllowsArbitraryLoads 28 | 29 | 30 | NSMainNibFile 31 | LaunchScreen 32 | UILaunchStoryboardName 33 | LaunchScreen 34 | UIRequiredDeviceCapabilities 35 | 36 | armv7 37 | 38 | UISupportedInterfaceOrientations 39 | 40 | UIInterfaceOrientationPortrait 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/DataImport/MagicalImportFunctions.h: -------------------------------------------------------------------------------- 1 | // 2 | // MagicalImportFunctions.h 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/7/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | NSDate * adjustDateForDST(NSDate *date); 13 | NSDate * dateFromString(NSString *value, NSString *format); 14 | NSNumber * numberFromString(NSString *value); 15 | NSString * attributeNameFromString(NSString *value); 16 | NSString * primaryKeyNameFromString(NSString *value); 17 | 18 | #if TARGET_OS_IPHONE 19 | #import 20 | UIColor * UIColorFromString(NSString *serializedColor); 21 | 22 | #else 23 | #import 24 | NSColor * NSColorFromString(NSString *serializedColor); 25 | 26 | #endif 27 | extern id (*colorFromString)(NSString *); 28 | 29 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/DataImport/MagicalImportFunctions.m: -------------------------------------------------------------------------------- 1 | // 2 | // MagicalImportFunctions.m 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/7/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "MagicalImportFunctions.h" 10 | 11 | 12 | #pragma mark - Data import helper functions 13 | 14 | NSString * attributeNameFromString(NSString *value) 15 | { 16 | NSString *firstCharacter = [[value substringToIndex:1] capitalizedString]; 17 | return [firstCharacter stringByAppendingString:[value substringFromIndex:1]]; 18 | } 19 | 20 | NSString * primaryKeyNameFromString(NSString *value) 21 | { 22 | NSString *firstCharacter = [[value substringToIndex:1] lowercaseString]; 23 | return [firstCharacter stringByAppendingFormat:@"%@ID", [value substringFromIndex:1]]; 24 | } 25 | 26 | NSDate * adjustDateForDST(NSDate *date) 27 | { 28 | NSTimeInterval dstOffset = [[NSTimeZone localTimeZone] daylightSavingTimeOffsetForDate:date]; 29 | NSDate *actualDate = [date dateByAddingTimeInterval:dstOffset]; 30 | 31 | return actualDate; 32 | } 33 | 34 | NSDate * dateFromString(NSString *value, NSString *format) 35 | { 36 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 37 | [formatter setTimeZone:[NSTimeZone localTimeZone]]; 38 | [formatter setLocale:[NSLocale currentLocale]]; 39 | [formatter setDateFormat:format]; 40 | 41 | NSDate *parsedDate = [formatter dateFromString:value]; 42 | 43 | return parsedDate; 44 | } 45 | 46 | NSNumber * numberFromString(NSString *value) { 47 | return [NSNumber numberWithDouble:[value doubleValue]]; 48 | } 49 | 50 | NSInteger* newColorComponentsFromString(NSString *serializedColor); 51 | NSInteger* newColorComponentsFromString(NSString *serializedColor) 52 | { 53 | NSScanner *colorScanner = [NSScanner scannerWithString:serializedColor]; 54 | NSString *colorType; 55 | [colorScanner scanUpToString:@"(" intoString:&colorType]; 56 | 57 | NSInteger *componentValues = malloc(4 * sizeof(NSInteger)); 58 | if ([colorType hasPrefix:@"rgba"]) 59 | { 60 | NSCharacterSet *rgbaCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@"(,)"]; 61 | 62 | NSInteger *componentValue = componentValues; 63 | while (![colorScanner isAtEnd]) 64 | { 65 | [colorScanner scanCharactersFromSet:rgbaCharacterSet intoString:nil]; 66 | [colorScanner scanInteger:componentValue]; 67 | componentValue++; 68 | } 69 | } 70 | //else if ([colorType hasPrefix:@"hsba"]) 71 | //else if ([colorType hasPrefix:@""]) 72 | return componentValues; 73 | } 74 | 75 | #if TARGET_OS_IPHONE 76 | 77 | UIColor * UIColorFromString(NSString *serializedColor) 78 | { 79 | NSInteger *componentValues = newColorComponentsFromString(serializedColor); 80 | UIColor *color = [UIColor colorWithRed:(componentValues[0] / 255.0f) 81 | green:(componentValues[1] / 255.0f) 82 | blue:(componentValues[2] / 255.0f) 83 | alpha:componentValues[3]]; 84 | 85 | free(componentValues); 86 | return color; 87 | } 88 | id (*colorFromString)(NSString *) = UIColorFromString; 89 | 90 | #else 91 | 92 | NSColor * NSColorFromString(NSString *serializedColor) 93 | { 94 | NSInteger *componentValues = newColorComponentsFromString(serializedColor); 95 | NSColor *color = [NSColor colorWithDeviceRed:(componentValues[0] / 255.0f) 96 | green:(componentValues[1] / 255.0f) 97 | blue:(componentValues[2] / 255.0f) 98 | alpha:componentValues[3]]; 99 | free(componentValues); 100 | return color; 101 | } 102 | id (*colorFromString)(NSString *) = NSColorFromString; 103 | 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/DataImport/NSAttributeDescription+MagicalDataImport.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSAttributeDescription+MagicalDataImport.h 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 9/4/11. 6 | // Copyright 2011 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSAttributeDescription (MagicalRecord_DataImport) 12 | 13 | - (NSString *) MR_primaryKey; 14 | - (id) MR_valueForKeyPath:(NSString *)keyPath fromObjectData:(id)objectData; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/DataImport/NSAttributeDescription+MagicalDataImport.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSAttributeDescription+MagicalDataImport.m 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 9/4/11. 6 | // Copyright 2011 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "NSAttributeDescription+MagicalDataImport.h" 10 | #import "NSManagedObject+MagicalDataImport.h" 11 | #import "MagicalImportFunctions.h" 12 | 13 | @implementation NSAttributeDescription (MagicalRecord_DataImport) 14 | 15 | - (NSString *) MR_primaryKey; 16 | { 17 | return nil; 18 | } 19 | 20 | - (id) MR_valueForKeyPath:(NSString *)keyPath fromObjectData:(id)objectData; 21 | { 22 | id value = [objectData valueForKeyPath:keyPath]; 23 | 24 | NSAttributeType attributeType = [self attributeType]; 25 | NSString *desiredAttributeType = [[self userInfo] valueForKey:kMagicalRecordImportAttributeValueClassNameKey]; 26 | if (desiredAttributeType) 27 | { 28 | if ([desiredAttributeType hasSuffix:@"Color"]) 29 | { 30 | value = colorFromString(value); 31 | } 32 | } 33 | else 34 | { 35 | if (attributeType == NSDateAttributeType) 36 | { 37 | if (![value isKindOfClass:[NSDate class]]) 38 | { 39 | NSString *dateFormat = [[self userInfo] valueForKey:kMagicalRecordImportCustomDateFormatKey]; 40 | value = dateFromString([value description], dateFormat ?: kMagicalRecordImportDefaultDateFormatString); 41 | } 42 | // value = adjustDateForDST(value); 43 | } 44 | else if (attributeType == NSInteger16AttributeType || 45 | attributeType == NSInteger32AttributeType || 46 | attributeType == NSInteger64AttributeType || 47 | attributeType == NSDecimalAttributeType || 48 | attributeType == NSDoubleAttributeType || 49 | attributeType == NSFloatAttributeType) { 50 | if (![value isKindOfClass:[NSNumber class]] && value != [NSNull null]) { 51 | value = numberFromString([value description]); 52 | } 53 | } 54 | } 55 | 56 | return value == [NSNull null] ? nil : value; 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/DataImport/NSEntityDescription+MagicalDataImport.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSEntityDescription+MagicalDataImport.h 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 9/5/11. 6 | // Copyright 2011 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | 10 | @interface NSEntityDescription (MagicalRecord_DataImport) 11 | 12 | - (NSAttributeDescription *) MR_primaryAttributeToRelateBy; 13 | - (NSManagedObject *) MR_createInstanceInContext:(NSManagedObjectContext *)context; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/DataImport/NSEntityDescription+MagicalDataImport.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSEntityDescription+MagicalDataImport.m 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 9/5/11. 6 | // Copyright 2011 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "CoreData+MagicalRecord.h" 10 | 11 | @implementation NSEntityDescription (MagicalRecord_DataImport) 12 | 13 | - (NSAttributeDescription *) MR_primaryAttributeToRelateBy; 14 | { 15 | NSString *lookupKey = [[self userInfo] valueForKey:kMagicalRecordImportRelationshipLinkedByKey] ?: primaryKeyNameFromString([self name]); 16 | NSDictionary *attributesByName = [self attributesByName]; 17 | 18 | if ([attributesByName count] == 0) return nil; 19 | 20 | NSAttributeDescription *primaryAttribute = [attributesByName objectForKey:lookupKey]; 21 | 22 | return primaryAttribute; 23 | } 24 | 25 | - (NSManagedObject *) MR_createInstanceInContext:(NSManagedObjectContext *)context; 26 | { 27 | Class relatedClass = NSClassFromString([self managedObjectClassName]); 28 | NSManagedObject *newInstance = [relatedClass MR_createInContext:context]; 29 | 30 | return newInstance; 31 | } 32 | 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/DataImport/NSNumber+MagicalDataImport.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSNumber+MagicalDataImport.h 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 9/4/11. 6 | // Copyright 2011 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSNumber (MagicalRecord_DataImport) 12 | 13 | - (NSString *) MR_lookupKeyForAttribute:(NSAttributeDescription *)attributeInfo; 14 | - (id) MR_relatedValueForRelationship:(NSRelationshipDescription *)relationshipInfo; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/DataImport/NSNumber+MagicalDataImport.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSNumber+MagicalDataImport.m 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 9/4/11. 6 | // Copyright 2011 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "NSNumber+MagicalDataImport.h" 10 | 11 | 12 | 13 | @implementation NSNumber (MagicalRecord_DataImport) 14 | 15 | - (id) MR_relatedValueForRelationship:(NSRelationshipDescription *)relationshipInfo 16 | { 17 | return self; 18 | } 19 | 20 | - (NSString *) MR_lookupKeyForAttribute:(NSAttributeDescription *)attributeInfo 21 | { 22 | return nil; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/DataImport/NSObject+MagicalDataImport.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+MagicalDataImport.h 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 9/4/11. 6 | // Copyright 2011 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (MagicalRecord_DataImport) 12 | 13 | - (NSString *) MR_lookupKeyForAttribute:(NSAttributeDescription *)attributeInfo; 14 | - (id) MR_valueForAttribute:(NSAttributeDescription *)attributeInfo; 15 | 16 | - (NSString *) MR_lookupKeyForRelationship:(NSRelationshipDescription *)relationshipInfo; 17 | - (id) MR_relatedValueForRelationship:(NSRelationshipDescription *)relationshipInfo; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/DataImport/NSObject+MagicalDataImport.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+MagicalDataImport.m 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 9/4/11. 6 | // Copyright 2011 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "NSObject+MagicalDataImport.h" 10 | #import "NSManagedObject+MagicalDataImport.h" 11 | #import "MagicalRecord.h" 12 | #import "CoreData+MagicalRecord.h" 13 | 14 | NSUInteger const kMagicalRecordImportMaximumAttributeFailoverDepth = 10; 15 | 16 | 17 | @implementation NSObject (MagicalRecord_DataImport) 18 | 19 | //#warning If you implement valueForUndefinedKey: in any NSObject in your code, this may be the problem if something broke 20 | - (id) MR_valueForUndefinedKey:(NSString *)key 21 | { 22 | return nil; 23 | } 24 | 25 | - (NSString *) MR_lookupKeyForAttribute:(NSAttributeDescription *)attributeInfo; 26 | { 27 | NSString *attributeName = [attributeInfo name]; 28 | NSString *lookupKey = [[attributeInfo userInfo] valueForKey:kMagicalRecordImportAttributeKeyMapKey] ?: attributeName; 29 | 30 | id value = [self valueForKeyPath:lookupKey]; 31 | 32 | for (NSUInteger i = 1; i < kMagicalRecordImportMaximumAttributeFailoverDepth && value == nil; i++) 33 | { 34 | attributeName = [NSString stringWithFormat:@"%@.%lu", kMagicalRecordImportAttributeKeyMapKey, (unsigned long)i]; 35 | lookupKey = [[attributeInfo userInfo] valueForKey:attributeName]; 36 | if (lookupKey == nil) 37 | { 38 | return nil; 39 | } 40 | value = [self valueForKeyPath:lookupKey]; 41 | } 42 | 43 | return value != nil ? lookupKey : nil; 44 | } 45 | 46 | - (id) MR_valueForAttribute:(NSAttributeDescription *)attributeInfo 47 | { 48 | NSString *lookupKey = [self MR_lookupKeyForAttribute:attributeInfo]; 49 | return lookupKey ? [self valueForKeyPath:lookupKey] : nil; 50 | } 51 | 52 | - (NSString *) MR_lookupKeyForRelationship:(NSRelationshipDescription *)relationshipInfo 53 | { 54 | NSEntityDescription *destinationEntity = [relationshipInfo destinationEntity]; 55 | if (destinationEntity == nil) 56 | { 57 | MRLog(@"Unable to find entity for type '%@'", [self valueForKey:kMagicalRecordImportRelationshipTypeKey]); 58 | return nil; 59 | } 60 | 61 | NSString *primaryKeyName = [relationshipInfo MR_primaryKey]; 62 | 63 | NSAttributeDescription *primaryKeyAttribute = [[destinationEntity attributesByName] valueForKey:primaryKeyName]; 64 | NSString *lookupKey = [[primaryKeyAttribute userInfo] valueForKey:kMagicalRecordImportAttributeKeyMapKey] ?: [primaryKeyAttribute name]; 65 | 66 | return lookupKey; 67 | } 68 | 69 | - (id) MR_relatedValueForRelationship:(NSRelationshipDescription *)relationshipInfo 70 | { 71 | NSString *lookupKey = [self MR_lookupKeyForRelationship:relationshipInfo]; 72 | return lookupKey ? [self valueForKeyPath:lookupKey] : nil; 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/DataImport/NSRelationshipDescription+MagicalDataImport.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSRelationshipDescription+MagicalDataImport.h 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 9/4/11. 6 | // Copyright 2011 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSRelationshipDescription (MagicalRecord_DataImport) 12 | 13 | - (NSString *) MR_primaryKey; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/DataImport/NSRelationshipDescription+MagicalDataImport.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSRelationshipDescription+MagicalDataImport.m 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 9/4/11. 6 | // Copyright 2011 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "NSRelationshipDescription+MagicalDataImport.h" 10 | #import "NSManagedObject+MagicalDataImport.h" 11 | #import "MagicalImportFunctions.h" 12 | #import "MagicalRecord.h" 13 | 14 | @implementation NSRelationshipDescription (MagicalRecord_DataImport) 15 | 16 | - (NSString *) MR_primaryKey; 17 | { 18 | NSString *primaryKeyName = [[self userInfo] valueForKey:kMagicalRecordImportRelationshipLinkedByKey] ?: 19 | primaryKeyNameFromString([[self destinationEntity] name]); 20 | 21 | return primaryKeyName; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/DataImport/NSString+MagicalDataImport.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+MagicalRecord_MagicalDataImport.h 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 12/10/11. 6 | // Copyright (c) 2011 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (MagicalRecord_DataImport) 12 | 13 | - (NSString *) MR_capitalizedFirstCharacterString; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/DataImport/NSString+MagicalDataImport.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+MagicalRecord_MagicalDataImport.m 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 12/10/11. 6 | // Copyright (c) 2011 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "NSString+MagicalDataImport.h" 10 | 11 | 12 | @implementation NSString (MagicalRecord_DataImport) 13 | 14 | - (NSString *) MR_capitalizedFirstCharacterString; 15 | { 16 | if ([self length] > 0) 17 | { 18 | NSString *firstChar = [[self substringToIndex:1] capitalizedString]; 19 | return [firstChar stringByAppendingString:[self substringFromIndex:1]]; 20 | } 21 | return self; 22 | } 23 | 24 | - (id) MR_relatedValueForRelationship:(NSRelationshipDescription *)relationshipInfo 25 | { 26 | return self; 27 | } 28 | 29 | - (NSString *) MR_lookupKeyForAttribute:(NSAttributeDescription *)attributeInfo 30 | { 31 | return nil; 32 | } 33 | 34 | @end 35 | 36 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSManagedObject/NSManagedObject+MagicalAggregation.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSManagedObject+MagicalAggregation.h 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/7/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSManagedObject (MagicalAggregation) 12 | 13 | + (NSNumber *) MR_numberOfEntities; 14 | + (NSNumber *) MR_numberOfEntitiesWithContext:(NSManagedObjectContext *)context; 15 | + (NSNumber *) MR_numberOfEntitiesWithPredicate:(NSPredicate *)searchTerm; 16 | + (NSNumber *) MR_numberOfEntitiesWithPredicate:(NSPredicate *)searchTerm inContext:(NSManagedObjectContext *)context; 17 | 18 | + (NSUInteger) MR_countOfEntities; 19 | + (NSUInteger) MR_countOfEntitiesWithContext:(NSManagedObjectContext *)context; 20 | + (NSUInteger) MR_countOfEntitiesWithPredicate:(NSPredicate *)searchFilter; 21 | + (NSUInteger) MR_countOfEntitiesWithPredicate:(NSPredicate *)searchFilter inContext:(NSManagedObjectContext *)context; 22 | 23 | + (BOOL) MR_hasAtLeastOneEntity; 24 | + (BOOL) MR_hasAtLeastOneEntityInContext:(NSManagedObjectContext *)context; 25 | 26 | + (NSNumber *)MR_aggregateOperation:(NSString *)function onAttribute:(NSString *)attributeName withPredicate:(NSPredicate *)predicate inContext:(NSManagedObjectContext *)context; 27 | + (NSNumber *)MR_aggregateOperation:(NSString *)function onAttribute:(NSString *)attributeName withPredicate:(NSPredicate *)predicate; 28 | 29 | - (id) MR_objectWithMinValueFor:(NSString *)property; 30 | - (id) MR_objectWithMinValueFor:(NSString *)property inContext:(NSManagedObjectContext *)context; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSManagedObject/NSManagedObject+MagicalAggregation.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSManagedObject+MagicalAggregation.m 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/7/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "NSManagedObject+MagicalAggregation.h" 10 | #import "NSManagedObjectContext+MagicalRecord.h" 11 | #import "NSManagedObjectContext+MagicalThreading.h" 12 | #import "NSManagedObject+MagicalRequests.h" 13 | #import "NSManagedObject+MagicalRecord.h" 14 | #import "NSManagedObject+MagicalFinders.h" 15 | #import "MagicalRecord+ErrorHandling.h" 16 | 17 | @implementation NSManagedObject (MagicalAggregation) 18 | 19 | #pragma mark - 20 | #pragma mark Number of Entities 21 | 22 | + (NSNumber *) MR_numberOfEntitiesWithContext:(NSManagedObjectContext *)context 23 | { 24 | return [NSNumber numberWithUnsignedInteger:[self MR_countOfEntitiesWithContext:context]]; 25 | } 26 | 27 | + (NSNumber *) MR_numberOfEntities 28 | { 29 | return [self MR_numberOfEntitiesWithContext:[NSManagedObjectContext MR_contextForCurrentThread]]; 30 | } 31 | 32 | + (NSNumber *) MR_numberOfEntitiesWithPredicate:(NSPredicate *)searchTerm inContext:(NSManagedObjectContext *)context 33 | { 34 | 35 | return [NSNumber numberWithUnsignedInteger:[self MR_countOfEntitiesWithPredicate:searchTerm inContext:context]]; 36 | } 37 | 38 | + (NSNumber *) MR_numberOfEntitiesWithPredicate:(NSPredicate *)searchTerm; 39 | { 40 | return [self MR_numberOfEntitiesWithPredicate:searchTerm 41 | inContext:[NSManagedObjectContext MR_contextForCurrentThread]]; 42 | } 43 | 44 | + (NSUInteger) MR_countOfEntities; 45 | { 46 | return [self MR_countOfEntitiesWithContext:[NSManagedObjectContext MR_contextForCurrentThread]]; 47 | } 48 | 49 | + (NSUInteger) MR_countOfEntitiesWithContext:(NSManagedObjectContext *)context; 50 | { 51 | NSError *error = nil; 52 | NSUInteger count = [context countForFetchRequest:[self MR_createFetchRequestInContext:context] error:&error]; 53 | [MagicalRecord handleErrors:error]; 54 | 55 | return count; 56 | } 57 | 58 | + (NSUInteger) MR_countOfEntitiesWithPredicate:(NSPredicate *)searchFilter; 59 | { 60 | return [self MR_countOfEntitiesWithPredicate:searchFilter inContext:[NSManagedObjectContext MR_defaultContext]]; 61 | } 62 | 63 | + (NSUInteger) MR_countOfEntitiesWithPredicate:(NSPredicate *)searchFilter inContext:(NSManagedObjectContext *)context; 64 | { 65 | NSError *error = nil; 66 | NSFetchRequest *request = [self MR_createFetchRequestInContext:context]; 67 | [request setPredicate:searchFilter]; 68 | 69 | NSUInteger count = [context countForFetchRequest:request error:&error]; 70 | [MagicalRecord handleErrors:error]; 71 | 72 | return count; 73 | } 74 | 75 | + (BOOL) MR_hasAtLeastOneEntity 76 | { 77 | return [self MR_hasAtLeastOneEntityInContext:[NSManagedObjectContext MR_contextForCurrentThread]]; 78 | } 79 | 80 | + (BOOL) MR_hasAtLeastOneEntityInContext:(NSManagedObjectContext *)context 81 | { 82 | return [[self MR_numberOfEntitiesWithContext:context] intValue] > 0; 83 | } 84 | 85 | - (NSNumber *) MR_maxValueFor:(NSString *)property 86 | { 87 | NSManagedObject *obj = [[self class] MR_findFirstByAttribute:property 88 | withValue:[NSString stringWithFormat:@"max(%@)", property]]; 89 | 90 | return [obj valueForKey:property]; 91 | } 92 | 93 | - (id) MR_objectWithMinValueFor:(NSString *)property inContext:(NSManagedObjectContext *)context 94 | { 95 | NSFetchRequest *request = [[self class] MR_createFetchRequestInContext:context]; 96 | 97 | NSPredicate *searchFor = [NSPredicate predicateWithFormat:@"SELF = %@ AND %K = min(%@)", self, property, property]; 98 | [request setPredicate:searchFor]; 99 | 100 | return [[self class] MR_executeFetchRequestAndReturnFirstObject:request inContext:context]; 101 | } 102 | 103 | - (id) MR_objectWithMinValueFor:(NSString *)property 104 | { 105 | return [self MR_objectWithMinValueFor:property inContext:[self managedObjectContext]]; 106 | } 107 | 108 | + (NSNumber *) MR_aggregateOperation:(NSString *)function onAttribute:(NSString *)attributeName withPredicate:(NSPredicate *)predicate inContext:(NSManagedObjectContext *)context 109 | { 110 | NSExpression *ex = [NSExpression expressionForFunction:function 111 | arguments:[NSArray arrayWithObject:[NSExpression expressionForKeyPath:attributeName]]]; 112 | 113 | NSExpressionDescription *ed = [[NSExpressionDescription alloc] init]; 114 | [ed setName:@"result"]; 115 | [ed setExpression:ex]; 116 | 117 | // determine the type of attribute, required to set the expression return type 118 | NSAttributeDescription *attributeDescription = [[[self MR_entityDescription] attributesByName] objectForKey:attributeName]; 119 | [ed setExpressionResultType:[attributeDescription attributeType]]; 120 | NSArray *properties = [NSArray arrayWithObject:ed]; 121 | 122 | NSFetchRequest *request = [self MR_requestAllWithPredicate:predicate inContext:context]; 123 | [request setPropertiesToFetch:properties]; 124 | [request setResultType:NSDictionaryResultType]; 125 | 126 | NSDictionary *resultsDictionary = [self MR_executeFetchRequestAndReturnFirstObject:request inContext:context]; 127 | NSNumber *resultValue = [resultsDictionary objectForKey:@"result"]; 128 | 129 | return resultValue; 130 | } 131 | 132 | + (NSNumber *) MR_aggregateOperation:(NSString *)function onAttribute:(NSString *)attributeName withPredicate:(NSPredicate *)predicate 133 | { 134 | return [self MR_aggregateOperation:function 135 | onAttribute:attributeName 136 | withPredicate:predicate 137 | inContext:[NSManagedObjectContext MR_defaultContext]]; 138 | } 139 | 140 | @end 141 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSManagedObject/NSManagedObject+MagicalDataImport.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSManagedObject+JSONHelpers.h 3 | // 4 | // Created by Saul Mora on 6/28/11. 5 | // Copyright 2011 Magical Panda Software LLC. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | extern NSString * const kMagicalRecordImportCustomDateFormatKey; 11 | extern NSString * const kMagicalRecordImportDefaultDateFormatString; 12 | extern NSString * const kMagicalRecordImportAttributeKeyMapKey; 13 | extern NSString * const kMagicalRecordImportAttributeValueClassNameKey; 14 | 15 | extern NSString * const kMagicalRecordImportRelationshipMapKey; 16 | extern NSString * const kMagicalRecordImportRelationshipLinkedByKey; 17 | extern NSString * const kMagicalRecordImportRelationshipTypeKey; 18 | 19 | @interface NSManagedObject (MagicalRecord_DataImport) 20 | 21 | - (BOOL) MR_importValuesForKeysWithObject:(id)objectData; 22 | 23 | + (id) MR_importFromObject:(id)data; 24 | + (id) MR_importFromObject:(id)data inContext:(NSManagedObjectContext *)context; 25 | 26 | + (NSArray *) MR_importFromArray:(NSArray *)listOfObjectData; 27 | + (NSArray *) MR_importFromArray:(NSArray *)listOfObjectData inContext:(NSManagedObjectContext *)context; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSManagedObject/NSManagedObject+MagicalFinders.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSManagedObject+MagicalFinders.h 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/7/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSManagedObject (MagicalFinders) 12 | 13 | + (NSArray *) MR_findAll; 14 | + (NSArray *) MR_findAllInContext:(NSManagedObjectContext *)context; 15 | + (NSArray *) MR_findAllSortedBy:(NSString *)sortTerm ascending:(BOOL)ascending; 16 | + (NSArray *) MR_findAllSortedBy:(NSString *)sortTerm ascending:(BOOL)ascending inContext:(NSManagedObjectContext *)context; 17 | + (NSArray *) MR_findAllSortedBy:(NSString *)sortTerm ascending:(BOOL)ascending withPredicate:(NSPredicate *)searchTerm; 18 | + (NSArray *) MR_findAllSortedBy:(NSString *)sortTerm ascending:(BOOL)ascending withPredicate:(NSPredicate *)searchTerm inContext:(NSManagedObjectContext *)context; 19 | 20 | + (NSArray *) MR_findAllWithPredicate:(NSPredicate *)searchTerm; 21 | + (NSArray *) MR_findAllWithPredicate:(NSPredicate *)searchTerm inContext:(NSManagedObjectContext *)context; 22 | 23 | + (id) MR_findFirst; 24 | + (id) MR_findFirstInContext:(NSManagedObjectContext *)context; 25 | + (id) MR_findFirstWithPredicate:(NSPredicate *)searchTerm; 26 | + (id) MR_findFirstWithPredicate:(NSPredicate *)searchTerm inContext:(NSManagedObjectContext *)context; 27 | + (id) MR_findFirstWithPredicate:(NSPredicate *)searchterm sortedBy:(NSString *)property ascending:(BOOL)ascending; 28 | + (id) MR_findFirstWithPredicate:(NSPredicate *)searchterm sortedBy:(NSString *)property ascending:(BOOL)ascending inContext:(NSManagedObjectContext *)context; 29 | + (id) MR_findFirstWithPredicate:(NSPredicate *)searchTerm andRetrieveAttributes:(NSArray *)attributes; 30 | + (id) MR_findFirstWithPredicate:(NSPredicate *)searchTerm andRetrieveAttributes:(NSArray *)attributes inContext:(NSManagedObjectContext *)context; 31 | + (id) MR_findFirstWithPredicate:(NSPredicate *)searchTerm sortedBy:(NSString *)sortBy ascending:(BOOL)ascending andRetrieveAttributes:(id)attributes, ...; 32 | + (id) MR_findFirstWithPredicate:(NSPredicate *)searchTerm sortedBy:(NSString *)sortBy ascending:(BOOL)ascending inContext:(NSManagedObjectContext *)context andRetrieveAttributes:(id)attributes, ...; 33 | + (id) MR_findFirstByAttribute:(NSString *)attribute withValue:(id)searchValue; 34 | + (id) MR_findFirstByAttribute:(NSString *)attribute withValue:(id)searchValue inContext:(NSManagedObjectContext *)context; 35 | + (id) MR_findFirstOrderedByAttribute:(NSString *)attribute ascending:(BOOL)ascending; 36 | + (id) MR_findFirstOrderedByAttribute:(NSString *)attribute ascending:(BOOL)ascending inContext:(NSManagedObjectContext *)context; 37 | 38 | + (NSArray *) MR_findByAttribute:(NSString *)attribute withValue:(id)searchValue; 39 | + (NSArray *) MR_findByAttribute:(NSString *)attribute withValue:(id)searchValue inContext:(NSManagedObjectContext *)context; 40 | + (NSArray *) MR_findByAttribute:(NSString *)attribute withValue:(id)searchValue andOrderBy:(NSString *)sortTerm ascending:(BOOL)ascending; 41 | + (NSArray *) MR_findByAttribute:(NSString *)attribute withValue:(id)searchValue andOrderBy:(NSString *)sortTerm ascending:(BOOL)ascending inContext:(NSManagedObjectContext *)context; 42 | 43 | #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR 44 | 45 | + (NSFetchedResultsController *) MR_fetchAllWithDelegate:(id)delegate; 46 | + (NSFetchedResultsController *) MR_fetchAllWithDelegate:(id)delegate inContext:(NSManagedObjectContext *)context; 47 | 48 | + (NSFetchedResultsController *) MR_fetchAllSortedBy:(NSString *)sortTerm ascending:(BOOL)ascending withPredicate:(NSPredicate *)searchTerm groupBy:(NSString *)groupingKeyPath delegate:(id)delegate; 49 | + (NSFetchedResultsController *) MR_fetchAllSortedBy:(NSString *)sortTerm ascending:(BOOL)ascending withPredicate:(NSPredicate *)searchTerm groupBy:(NSString *)groupingKeyPath delegate:(id)delegate inContext:(NSManagedObjectContext *)context; 50 | 51 | + (NSFetchedResultsController *) MR_fetchAllGroupedBy:(NSString *)group withPredicate:(NSPredicate *)searchTerm sortedBy:(NSString *)sortTerm ascending:(BOOL)ascending; 52 | + (NSFetchedResultsController *) MR_fetchAllGroupedBy:(NSString *)group withPredicate:(NSPredicate *)searchTerm sortedBy:(NSString *)sortTerm ascending:(BOOL)ascending inContext:(NSManagedObjectContext *)context; 53 | 54 | + (NSFetchedResultsController *) MR_fetchAllGroupedBy:(NSString *)group withPredicate:(NSPredicate *)searchTerm sortedBy:(NSString *)sortTerm ascending:(BOOL)ascending delegate:(id)delegate; 55 | + (NSFetchedResultsController *) MR_fetchAllGroupedBy:(NSString *)group withPredicate:(NSPredicate *)searchTerm sortedBy:(NSString *)sortTerm ascending:(BOOL)ascending delegate:(id)delegate inContext:(NSManagedObjectContext *)context; 56 | 57 | #endif 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSManagedObject/NSManagedObject+MagicalRecord.h: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Created by Saul Mora on 11/15/09. 4 | // Copyright 2010 Magical Panda Software, LLC All rights reserved. 5 | // 6 | 7 | #import 8 | #import "MagicalRecord.h" 9 | 10 | #define kMagicalRecordDefaultBatchSize 20 11 | 12 | @interface NSManagedObject (MagicalRecord) 13 | 14 | + (NSUInteger) MR_defaultBatchSize; 15 | + (void) MR_setDefaultBatchSize:(NSUInteger)newBatchSize; 16 | 17 | + (NSArray *) MR_executeFetchRequest:(NSFetchRequest *)request; 18 | + (NSArray *) MR_executeFetchRequest:(NSFetchRequest *)request inContext:(NSManagedObjectContext *)context; 19 | + (id) MR_executeFetchRequestAndReturnFirstObject:(NSFetchRequest *)request; 20 | + (id) MR_executeFetchRequestAndReturnFirstObject:(NSFetchRequest *)request inContext:(NSManagedObjectContext *)context; 21 | 22 | #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR 23 | 24 | + (void) MR_performFetch:(NSFetchedResultsController *)controller; 25 | 26 | #endif 27 | 28 | + (NSEntityDescription *) MR_entityDescription; 29 | + (NSEntityDescription *) MR_entityDescriptionInContext:(NSManagedObjectContext *)context; 30 | + (NSArray *) MR_propertiesNamed:(NSArray *)properties; 31 | 32 | + (id) MR_createEntity; 33 | + (id) MR_createInContext:(NSManagedObjectContext *)context; 34 | - (BOOL) MR_deleteEntity; 35 | - (BOOL) MR_deleteInContext:(NSManagedObjectContext *)context; 36 | 37 | + (BOOL) MR_deleteAllMatchingPredicate:(NSPredicate *)predicate; 38 | + (BOOL) MR_deleteAllMatchingPredicate:(NSPredicate *)predicate inContext:(NSManagedObjectContext *)context; 39 | 40 | + (BOOL) MR_truncateAll; 41 | + (BOOL) MR_truncateAllInContext:(NSManagedObjectContext *)context; 42 | 43 | + (NSArray *) MR_ascendingSortDescriptors:(NSArray *)attributesToSortBy; 44 | + (NSArray *) MR_descendingSortDescriptors:(NSArray *)attributesToSortBy; 45 | 46 | - (id) MR_inContext:(NSManagedObjectContext *)otherContext; 47 | - (id) MR_inThreadContext; 48 | 49 | @end 50 | 51 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSManagedObject/NSManagedObject+MagicalRecord.m: -------------------------------------------------------------------------------- 1 | 2 | // Created by Saul Mora on 11/15/09. 3 | // Copyright 2010 Magical Panda Software, LLC All rights reserved. 4 | // 5 | 6 | #import "CoreData+MagicalRecord.h" 7 | 8 | static NSUInteger defaultBatchSize = kMagicalRecordDefaultBatchSize; 9 | 10 | 11 | @implementation NSManagedObject (MagicalRecord) 12 | 13 | + (void) MR_setDefaultBatchSize:(NSUInteger)newBatchSize 14 | { 15 | @synchronized(self) 16 | { 17 | defaultBatchSize = newBatchSize; 18 | } 19 | } 20 | 21 | + (NSUInteger) MR_defaultBatchSize 22 | { 23 | return defaultBatchSize; 24 | } 25 | 26 | + (NSArray *) MR_executeFetchRequest:(NSFetchRequest *)request inContext:(NSManagedObjectContext *)context 27 | { 28 | __block NSArray *results = nil; 29 | [context performBlockAndWait:^{ 30 | 31 | NSError *error = nil; 32 | 33 | results = [context executeFetchRequest:request error:&error]; 34 | 35 | if (results == nil) 36 | { 37 | [MagicalRecord handleErrors:error]; 38 | } 39 | 40 | }]; 41 | return results; 42 | } 43 | 44 | + (NSArray *) MR_executeFetchRequest:(NSFetchRequest *)request 45 | { 46 | return [self MR_executeFetchRequest:request inContext:[NSManagedObjectContext MR_contextForCurrentThread]]; 47 | } 48 | 49 | + (id) MR_executeFetchRequestAndReturnFirstObject:(NSFetchRequest *)request inContext:(NSManagedObjectContext *)context 50 | { 51 | [request setFetchLimit:1]; 52 | 53 | NSArray *results = [self MR_executeFetchRequest:request inContext:context]; 54 | if ([results count] == 0) 55 | { 56 | return nil; 57 | } 58 | return [results objectAtIndex:0]; 59 | } 60 | 61 | + (id) MR_executeFetchRequestAndReturnFirstObject:(NSFetchRequest *)request 62 | { 63 | return [self MR_executeFetchRequestAndReturnFirstObject:request inContext:[NSManagedObjectContext MR_contextForCurrentThread]]; 64 | } 65 | 66 | #if TARGET_OS_IPHONE 67 | 68 | + (void) MR_performFetch:(NSFetchedResultsController *)controller 69 | { 70 | NSError *error = nil; 71 | if (![controller performFetch:&error]) 72 | { 73 | [MagicalRecord handleErrors:error]; 74 | } 75 | } 76 | 77 | #endif 78 | 79 | + (NSString *) MR_entityName 80 | { 81 | return NSStringFromClass(self); 82 | } 83 | 84 | + (NSEntityDescription *) MR_entityDescriptionInContext:(NSManagedObjectContext *)context 85 | { 86 | if ([self respondsToSelector:@selector(entityInManagedObjectContext:)]) 87 | { 88 | NSEntityDescription *entity = [self performSelector:@selector(entityInManagedObjectContext:) withObject:context]; 89 | return entity; 90 | } 91 | else 92 | { 93 | NSString *entityName = [self MR_entityName]; 94 | return [NSEntityDescription entityForName:entityName inManagedObjectContext:context]; 95 | } 96 | } 97 | 98 | + (NSEntityDescription *) MR_entityDescription 99 | { 100 | return [self MR_entityDescriptionInContext:[NSManagedObjectContext MR_contextForCurrentThread]]; 101 | } 102 | 103 | + (NSArray *) MR_propertiesNamed:(NSArray *)properties 104 | { 105 | NSEntityDescription *description = [self MR_entityDescription]; 106 | NSMutableArray *propertiesWanted = [NSMutableArray array]; 107 | 108 | if (properties) 109 | { 110 | NSDictionary *propDict = [description propertiesByName]; 111 | 112 | for (NSString *propertyName in properties) 113 | { 114 | NSPropertyDescription *property = [propDict objectForKey:propertyName]; 115 | if (property) 116 | { 117 | [propertiesWanted addObject:property]; 118 | } 119 | else 120 | { 121 | MRLog(@"Property '%@' not found in %lx properties for %@", propertyName, (unsigned long)[propDict count], NSStringFromClass(self)); 122 | } 123 | } 124 | } 125 | return propertiesWanted; 126 | } 127 | 128 | + (NSArray *) MR_sortAscending:(BOOL)ascending attributes:(NSArray *)attributesToSortBy 129 | { 130 | NSMutableArray *attributes = [NSMutableArray array]; 131 | 132 | for (NSString *attributeName in attributesToSortBy) 133 | { 134 | NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:attributeName ascending:ascending]; 135 | [attributes addObject:sortDescriptor]; 136 | } 137 | 138 | return attributes; 139 | } 140 | 141 | + (NSArray *) MR_ascendingSortDescriptors:(NSArray *)attributesToSortBy 142 | { 143 | return [self MR_sortAscending:YES attributes:attributesToSortBy]; 144 | } 145 | 146 | + (NSArray *) MR_descendingSortDescriptors:(NSArray *)attributesToSortBy 147 | { 148 | return [self MR_sortAscending:NO attributes:attributesToSortBy]; 149 | } 150 | 151 | #pragma mark - 152 | 153 | + (id) MR_createInContext:(NSManagedObjectContext *)context 154 | { 155 | if ([self respondsToSelector:@selector(insertInManagedObjectContext:)]) 156 | { 157 | id entity = [self performSelector:@selector(insertInManagedObjectContext:) withObject:context]; 158 | return entity; 159 | } 160 | else 161 | { 162 | return [NSEntityDescription insertNewObjectForEntityForName:[self MR_entityName] inManagedObjectContext:context]; 163 | } 164 | } 165 | 166 | + (id) MR_createEntity 167 | { 168 | NSManagedObject *newEntity = [self MR_createInContext:[NSManagedObjectContext MR_contextForCurrentThread]]; 169 | 170 | return newEntity; 171 | } 172 | 173 | - (BOOL) MR_deleteInContext:(NSManagedObjectContext *)context 174 | { 175 | [context deleteObject:self]; 176 | return YES; 177 | } 178 | 179 | - (BOOL) MR_deleteEntity 180 | { 181 | [self MR_deleteInContext:[self managedObjectContext]]; 182 | return YES; 183 | } 184 | 185 | + (BOOL) MR_deleteAllMatchingPredicate:(NSPredicate *)predicate inContext:(NSManagedObjectContext *)context 186 | { 187 | NSFetchRequest *request = [self MR_requestAllWithPredicate:predicate inContext:context]; 188 | [request setReturnsObjectsAsFaults:YES]; 189 | [request setIncludesPropertyValues:NO]; 190 | 191 | NSArray *objectsToTruncate = [self MR_executeFetchRequest:request inContext:context]; 192 | 193 | for (id objectToTruncate in objectsToTruncate) 194 | { 195 | [objectToTruncate MR_deleteInContext:context]; 196 | } 197 | 198 | return YES; 199 | } 200 | 201 | + (BOOL) MR_deleteAllMatchingPredicate:(NSPredicate *)predicate 202 | { 203 | return [self MR_deleteAllMatchingPredicate:predicate inContext:[NSManagedObjectContext MR_contextForCurrentThread]]; 204 | } 205 | 206 | + (BOOL) MR_truncateAllInContext:(NSManagedObjectContext *)context 207 | { 208 | NSArray *allEntities = [self MR_findAllInContext:context]; 209 | for (NSManagedObject *obj in allEntities) 210 | { 211 | [obj MR_deleteInContext:context]; 212 | } 213 | return YES; 214 | } 215 | 216 | + (BOOL) MR_truncateAll 217 | { 218 | [self MR_truncateAllInContext:[NSManagedObjectContext MR_contextForCurrentThread]]; 219 | return YES; 220 | } 221 | 222 | - (id) MR_inContext:(NSManagedObjectContext *)otherContext 223 | { 224 | NSError *error = nil; 225 | NSManagedObject *inContext = [otherContext existingObjectWithID:[self objectID] error:&error]; 226 | [MagicalRecord handleErrors:error]; 227 | 228 | return inContext; 229 | } 230 | 231 | - (id) MR_inThreadContext 232 | { 233 | NSManagedObject *weakSelf = self; 234 | return [weakSelf MR_inContext:[NSManagedObjectContext MR_contextForCurrentThread]]; 235 | } 236 | 237 | @end 238 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSManagedObject/NSManagedObject+MagicalRequests.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSManagedObject+MagicalRequests.h 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/7/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSManagedObject (MagicalRequests) 12 | 13 | + (NSFetchRequest *) MR_createFetchRequest; 14 | + (NSFetchRequest *) MR_createFetchRequestInContext:(NSManagedObjectContext *)context; 15 | 16 | + (NSFetchRequest *) MR_requestAll; 17 | + (NSFetchRequest *) MR_requestAllInContext:(NSManagedObjectContext *)context; 18 | + (NSFetchRequest *) MR_requestAllWithPredicate:(NSPredicate *)searchTerm; 19 | + (NSFetchRequest *) MR_requestAllWithPredicate:(NSPredicate *)searchTerm inContext:(NSManagedObjectContext *)context; 20 | + (NSFetchRequest *) MR_requestAllWhere:(NSString *)property isEqualTo:(id)value; 21 | + (NSFetchRequest *) MR_requestAllWhere:(NSString *)property isEqualTo:(id)value inContext:(NSManagedObjectContext *)context; 22 | + (NSFetchRequest *) MR_requestFirstWithPredicate:(NSPredicate *)searchTerm; 23 | + (NSFetchRequest *) MR_requestFirstWithPredicate:(NSPredicate *)searchTerm inContext:(NSManagedObjectContext *)context; 24 | + (NSFetchRequest *) MR_requestFirstByAttribute:(NSString *)attribute withValue:(id)searchValue; 25 | + (NSFetchRequest *) MR_requestFirstByAttribute:(NSString *)attribute withValue:(id)searchValue inContext:(NSManagedObjectContext *)context; 26 | + (NSFetchRequest *) MR_requestAllSortedBy:(NSString *)sortTerm ascending:(BOOL)ascending; 27 | + (NSFetchRequest *) MR_requestAllSortedBy:(NSString *)sortTerm ascending:(BOOL)ascending inContext:(NSManagedObjectContext *)context; 28 | + (NSFetchRequest *) MR_requestAllSortedBy:(NSString *)sortTerm ascending:(BOOL)ascending withPredicate:(NSPredicate *)searchTerm; 29 | + (NSFetchRequest *) MR_requestAllSortedBy:(NSString *)sortTerm ascending:(BOOL)ascending withPredicate:(NSPredicate *)searchTerm inContext:(NSManagedObjectContext *)context; 30 | 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSManagedObject/NSManagedObject+MagicalRequests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSManagedObject+MagicalRequests.m 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/7/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "NSManagedObject+MagicalRequests.h" 10 | #import "NSManagedObject+MagicalRecord.h" 11 | #import "NSManagedObjectContext+MagicalThreading.h" 12 | 13 | @implementation NSManagedObject (MagicalRequests) 14 | 15 | 16 | + (NSFetchRequest *)MR_createFetchRequestInContext:(NSManagedObjectContext *)context 17 | { 18 | NSFetchRequest *request = [[NSFetchRequest alloc] init]; 19 | [request setEntity:[self MR_entityDescriptionInContext:context]]; 20 | 21 | return request; 22 | } 23 | 24 | + (NSFetchRequest *) MR_createFetchRequest 25 | { 26 | return [self MR_createFetchRequestInContext:[NSManagedObjectContext MR_contextForCurrentThread]]; 27 | } 28 | 29 | 30 | + (NSFetchRequest *) MR_requestAll 31 | { 32 | return [self MR_createFetchRequestInContext:[NSManagedObjectContext MR_contextForCurrentThread]]; 33 | } 34 | 35 | + (NSFetchRequest *) MR_requestAllInContext:(NSManagedObjectContext *)context 36 | { 37 | return [self MR_createFetchRequestInContext:context]; 38 | } 39 | 40 | + (NSFetchRequest *) MR_requestAllWithPredicate:(NSPredicate *)searchTerm; 41 | { 42 | return [self MR_requestAllWithPredicate:searchTerm inContext:[NSManagedObjectContext MR_contextForCurrentThread]]; 43 | } 44 | 45 | + (NSFetchRequest *) MR_requestAllWithPredicate:(NSPredicate *)searchTerm inContext:(NSManagedObjectContext *)context; 46 | { 47 | NSFetchRequest *request = [self MR_createFetchRequestInContext:context]; 48 | [request setPredicate:searchTerm]; 49 | 50 | return request; 51 | } 52 | 53 | + (NSFetchRequest *) MR_requestAllWhere:(NSString *)property isEqualTo:(id)value 54 | { 55 | return [self MR_requestAllWhere:property isEqualTo:value inContext:[NSManagedObjectContext MR_contextForCurrentThread]]; 56 | } 57 | 58 | + (NSFetchRequest *) MR_requestAllWhere:(NSString *)property isEqualTo:(id)value inContext:(NSManagedObjectContext *)context 59 | { 60 | NSFetchRequest *request = [self MR_createFetchRequestInContext:context]; 61 | [request setPredicate:[NSPredicate predicateWithFormat:@"%K = %@", property, value]]; 62 | 63 | return request; 64 | } 65 | 66 | + (NSFetchRequest *) MR_requestFirstWithPredicate:(NSPredicate *)searchTerm 67 | { 68 | return [self MR_requestFirstWithPredicate:searchTerm inContext:[NSManagedObjectContext MR_contextForCurrentThread]]; 69 | } 70 | 71 | + (NSFetchRequest *) MR_requestFirstWithPredicate:(NSPredicate *)searchTerm inContext:(NSManagedObjectContext *)context 72 | { 73 | NSFetchRequest *request = [self MR_createFetchRequestInContext:context]; 74 | [request setPredicate:searchTerm]; 75 | [request setFetchLimit:1]; 76 | 77 | return request; 78 | } 79 | 80 | + (NSFetchRequest *) MR_requestFirstByAttribute:(NSString *)attribute withValue:(id)searchValue; 81 | { 82 | return [self MR_requestFirstByAttribute:attribute withValue:searchValue inContext:[NSManagedObjectContext MR_contextForCurrentThread]]; 83 | } 84 | 85 | + (NSFetchRequest *) MR_requestFirstByAttribute:(NSString *)attribute withValue:(id)searchValue inContext:(NSManagedObjectContext *)context; 86 | { 87 | NSFetchRequest *request = [self MR_requestAllWhere:attribute isEqualTo:searchValue inContext:context]; 88 | [request setFetchLimit:1]; 89 | 90 | return request; 91 | } 92 | 93 | + (NSFetchRequest *) MR_requestAllSortedBy:(NSString *)sortTerm ascending:(BOOL)ascending inContext:(NSManagedObjectContext *)context 94 | { 95 | return [self MR_requestAllSortedBy:sortTerm 96 | ascending:ascending 97 | withPredicate:nil 98 | inContext:context]; 99 | } 100 | 101 | + (NSFetchRequest *) MR_requestAllSortedBy:(NSString *)sortTerm ascending:(BOOL)ascending 102 | { 103 | return [self MR_requestAllSortedBy:sortTerm 104 | ascending:ascending 105 | inContext:[NSManagedObjectContext MR_contextForCurrentThread]]; 106 | } 107 | 108 | + (NSFetchRequest *) MR_requestAllSortedBy:(NSString *)sortTerm ascending:(BOOL)ascending withPredicate:(NSPredicate *)searchTerm inContext:(NSManagedObjectContext *)context 109 | { 110 | NSFetchRequest *request = [self MR_requestAllInContext:context]; 111 | if (searchTerm) 112 | { 113 | [request setPredicate:searchTerm]; 114 | } 115 | [request setFetchBatchSize:[self MR_defaultBatchSize]]; 116 | 117 | NSMutableArray* sortDescriptors = [[NSMutableArray alloc] init]; 118 | NSArray* sortKeys = [sortTerm componentsSeparatedByString:@","]; 119 | for (NSString* sortKey in sortKeys) 120 | { 121 | NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:ascending]; 122 | [sortDescriptors addObject:sortDescriptor]; 123 | } 124 | 125 | [request setSortDescriptors:sortDescriptors]; 126 | 127 | return request; 128 | } 129 | 130 | + (NSFetchRequest *) MR_requestAllSortedBy:(NSString *)sortTerm ascending:(BOOL)ascending withPredicate:(NSPredicate *)searchTerm; 131 | { 132 | NSFetchRequest *request = [self MR_requestAllSortedBy:sortTerm 133 | ascending:ascending 134 | withPredicate:searchTerm 135 | inContext:[NSManagedObjectContext MR_contextForCurrentThread]]; 136 | return request; 137 | } 138 | 139 | 140 | @end 141 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSManagedObjectContext/NSManagedObjectContext+MagicalObserving.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSManagedObjectContext+MagicalObserving.h 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/9/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSManagedObjectContext (MagicalObserving) 12 | 13 | - (void) MR_observeContext:(NSManagedObjectContext *)otherContext; 14 | - (void) MR_stopObservingContext:(NSManagedObjectContext *)otherContext; 15 | - (void) MR_observeContextOnMainThread:(NSManagedObjectContext *)otherContext; 16 | 17 | - (void) MR_observeiCloudChangesInCoordinator:(NSPersistentStoreCoordinator *)coordinator; 18 | - (void) MR_stopObservingiCloudChangesInCoordinator:(NSPersistentStoreCoordinator *)coordinator; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSManagedObjectContext/NSManagedObjectContext+MagicalObserving.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSManagedObjectContext+MagicalObserving.m 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/9/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "NSManagedObjectContext+MagicalObserving.h" 10 | #import "NSManagedObjectContext+MagicalRecord.h" 11 | #import "MagicalRecord.h" 12 | #import "MagicalRecord+iCloud.h" 13 | 14 | NSString * const kMagicalRecordDidMergeChangesFromiCloudNotification = @"kMagicalRecordDidMergeChangesFromiCloudNotification"; 15 | 16 | 17 | @implementation NSManagedObjectContext (MagicalObserving) 18 | 19 | #pragma mark - Context Observation Helpers 20 | 21 | - (void) MR_observeContext:(NSManagedObjectContext *)otherContext 22 | { 23 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 24 | [notificationCenter addObserver:self 25 | selector:@selector(MR_mergeChangesFromNotification:) 26 | name:NSManagedObjectContextDidSaveNotification 27 | object:otherContext]; 28 | } 29 | 30 | - (void) MR_observeContextOnMainThread:(NSManagedObjectContext *)otherContext 31 | { 32 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 33 | [notificationCenter addObserver:self 34 | selector:@selector(MR_mergeChangesOnMainThread:) 35 | name:NSManagedObjectContextDidSaveNotification 36 | object:otherContext]; 37 | } 38 | 39 | - (void) MR_stopObservingContext:(NSManagedObjectContext *)otherContext 40 | { 41 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 42 | 43 | [notificationCenter removeObserver:self 44 | name:NSManagedObjectContextDidSaveNotification 45 | object:otherContext]; 46 | } 47 | 48 | #pragma mark - Context iCloud Merge Helpers 49 | 50 | - (void) MR_mergeChangesFromiCloud:(NSNotification *)notification; 51 | { 52 | [self performBlock:^{ 53 | 54 | MRLog(@"Merging changes From iCloud %@context%@", 55 | self == [NSManagedObjectContext MR_defaultContext] ? @"*** DEFAULT *** " : @"", 56 | ([NSThread isMainThread] ? @" *** on Main Thread ***" : @"")); 57 | 58 | [self mergeChangesFromContextDidSaveNotification:notification]; 59 | 60 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 61 | 62 | [notificationCenter postNotificationName:kMagicalRecordDidMergeChangesFromiCloudNotification 63 | object:self 64 | userInfo:[notification userInfo]]; 65 | }]; 66 | } 67 | 68 | - (void) MR_mergeChangesFromNotification:(NSNotification *)notification; 69 | { 70 | MRLog(@"Merging changes to %@context%@", 71 | self == [NSManagedObjectContext MR_defaultContext] ? @"*** DEFAULT *** " : @"", 72 | ([NSThread isMainThread] ? @" *** on Main Thread ***" : @"")); 73 | 74 | [self mergeChangesFromContextDidSaveNotification:notification]; 75 | } 76 | 77 | - (void) MR_mergeChangesOnMainThread:(NSNotification *)notification; 78 | { 79 | if ([NSThread isMainThread]) 80 | { 81 | [self MR_mergeChangesFromNotification:notification]; 82 | } 83 | else 84 | { 85 | [self performSelectorOnMainThread:@selector(MR_mergeChangesFromNotification:) withObject:notification waitUntilDone:YES]; 86 | } 87 | } 88 | 89 | - (void) MR_observeiCloudChangesInCoordinator:(NSPersistentStoreCoordinator *)coordinator; 90 | { 91 | if (![MagicalRecord isICloudEnabled]) return; 92 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 93 | [notificationCenter addObserver:self 94 | selector:@selector(MR_mergeChangesFromiCloud:) 95 | name:NSPersistentStoreDidImportUbiquitousContentChangesNotification 96 | object:coordinator]; 97 | 98 | } 99 | 100 | - (void) MR_stopObservingiCloudChangesInCoordinator:(NSPersistentStoreCoordinator *)coordinator; 101 | { 102 | if (![MagicalRecord isICloudEnabled]) return; 103 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 104 | [notificationCenter removeObserver:self 105 | name:NSPersistentStoreDidImportUbiquitousContentChangesNotification 106 | object:coordinator]; 107 | } 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSManagedObjectContext/NSManagedObjectContext+MagicalRecord.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSManagedObjectContext+MagicalRecord.h 3 | // 4 | // Created by Saul Mora on 11/23/09. 5 | // Copyright 2010 Magical Panda Software, LLC All rights reserved. 6 | // 7 | 8 | #import "MagicalRecord.h" 9 | 10 | extern NSString * const kMagicalRecordDidMergeChangesFromiCloudNotification; 11 | 12 | @interface NSManagedObjectContext (MagicalRecord) 13 | 14 | + (void) MR_initializeDefaultContextWithCoordinator:(NSPersistentStoreCoordinator *)coordinator; 15 | 16 | + (NSManagedObjectContext *) MR_context NS_RETURNS_RETAINED; 17 | + (NSManagedObjectContext *) MR_contextWithParent:(NSManagedObjectContext *)parentContext NS_RETURNS_RETAINED; 18 | + (NSManagedObjectContext *) MR_newMainQueueContext NS_RETURNS_RETAINED; 19 | + (NSManagedObjectContext *) MR_contextWithStoreCoordinator:(NSPersistentStoreCoordinator *)coordinator NS_RETURNS_RETAINED; 20 | 21 | + (void) MR_resetDefaultContext; 22 | + (NSManagedObjectContext *) MR_rootSavingContext; 23 | + (NSManagedObjectContext *) MR_defaultContext; 24 | 25 | - (NSString *) MR_description; 26 | - (NSString *) MR_parentChain; 27 | 28 | @property (nonatomic, copy, setter = MR_setWorkingName:) NSString *MR_workingName; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSManagedObjectContext/NSManagedObjectContext+MagicalRecord.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSManagedObjectContext+MagicalRecord.m 3 | // 4 | // Created by Saul Mora on 11/23/09. 5 | // Copyright 2010 Magical Panda Software, LLC All rights reserved. 6 | // 7 | 8 | #import "CoreData+MagicalRecord.h" 9 | #import 10 | 11 | static NSManagedObjectContext *rootSavingContext = nil; 12 | static NSManagedObjectContext *defaultManagedObjectContext_ = nil; 13 | static id iCloudSetupNotificationObserver = nil; 14 | 15 | static NSString * const kMagicalRecordNSManagedObjectContextWorkingName = @"kNSManagedObjectContextWorkingName"; 16 | 17 | @interface NSManagedObjectContext (MagicalRecordInternal) 18 | 19 | - (void) MR_mergeChangesFromNotification:(NSNotification *)notification; 20 | - (void) MR_mergeChangesOnMainThread:(NSNotification *)notification; 21 | + (void) MR_setDefaultContext:(NSManagedObjectContext *)moc; 22 | + (void) MR_setRootSavingContext:(NSManagedObjectContext *)context; 23 | 24 | @end 25 | 26 | 27 | @implementation NSManagedObjectContext (MagicalRecord) 28 | 29 | + (void) MR_cleanUp; 30 | { 31 | [self MR_setDefaultContext:nil]; 32 | [self MR_setRootSavingContext:nil]; 33 | } 34 | 35 | - (NSString *) MR_description; 36 | { 37 | NSString *contextLabel = [NSString stringWithFormat:@"*** %@ ***", [self MR_workingName]]; 38 | NSString *onMainThread = [NSThread isMainThread] ? @"*** MAIN THREAD ***" : @"*** BACKGROUND THREAD ***"; 39 | 40 | return [NSString stringWithFormat:@"<%@ (%p): %@> on %@", NSStringFromClass([self class]), self, contextLabel, onMainThread]; 41 | } 42 | 43 | - (NSString *) MR_parentChain; 44 | { 45 | NSMutableString *familyTree = [@"\n" mutableCopy]; 46 | NSManagedObjectContext *currentContext = self; 47 | do 48 | { 49 | [familyTree appendFormat:@"- %@ (%p) %@\n", [currentContext MR_workingName], currentContext, (currentContext == self ? @"(*)" : @"")]; 50 | } 51 | while ((currentContext = [currentContext parentContext])); 52 | 53 | return [NSString stringWithString:familyTree]; 54 | } 55 | 56 | + (NSManagedObjectContext *) MR_defaultContext 57 | { 58 | @synchronized (self) 59 | { 60 | NSAssert(defaultManagedObjectContext_ != nil, @"Default Context is nil! Did you forget to initialize the Core Data Stack?"); 61 | return defaultManagedObjectContext_; 62 | } 63 | } 64 | 65 | + (void) MR_setDefaultContext:(NSManagedObjectContext *)moc 66 | { 67 | if (defaultManagedObjectContext_) 68 | { 69 | [[NSNotificationCenter defaultCenter] removeObserver:defaultManagedObjectContext_]; 70 | } 71 | 72 | NSPersistentStoreCoordinator *coordinator = [NSPersistentStoreCoordinator MR_defaultStoreCoordinator]; 73 | if (iCloudSetupNotificationObserver) 74 | { 75 | [[NSNotificationCenter defaultCenter] removeObserver:iCloudSetupNotificationObserver]; 76 | iCloudSetupNotificationObserver = nil; 77 | } 78 | 79 | if ([MagicalRecord isICloudEnabled]) 80 | { 81 | [defaultManagedObjectContext_ MR_stopObservingiCloudChangesInCoordinator:coordinator]; 82 | } 83 | 84 | defaultManagedObjectContext_ = moc; 85 | [defaultManagedObjectContext_ MR_setWorkingName:@"DEFAULT"]; 86 | 87 | if ((defaultManagedObjectContext_ != nil) && ([self MR_rootSavingContext] != nil)) { 88 | [[NSNotificationCenter defaultCenter] addObserver:self 89 | selector:@selector(rootContextChanged:) 90 | name:NSManagedObjectContextDidSaveNotification 91 | object:[self MR_rootSavingContext]]; 92 | } 93 | 94 | [moc MR_obtainPermanentIDsBeforeSaving]; 95 | if ([MagicalRecord isICloudEnabled]) 96 | { 97 | [defaultManagedObjectContext_ MR_observeiCloudChangesInCoordinator:coordinator]; 98 | } 99 | else 100 | { 101 | // If icloud is NOT enabled at the time of this method being called, listen for it to be setup later, and THEN set up observing cloud changes 102 | iCloudSetupNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMagicalRecordPSCDidCompleteiCloudSetupNotification 103 | object:nil 104 | queue:[NSOperationQueue mainQueue] 105 | usingBlock:^(NSNotification *note) { 106 | [[NSManagedObjectContext MR_defaultContext] MR_observeiCloudChangesInCoordinator:coordinator]; 107 | }]; 108 | } 109 | MRLog(@"Set Default Context: %@", defaultManagedObjectContext_); 110 | } 111 | 112 | + (void)rootContextChanged:(NSNotification *)notification { 113 | if ([NSThread isMainThread] == NO) { 114 | dispatch_async(dispatch_get_main_queue(), ^{ 115 | [self rootContextChanged:notification]; 116 | }); 117 | 118 | return; 119 | } 120 | 121 | [[self MR_defaultContext] mergeChangesFromContextDidSaveNotification:notification]; 122 | } 123 | 124 | + (NSManagedObjectContext *) MR_rootSavingContext; 125 | { 126 | return rootSavingContext; 127 | } 128 | 129 | + (void) MR_setRootSavingContext:(NSManagedObjectContext *)context; 130 | { 131 | if (rootSavingContext) 132 | { 133 | [[NSNotificationCenter defaultCenter] removeObserver:rootSavingContext]; 134 | } 135 | 136 | rootSavingContext = context; 137 | [context MR_obtainPermanentIDsBeforeSaving]; 138 | [rootSavingContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy]; 139 | [rootSavingContext MR_setWorkingName:@"BACKGROUND SAVING (ROOT)"]; 140 | MRLog(@"Set Root Saving Context: %@", rootSavingContext); 141 | } 142 | 143 | + (void) MR_initializeDefaultContextWithCoordinator:(NSPersistentStoreCoordinator *)coordinator; 144 | { 145 | if (defaultManagedObjectContext_ == nil) 146 | { 147 | NSManagedObjectContext *rootContext = [self MR_contextWithStoreCoordinator:coordinator]; 148 | [self MR_setRootSavingContext:rootContext]; 149 | 150 | NSManagedObjectContext *defaultContext = [self MR_newMainQueueContext]; 151 | [self MR_setDefaultContext:defaultContext]; 152 | 153 | [defaultContext setParentContext:rootContext]; 154 | } 155 | } 156 | 157 | + (void) MR_resetDefaultContext 158 | { 159 | void (^resetBlock)(void) = ^{ 160 | [[NSManagedObjectContext MR_defaultContext] reset]; 161 | }; 162 | 163 | dispatch_async(dispatch_get_main_queue(), resetBlock); 164 | } 165 | 166 | + (NSManagedObjectContext *) MR_contextWithoutParent; 167 | { 168 | NSManagedObjectContext *context = [[self alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 169 | return context; 170 | } 171 | 172 | + (NSManagedObjectContext *) MR_context; 173 | { 174 | NSManagedObjectContext *context = [[self alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 175 | [context setParentContext:[self MR_defaultContext]]; 176 | return context; 177 | } 178 | 179 | + (NSManagedObjectContext *) MR_contextWithParent:(NSManagedObjectContext *)parentContext; 180 | { 181 | NSManagedObjectContext *context = [self MR_contextWithoutParent]; 182 | [context setParentContext:parentContext]; 183 | [context MR_obtainPermanentIDsBeforeSaving]; 184 | return context; 185 | } 186 | 187 | + (NSManagedObjectContext *) MR_newMainQueueContext; 188 | { 189 | NSManagedObjectContext *context = [[self alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 190 | MRLog(@"Created Main Queue Context: %@", context); 191 | return context; 192 | } 193 | 194 | + (NSManagedObjectContext *) MR_contextWithStoreCoordinator:(NSPersistentStoreCoordinator *)coordinator; 195 | { 196 | NSManagedObjectContext *context = nil; 197 | if (coordinator != nil) 198 | { 199 | context = [self MR_contextWithoutParent]; 200 | [context performBlockAndWait:^{ 201 | [context setPersistentStoreCoordinator:coordinator]; 202 | }]; 203 | 204 | MRLog(@"-> Created Context %@", [context MR_workingName]); 205 | } 206 | return context; 207 | } 208 | 209 | - (void) MR_obtainPermanentIDsBeforeSaving; 210 | { 211 | [[NSNotificationCenter defaultCenter] addObserver:self 212 | selector:@selector(MR_contextWillSave:) 213 | name:NSManagedObjectContextWillSaveNotification 214 | object:self]; 215 | 216 | 217 | } 218 | 219 | - (void) MR_contextWillSave:(NSNotification *)notification 220 | { 221 | NSManagedObjectContext *context = [notification object]; 222 | NSSet *insertedObjects = [context insertedObjects]; 223 | 224 | if ([insertedObjects count]) 225 | { 226 | MRLog(@"Context %@ is about to save. Obtaining permanent IDs for new %lu inserted objects", [context MR_workingName], (unsigned long)[insertedObjects count]); 227 | NSError *error = nil; 228 | BOOL success = [context obtainPermanentIDsForObjects:[insertedObjects allObjects] error:&error]; 229 | if (!success) 230 | { 231 | [MagicalRecord handleErrors:error]; 232 | } 233 | } 234 | } 235 | 236 | - (void) MR_setWorkingName:(NSString *)workingName; 237 | { 238 | [[self userInfo] setObject:workingName forKey:kMagicalRecordNSManagedObjectContextWorkingName]; 239 | } 240 | 241 | - (NSString *) MR_workingName; 242 | { 243 | NSString *workingName = [[self userInfo] objectForKey:kMagicalRecordNSManagedObjectContextWorkingName]; 244 | if (nil == workingName) 245 | { 246 | workingName = @"UNNAMED"; 247 | } 248 | return workingName; 249 | } 250 | 251 | 252 | @end 253 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSManagedObjectContext/NSManagedObjectContext+MagicalSaves.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSManagedObjectContext+MagicalSaves.h 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/9/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_OPTIONS(NSUInteger, MRSaveContextOptions) { 12 | MRSaveParentContexts = 1, ///< When saving, continue saving parent contexts until the changes are present in the persistent store 13 | MRSaveSynchronously = 2 ///< Peform saves synchronously, blocking execution on the current thread until the save is complete 14 | }; 15 | 16 | typedef void (^MRSaveCompletionHandler)(BOOL success, NSError *error); 17 | 18 | @interface NSManagedObjectContext (MagicalSaves) 19 | 20 | /// \brief Asynchronously save changes in the current context and it's parent 21 | /// \param completion Completion block that is called after the save has completed. The block is passed a success state as a `BOOL` and an `NSError` instance if an error occurs. Always called on the main queue. 22 | /// \discussion Executes a save on the current context's dispatch queue asynchronously. This method only saves the current context, and the parent of the current context if one is set. The completion block will always be called on the main queue. 23 | - (void) MR_saveOnlySelfWithCompletion:(MRSaveCompletionHandler)completion; 24 | 25 | /// \brief Asynchronously save changes in the current context all the way back to the persistent store 26 | /// \param completion Completion block that is called after the save has completed. The block is passed a success state as a `BOOL` and an `NSError` instance if an error occurs. Always called on the main queue. 27 | /// \discussion Executes asynchronous saves on the current context, and any ancestors, until the changes have been persisted to the assigned persistent store. The completion block will always be called on the main queue. 28 | - (void) MR_saveToPersistentStoreWithCompletion:(MRSaveCompletionHandler)completion; 29 | 30 | /// \brief Synchronously save changes in the current context and it's parent 31 | /// \discussion Executes a save on the current context's dispatch queue. This method only saves the current context, and the parent of the current context if one is set. The method will not return until the save is complete. 32 | - (void) MR_saveOnlySelfAndWait; 33 | 34 | /// \brief Synchronously save changes in the current context all the way back to the persistent store 35 | /// \discussion Executes saves on the current context, and any ancestors, until the changes have been persisted to the assigned persistent store. The method will not return until the save is complete. 36 | - (void) MR_saveToPersistentStoreAndWait; 37 | 38 | /// \brief Save the current context with options 39 | /// \param mask bitmasked options for the save process 40 | /// \param completion Completion block that is called after the save has completed. The block is passed a success state as a `BOOL` and an `NSError` instance if an error occurs. Always called on the main queue. 41 | /// \discussion All other save methods are conveniences to this method. 42 | - (void) MR_saveWithOptions:(MRSaveContextOptions)mask completion:(MRSaveCompletionHandler)completion; 43 | 44 | 45 | /* DEPRECATION NOTICE: 46 | * The following methods are deprecated, but remain in place for backwards compatibility until the next major version (3.x) 47 | */ 48 | 49 | /// \brief Synchronously save changes in the current context all the way back to the persistent store 50 | /// \discussion Replaced by \MR_saveToPersistentStoreAndWait 51 | /// \deprecated 52 | - (void) MR_save __attribute__((deprecated)); 53 | 54 | /// \brief Synchronously save changes in the current context all the way back to the persistent store 55 | /// \param errorCallback Block that is called if an error is encountered while saving. Always called on the main thread. 56 | /// \deprecated 57 | - (void) MR_saveWithErrorCallback:(void(^)(NSError *error))errorCallback __attribute__((deprecated)); 58 | 59 | /// \brief Asynchronously save changes in the current context and it's parent 60 | /// \param completion Completion block that is called after the save has completed. Always called on the main queue. 61 | /// \deprecated 62 | - (void) MR_saveInBackgroundCompletion:(void (^)(void))completion __attribute__((deprecated)); 63 | 64 | /// \brief Asynchronously save changes in the current context and it's parent 65 | /// \param errorCallback Block that is called if an error is encountered while saving. Always called on the main thread. 66 | /// \deprecated 67 | - (void) MR_saveInBackgroundErrorHandler:(void (^)(NSError *error))errorCallback __attribute__((deprecated)); 68 | 69 | /// \brief Asynchronously save changes in the current context and it's parent 70 | /// \param errorCallback Block that is called if an error is encountered while saving. Always called on the main thread. 71 | /// \param completion Completion block that is called after the save has completed. Always called on the main queue. 72 | /// \deprecated 73 | - (void) MR_saveInBackgroundErrorHandler:(void (^)(NSError *error))errorCallback completion:(void (^)(void))completion __attribute__((deprecated)); 74 | 75 | /// \brief Asynchronously save changes in the current context all the way back to the persistent store 76 | /// \discussion Replaced by \MR_saveToPersistentStoreWithCompletion: 77 | /// \deprecated 78 | - (void) MR_saveNestedContexts __attribute__((deprecated)); 79 | 80 | /// \brief Asynchronously save changes in the current context all the way back to the persistent store 81 | /// \param errorCallback Block that is called if an error is encountered while saving. Always called on the main thread. 82 | /// \discussion Replaced by \MR_saveToPersistentStoreWithCompletion: 83 | /// \deprecated 84 | - (void) MR_saveNestedContextsErrorHandler:(void (^)(NSError *error))errorCallback __attribute__((deprecated)); 85 | 86 | /// \brief Asynchronously save changes in the current context all the way back to the persistent store 87 | /// \param errorCallback Block that is called if an error is encountered while saving. Always called on the main thread. 88 | /// \param completion Completion block that is called after the save has completed. Always called on the main queue. 89 | /// \discussion Replaced by \MR_saveToPersistentStoreWithCompletion: 90 | /// \deprecated 91 | - (void) MR_saveNestedContextsErrorHandler:(void (^)(NSError *error))errorCallback completion:(void (^)(void))completion __attribute__((deprecated)); 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSManagedObjectContext/NSManagedObjectContext+MagicalSaves.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSManagedObjectContext+MagicalSaves.m 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/9/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "NSManagedObjectContext+MagicalSaves.h" 10 | #import "MagicalRecord+ErrorHandling.h" 11 | #import "NSManagedObjectContext+MagicalRecord.h" 12 | #import "MagicalRecord.h" 13 | 14 | @implementation NSManagedObjectContext (MagicalSaves) 15 | 16 | - (void)MR_saveOnlySelfWithCompletion:(MRSaveCompletionHandler)completion; 17 | { 18 | [self MR_saveWithOptions:0 completion:completion]; 19 | } 20 | 21 | - (void)MR_saveOnlySelfAndWait; 22 | { 23 | [self MR_saveWithOptions:MRSaveSynchronously completion:nil]; 24 | } 25 | 26 | - (void) MR_saveToPersistentStoreWithCompletion:(MRSaveCompletionHandler)completion; 27 | { 28 | [self MR_saveWithOptions:MRSaveParentContexts completion:completion]; 29 | } 30 | 31 | - (void) MR_saveToPersistentStoreAndWait; 32 | { 33 | [self MR_saveWithOptions:MRSaveParentContexts | MRSaveSynchronously completion:nil]; 34 | } 35 | 36 | - (void)MR_saveWithOptions:(MRSaveContextOptions)mask completion:(MRSaveCompletionHandler)completion; 37 | { 38 | BOOL syncSave = ((mask & MRSaveSynchronously) == MRSaveSynchronously); 39 | BOOL saveParentContexts = ((mask & MRSaveParentContexts) == MRSaveParentContexts); 40 | 41 | if (![self hasChanges]) { 42 | MRLog(@"NO CHANGES IN ** %@ ** CONTEXT - NOT SAVING", [self MR_workingName]); 43 | 44 | if (completion) 45 | { 46 | dispatch_async(dispatch_get_main_queue(), ^{ 47 | completion(NO, nil); 48 | }); 49 | } 50 | 51 | return; 52 | } 53 | 54 | MRLog(@"→ Saving %@", [self MR_description]); 55 | MRLog(@"→ Save Parents? %@", @(saveParentContexts)); 56 | MRLog(@"→ Save Synchronously? %@", @(syncSave)); 57 | 58 | id saveBlock = ^{ 59 | NSError *error = nil; 60 | BOOL saved = NO; 61 | 62 | @try 63 | { 64 | saved = [self save:&error]; 65 | } 66 | @catch(NSException *exception) 67 | { 68 | MRLog(@"Unable to perform save: %@", (id)[exception userInfo] ? : (id)[exception reason]); 69 | } 70 | 71 | @finally 72 | { 73 | if (!saved) { 74 | [MagicalRecord handleErrors:error]; 75 | 76 | if (completion) { 77 | dispatch_async(dispatch_get_main_queue(), ^{ 78 | completion(saved, error); 79 | }); 80 | } 81 | } else { 82 | // If we're the default context, save to disk too (the user expects it to persist) 83 | BOOL isDefaultContext = (self == [[self class] MR_defaultContext]); 84 | BOOL shouldSaveParentContext = ((YES == saveParentContexts) || isDefaultContext); 85 | 86 | if (shouldSaveParentContext && [self parentContext]) { 87 | [[self parentContext] MR_saveWithOptions:mask completion:completion]; 88 | } 89 | // If we should not save the parent context, or there is not a parent context to save (root context), call the completion block 90 | else { 91 | MRLog(@"→ Finished saving: %@", [self MR_description]); 92 | 93 | if (completion) { 94 | dispatch_async(dispatch_get_main_queue(), ^{ 95 | completion(saved, error); 96 | }); 97 | } 98 | } 99 | } 100 | } 101 | }; 102 | 103 | if (YES == syncSave) { 104 | [self performBlockAndWait:saveBlock]; 105 | } else { 106 | [self performBlock:saveBlock]; 107 | } 108 | } 109 | 110 | #pragma mark - Deprecated methods 111 | // These methods will be removed in MagicalRecord 3.0 112 | 113 | #pragma clang diagnostic push 114 | #pragma clang diagnostic ignored "-Wdeprecated-implementations" 115 | 116 | - (void)MR_save; 117 | { 118 | [self MR_saveToPersistentStoreAndWait]; 119 | } 120 | 121 | - (void)MR_saveWithErrorCallback:(void (^)(NSError *error))errorCallback; 122 | { 123 | [self MR_saveWithOptions:MRSaveSynchronously|MRSaveParentContexts completion:^(BOOL success, NSError *error) { 124 | if (!success) { 125 | if (errorCallback) { 126 | errorCallback(error); 127 | } 128 | } 129 | }]; 130 | } 131 | 132 | - (void)MR_saveInBackgroundCompletion:(void (^)(void))completion; 133 | { 134 | [self MR_saveOnlySelfWithCompletion:^(BOOL success, NSError *error) { 135 | if (success) { 136 | if (completion) { 137 | completion(); 138 | } 139 | } 140 | }]; 141 | } 142 | 143 | - (void)MR_saveInBackgroundErrorHandler:(void (^)(NSError *error))errorCallback; 144 | { 145 | [self MR_saveOnlySelfWithCompletion:^(BOOL success, NSError *error) { 146 | if (!success) { 147 | if (errorCallback) { 148 | errorCallback(error); 149 | } 150 | } 151 | }]; 152 | } 153 | 154 | - (void)MR_saveInBackgroundErrorHandler:(void (^)(NSError *error))errorCallback completion:(void (^)(void))completion; 155 | { 156 | [self MR_saveOnlySelfWithCompletion:^(BOOL success, NSError *error) { 157 | if (success) { 158 | if (completion) { 159 | completion(); 160 | } 161 | } else { 162 | if (errorCallback) { 163 | errorCallback(error); 164 | } 165 | } 166 | }]; 167 | } 168 | 169 | - (void)MR_saveNestedContexts; 170 | { 171 | [self MR_saveToPersistentStoreWithCompletion:nil]; 172 | } 173 | 174 | - (void)MR_saveNestedContextsErrorHandler:(void (^)(NSError *error))errorCallback; 175 | { 176 | [self MR_saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) { 177 | if (!success) { 178 | if (errorCallback) { 179 | errorCallback(error); 180 | } 181 | } 182 | }]; 183 | } 184 | 185 | - (void)MR_saveNestedContextsErrorHandler:(void (^)(NSError *error))errorCallback completion:(void (^)(void))completion; 186 | { 187 | [self MR_saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) { 188 | if (success) { 189 | if (completion) { 190 | completion(); 191 | } 192 | } else { 193 | if (errorCallback) { 194 | errorCallback(error); 195 | } 196 | } 197 | }]; 198 | } 199 | 200 | #pragma clang diagnostic pop // ignored "-Wdeprecated-implementations" 201 | 202 | @end 203 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSManagedObjectContext/NSManagedObjectContext+MagicalThreading.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSManagedObjectContext+MagicalThreading.h 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/9/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSManagedObjectContext (MagicalThreading) 12 | 13 | + (NSManagedObjectContext *) MR_contextForCurrentThread; 14 | + (void) MR_resetContextForCurrentThread; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSManagedObjectContext/NSManagedObjectContext+MagicalThreading.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSManagedObjectContext+MagicalThreading.m 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/9/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "NSManagedObjectContext+MagicalThreading.h" 10 | #import "NSManagedObject+MagicalRecord.h" 11 | #import "NSManagedObjectContext+MagicalRecord.h" 12 | 13 | static NSString const * kMagicalRecordManagedObjectContextKey = @"MagicalRecord_NSManagedObjectContextForThreadKey"; 14 | 15 | @implementation NSManagedObjectContext (MagicalThreading) 16 | 17 | + (void)MR_resetContextForCurrentThread 18 | { 19 | [[NSManagedObjectContext MR_contextForCurrentThread] reset]; 20 | } 21 | 22 | + (NSManagedObjectContext *) MR_contextForCurrentThread; 23 | { 24 | if ([NSThread isMainThread]) 25 | { 26 | return [self MR_defaultContext]; 27 | } 28 | else 29 | { 30 | NSMutableDictionary *threadDict = [[NSThread currentThread] threadDictionary]; 31 | NSManagedObjectContext *threadContext = [threadDict objectForKey:kMagicalRecordManagedObjectContextKey]; 32 | if (threadContext == nil) 33 | { 34 | threadContext = [self MR_contextWithParent:[NSManagedObjectContext MR_defaultContext]]; 35 | [threadDict setObject:threadContext forKey:kMagicalRecordManagedObjectContextKey]; 36 | } 37 | return threadContext; 38 | } 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSManagedObjectModel+MagicalRecord.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSManagedObjectModel+MagicalRecord.h 3 | // 4 | // Created by Saul Mora on 3/11/10. 5 | // Copyright 2010 Magical Panda Software, LLC All rights reserved. 6 | // 7 | 8 | #import 9 | #import "MagicalRecord.h" 10 | 11 | 12 | @interface NSManagedObjectModel (MagicalRecord) 13 | 14 | + (NSManagedObjectModel *) MR_defaultManagedObjectModel; 15 | 16 | + (void) MR_setDefaultManagedObjectModel:(NSManagedObjectModel *)newDefaultModel; 17 | 18 | + (NSManagedObjectModel *) MR_mergedObjectModelFromMainBundle; 19 | + (NSManagedObjectModel *) MR_newManagedObjectModelNamed:(NSString *)modelFileName NS_RETURNS_RETAINED; 20 | + (NSManagedObjectModel *) MR_managedObjectModelNamed:(NSString *)modelFileName; 21 | + (NSManagedObjectModel *) MR_newModelNamed:(NSString *) modelName inBundleNamed:(NSString *) bundleName NS_RETURNS_RETAINED; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSManagedObjectModel+MagicalRecord.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSManagedObjectModel+MagicalRecord.m 3 | // 4 | // Created by Saul Mora on 3/11/10. 5 | // Copyright 2010 Magical Panda Software, LLC All rights reserved. 6 | // 7 | 8 | //#import "NSManagedObjectModel+MagicalRecord.h" 9 | #import "CoreData+MagicalRecord.h" 10 | 11 | 12 | static NSManagedObjectModel *defaultManagedObjectModel_ = nil; 13 | 14 | @implementation NSManagedObjectModel (MagicalRecord) 15 | 16 | + (NSManagedObjectModel *) MR_defaultManagedObjectModel 17 | { 18 | if (defaultManagedObjectModel_ == nil && [MagicalRecord shouldAutoCreateManagedObjectModel]) 19 | { 20 | [self MR_setDefaultManagedObjectModel:[self MR_mergedObjectModelFromMainBundle]]; 21 | } 22 | return defaultManagedObjectModel_; 23 | } 24 | 25 | + (void) MR_setDefaultManagedObjectModel:(NSManagedObjectModel *)newDefaultModel 26 | { 27 | defaultManagedObjectModel_ = newDefaultModel; 28 | } 29 | 30 | + (NSManagedObjectModel *) MR_mergedObjectModelFromMainBundle; 31 | { 32 | return [self mergedModelFromBundles:nil]; 33 | } 34 | 35 | + (NSManagedObjectModel *) MR_newModelNamed:(NSString *) modelName inBundleNamed:(NSString *) bundleName 36 | { 37 | NSString *path = [[NSBundle mainBundle] pathForResource:[modelName stringByDeletingPathExtension] 38 | ofType:[modelName pathExtension] 39 | inDirectory:bundleName]; 40 | NSURL *modelUrl = [NSURL fileURLWithPath:path]; 41 | 42 | NSManagedObjectModel *mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelUrl]; 43 | 44 | return mom; 45 | } 46 | 47 | + (NSManagedObjectModel *) MR_newManagedObjectModelNamed:(NSString *)modelFileName 48 | { 49 | NSString *path = [[NSBundle mainBundle] pathForResource:[modelFileName stringByDeletingPathExtension] 50 | ofType:[modelFileName pathExtension]]; 51 | NSURL *momURL = [NSURL fileURLWithPath:path]; 52 | 53 | NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL]; 54 | return model; 55 | } 56 | 57 | + (NSManagedObjectModel *) MR_managedObjectModelNamed:(NSString *)modelFileName 58 | { 59 | NSManagedObjectModel *model = [self MR_newManagedObjectModelNamed:modelFileName]; 60 | return model; 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSPersistentStore+MagicalRecord.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSPersistentStore+MagicalRecord.h 3 | // 4 | // Created by Saul Mora on 3/11/10. 5 | // Copyright 2010 Magical Panda Software, LLC All rights reserved. 6 | // 7 | 8 | #import "MagicalRecord.h" 9 | 10 | // option to autodelete store if it already exists 11 | 12 | extern NSString * const kMagicalRecordDefaultStoreFileName; 13 | 14 | 15 | @interface NSPersistentStore (MagicalRecord) 16 | 17 | + (NSURL *) MR_defaultLocalStoreUrl; 18 | 19 | + (NSPersistentStore *) MR_defaultPersistentStore; 20 | + (void) MR_setDefaultPersistentStore:(NSPersistentStore *) store; 21 | 22 | + (NSURL *) MR_urlForStoreName:(NSString *)storeFileName; 23 | + (NSURL *) MR_cloudURLForUbiqutiousContainer:(NSString *)bucketName; 24 | 25 | @end 26 | 27 | 28 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSPersistentStore+MagicalRecord.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSPersistentStore+MagicalRecord.m 3 | // 4 | // Created by Saul Mora on 3/11/10. 5 | // Copyright 2010 Magical Panda Software, LLC All rights reserved. 6 | // 7 | 8 | //#import "NSPersistentStore+MagicalRecord.h" 9 | #import "CoreData+MagicalRecord.h" 10 | 11 | NSString * const kMagicalRecordDefaultStoreFileName = @"CoreDataStore.sqlite"; 12 | 13 | static NSPersistentStore *defaultPersistentStore_ = nil; 14 | 15 | 16 | @implementation NSPersistentStore (MagicalRecord) 17 | 18 | + (NSPersistentStore *) MR_defaultPersistentStore 19 | { 20 | return defaultPersistentStore_; 21 | } 22 | 23 | + (void) MR_setDefaultPersistentStore:(NSPersistentStore *) store 24 | { 25 | defaultPersistentStore_ = store; 26 | } 27 | 28 | + (NSString *) MR_directory:(int) type 29 | { 30 | return [NSSearchPathForDirectoriesInDomains(type, NSUserDomainMask, YES) lastObject]; 31 | } 32 | 33 | + (NSString *)MR_applicationDocumentsDirectory 34 | { 35 | return [self MR_directory:NSDocumentDirectory]; 36 | } 37 | 38 | + (NSString *)MR_applicationStorageDirectory 39 | { 40 | NSString *applicationName = [[[NSBundle mainBundle] infoDictionary] valueForKey:(NSString *)kCFBundleNameKey]; 41 | return [[self MR_directory:NSApplicationSupportDirectory] stringByAppendingPathComponent:applicationName]; 42 | } 43 | 44 | + (NSURL *) MR_urlForStoreName:(NSString *)storeFileName 45 | { 46 | NSArray *paths = [NSArray arrayWithObjects:[self MR_applicationDocumentsDirectory], [self MR_applicationStorageDirectory], nil]; 47 | NSFileManager *fm = [[NSFileManager alloc] init]; 48 | 49 | for (NSString *path in paths) 50 | { 51 | NSString *filepath = [path stringByAppendingPathComponent:storeFileName]; 52 | if ([fm fileExistsAtPath:filepath]) 53 | { 54 | return [NSURL fileURLWithPath:filepath]; 55 | } 56 | } 57 | 58 | //set default url 59 | return [NSURL fileURLWithPath:[[self MR_applicationStorageDirectory] stringByAppendingPathComponent:storeFileName]]; 60 | } 61 | 62 | + (NSURL *) MR_cloudURLForUbiqutiousContainer:(NSString *)bucketName; 63 | { 64 | NSFileManager *fileManager = [[NSFileManager alloc] init]; 65 | NSURL *cloudURL = nil; 66 | if ([fileManager respondsToSelector:@selector(URLForUbiquityContainerIdentifier:)]) 67 | { 68 | cloudURL = [fileManager URLForUbiquityContainerIdentifier:bucketName]; 69 | } 70 | 71 | return cloudURL; 72 | } 73 | 74 | + (NSURL *) MR_defaultLocalStoreUrl 75 | { 76 | return [self MR_urlForStoreName:kMagicalRecordDefaultStoreFileName]; 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Categories/NSPersistentStoreCoordinator+MagicalRecord.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSPersistentStoreCoordinator+MagicalRecord.h 3 | // 4 | // Created by Saul Mora on 3/11/10. 5 | // Copyright 2010 Magical Panda Software, LLC All rights reserved. 6 | // 7 | 8 | #import "MagicalRecord.h" 9 | #import "NSPersistentStore+MagicalRecord.h" 10 | 11 | extern NSString * const kMagicalRecordPSCDidCompleteiCloudSetupNotification; 12 | 13 | @interface NSPersistentStoreCoordinator (MagicalRecord) 14 | 15 | + (NSPersistentStoreCoordinator *) MR_defaultStoreCoordinator; 16 | + (void) MR_setDefaultStoreCoordinator:(NSPersistentStoreCoordinator *)coordinator; 17 | 18 | + (NSPersistentStoreCoordinator *) MR_coordinatorWithInMemoryStore; 19 | 20 | + (NSPersistentStoreCoordinator *) MR_newPersistentStoreCoordinator NS_RETURNS_RETAINED; 21 | 22 | + (NSPersistentStoreCoordinator *) MR_coordinatorWithSqliteStoreNamed:(NSString *)storeFileName; 23 | + (NSPersistentStoreCoordinator *) MR_coordinatorWithAutoMigratingSqliteStoreNamed:(NSString *)storeFileName; 24 | + (NSPersistentStoreCoordinator *) MR_coordinatorWithPersistentStore:(NSPersistentStore *)persistentStore; 25 | + (NSPersistentStoreCoordinator *) MR_coordinatorWithiCloudContainerID:(NSString *)containerID contentNameKey:(NSString *)contentNameKey localStoreNamed:(NSString *)localStoreName cloudStorePathComponent:(NSString *)subPathComponent; 26 | 27 | + (NSPersistentStoreCoordinator *) MR_coordinatorWithiCloudContainerID:(NSString *)containerID contentNameKey:(NSString *)contentNameKey localStoreNamed:(NSString *)localStoreName cloudStorePathComponent:(NSString *)subPathComponent completion:(void(^)(void))completionHandler; 28 | 29 | - (NSPersistentStore *) MR_addInMemoryStore; 30 | - (NSPersistentStore *) MR_addAutoMigratingSqliteStoreNamed:(NSString *) storeFileName; 31 | - (NSPersistentStore *) MR_addSqliteStoreNamed:(id)storeFileName withOptions:(__autoreleasing NSDictionary *)options; 32 | 33 | - (void) MR_addiCloudContainerID:(NSString *)containerID contentNameKey:(NSString *)contentNameKey localStoreNamed:(NSString *)localStoreName cloudStorePathComponent:(NSString *)subPathComponent; 34 | - (void) MR_addiCloudContainerID:(NSString *)containerID contentNameKey:(NSString *)contentNameKey localStoreNamed:(NSString *)localStoreName cloudStorePathComponent:(NSString *)subPathComponent completion:(void(^)(void))completionBlock; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Core/MagicalRecord+Actions.h: -------------------------------------------------------------------------------- 1 | // 2 | // MagicalRecord+Actions.h 3 | // 4 | // Created by Saul Mora on 2/24/11. 5 | // Copyright 2011 Magical Panda Software. All rights reserved. 6 | // 7 | 8 | #import 9 | #import "NSManagedObjectContext+MagicalRecord.h" 10 | #import "NSManagedObjectContext+MagicalSaves.h" 11 | 12 | @interface MagicalRecord (Actions) 13 | 14 | /* For all background saving operations. These calls will be sent to a different thread/queue. 15 | */ 16 | + (void) saveWithBlock:(void(^)(NSManagedObjectContext *localContext))block; 17 | + (void) saveWithBlock:(void(^)(NSManagedObjectContext *localContext))block completion:(MRSaveCompletionHandler)completion; 18 | 19 | /* For saving on the current thread as the caller, only with a seperate context. Useful when you're managing your own threads/queues and need a serial call to create or change data 20 | */ 21 | + (void) saveWithBlockAndWait:(void(^)(NSManagedObjectContext *localContext))block; 22 | 23 | /* 24 | If you want to reuse the context on the current thread, use these methods. 25 | */ 26 | + (void) saveUsingCurrentThreadContextWithBlock:(void (^)(NSManagedObjectContext *localContext))block completion:(MRSaveCompletionHandler)completion; 27 | + (void) saveUsingCurrentThreadContextWithBlockAndWait:(void (^)(NSManagedObjectContext *localContext))block; 28 | 29 | 30 | /* DEPRECATION NOTICE: 31 | * The following methods are deprecated, but remain in place for backwards compatibility until the next major version (3.x) 32 | */ 33 | 34 | /* For all background saving operations. These calls will be sent to a different thread/queue. 35 | */ 36 | + (void) saveInBackgroundWithBlock:(void(^)(NSManagedObjectContext *localContext))block __attribute__((deprecated)); 37 | + (void) saveInBackgroundWithBlock:(void(^)(NSManagedObjectContext *localContext))block completion:(void(^)(void))completion __attribute__((deprecated)); 38 | 39 | /* 40 | If you want to reuse the context on the current thread, use this method. 41 | */ 42 | + (void) saveInBackgroundUsingCurrentContextWithBlock:(void (^)(NSManagedObjectContext *localContext))block completion:(void (^)(void))completion errorHandler:(void (^)(NSError *error))errorHandler __attribute__((deprecated)); 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Core/MagicalRecord+Actions.m: -------------------------------------------------------------------------------- 1 | // 2 | // MagicalRecord+Actions.m 3 | // 4 | // Created by Saul Mora on 2/24/11. 5 | // Copyright 2011 Magical Panda Software. All rights reserved. 6 | // 7 | 8 | #import "CoreData+MagicalRecord.h" 9 | #import "NSManagedObjectContext+MagicalRecord.h" 10 | 11 | 12 | @implementation MagicalRecord (Actions) 13 | 14 | #pragma mark - Asynchronous saving 15 | 16 | + (void) saveWithBlock:(void(^)(NSManagedObjectContext *localContext))block; 17 | { 18 | [self saveWithBlock:block completion:nil]; 19 | } 20 | 21 | + (void) saveWithBlock:(void(^)(NSManagedObjectContext *localContext))block completion:(MRSaveCompletionHandler)completion; 22 | { 23 | NSManagedObjectContext *mainContext = [NSManagedObjectContext MR_rootSavingContext]; 24 | NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextWithParent:mainContext]; 25 | 26 | [localContext performBlock:^{ 27 | if (block) { 28 | block(localContext); 29 | } 30 | 31 | [localContext MR_saveWithOptions:MRSaveParentContexts completion:completion]; 32 | }]; 33 | } 34 | 35 | + (void) saveUsingCurrentThreadContextWithBlock:(void (^)(NSManagedObjectContext *localContext))block completion:(MRSaveCompletionHandler)completion; 36 | { 37 | NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread]; 38 | 39 | [localContext performBlock:^{ 40 | if (block) { 41 | block(localContext); 42 | } 43 | 44 | [localContext MR_saveWithOptions:MRSaveParentContexts completion:completion]; 45 | }]; 46 | } 47 | 48 | 49 | #pragma mark - Synchronous saving 50 | 51 | + (void) saveWithBlockAndWait:(void(^)(NSManagedObjectContext *localContext))block; 52 | { 53 | NSManagedObjectContext *mainContext = [NSManagedObjectContext MR_rootSavingContext]; 54 | NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextWithParent:mainContext]; 55 | 56 | [localContext performBlockAndWait:^{ 57 | if (block) { 58 | block(localContext); 59 | } 60 | 61 | [localContext MR_saveWithOptions:MRSaveParentContexts|MRSaveSynchronously completion:nil]; 62 | }]; 63 | } 64 | 65 | + (void) saveUsingCurrentThreadContextWithBlockAndWait:(void (^)(NSManagedObjectContext *localContext))block; 66 | { 67 | NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread]; 68 | 69 | [localContext performBlockAndWait:^{ 70 | if (block) { 71 | block(localContext); 72 | } 73 | 74 | [localContext MR_saveWithOptions:MRSaveParentContexts|MRSaveSynchronously completion:nil]; 75 | }]; 76 | } 77 | 78 | 79 | #pragma mark - Deprecated methods 80 | 81 | #pragma clang diagnostic push 82 | #pragma clang diagnostic ignored "-Wdeprecated-implementations" 83 | 84 | + (void) saveInBackgroundWithBlock:(void(^)(NSManagedObjectContext *localContext))block 85 | { 86 | [[self class] saveWithBlock:block completion:nil]; 87 | } 88 | 89 | + (void) saveInBackgroundWithBlock:(void(^)(NSManagedObjectContext *localContext))block completion:(void(^)(void))completion 90 | { 91 | NSManagedObjectContext *mainContext = [NSManagedObjectContext MR_defaultContext]; 92 | NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextWithParent:mainContext]; 93 | 94 | [localContext performBlock:^{ 95 | if (block) 96 | { 97 | block(localContext); 98 | } 99 | 100 | [localContext MR_saveToPersistentStoreAndWait]; 101 | 102 | if (completion) 103 | { 104 | completion(); 105 | } 106 | }]; 107 | } 108 | 109 | + (void) saveInBackgroundUsingCurrentContextWithBlock:(void (^)(NSManagedObjectContext *localContext))block completion:(void (^)(void))completion errorHandler:(void (^)(NSError *error))errorHandler; 110 | { 111 | NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread]; 112 | 113 | [localContext performBlock:^{ 114 | if (block) { 115 | block(localContext); 116 | } 117 | 118 | [localContext MR_saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) { 119 | if (success) { 120 | if (completion) { 121 | completion(); 122 | } 123 | } 124 | else { 125 | if (errorHandler) { 126 | errorHandler(error); 127 | } 128 | } 129 | }]; 130 | }]; 131 | } 132 | 133 | #pragma clang diagnostic pop // ignored "-Wdeprecated-implementations" 134 | 135 | @end 136 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Core/MagicalRecord+ErrorHandling.h: -------------------------------------------------------------------------------- 1 | // 2 | // MagicalRecord+ErrorHandling.h 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/6/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "MagicalRecord.h" 10 | 11 | @interface MagicalRecord (ErrorHandling) 12 | 13 | + (void) handleErrors:(NSError *)error; 14 | - (void) handleErrors:(NSError *)error; 15 | 16 | + (void) setErrorHandlerTarget:(id)target action:(SEL)action; 17 | + (SEL) errorHandlerAction; 18 | + (id) errorHandlerTarget; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Core/MagicalRecord+ErrorHandling.m: -------------------------------------------------------------------------------- 1 | // 2 | // MagicalRecord+ErrorHandling.m 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/6/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "MagicalRecord+ErrorHandling.h" 10 | 11 | 12 | static id errorHandlerTarget = nil; 13 | static SEL errorHandlerAction = nil; 14 | 15 | 16 | @implementation MagicalRecord (ErrorHandling) 17 | 18 | + (void) cleanUpErrorHanding; 19 | { 20 | errorHandlerTarget = nil; 21 | errorHandlerAction = nil; 22 | } 23 | 24 | + (void) defaultErrorHandler:(NSError *)error 25 | { 26 | NSDictionary *userInfo = [error userInfo]; 27 | for (NSArray *detailedError in [userInfo allValues]) 28 | { 29 | if ([detailedError isKindOfClass:[NSArray class]]) 30 | { 31 | for (NSError *e in detailedError) 32 | { 33 | if ([e respondsToSelector:@selector(userInfo)]) 34 | { 35 | MRLog(@"Error Details: %@", [e userInfo]); 36 | } 37 | else 38 | { 39 | MRLog(@"Error Details: %@", e); 40 | } 41 | } 42 | } 43 | else 44 | { 45 | MRLog(@"Error: %@", detailedError); 46 | } 47 | } 48 | MRLog(@"Error Message: %@", [error localizedDescription]); 49 | MRLog(@"Error Domain: %@", [error domain]); 50 | MRLog(@"Recovery Suggestion: %@", [error localizedRecoverySuggestion]); 51 | } 52 | 53 | + (void) handleErrors:(NSError *)error 54 | { 55 | if (error) 56 | { 57 | // If a custom error handler is set, call that 58 | if (errorHandlerTarget != nil && errorHandlerAction != nil) 59 | { 60 | #pragma clang diagnostic push 61 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 62 | [errorHandlerTarget performSelector:errorHandlerAction withObject:error]; 63 | #pragma clang diagnostic pop 64 | } 65 | else 66 | { 67 | // Otherwise, fall back to the default error handling 68 | [self defaultErrorHandler:error]; 69 | } 70 | } 71 | } 72 | 73 | + (id) errorHandlerTarget 74 | { 75 | return errorHandlerTarget; 76 | } 77 | 78 | + (SEL) errorHandlerAction 79 | { 80 | return errorHandlerAction; 81 | } 82 | 83 | + (void) setErrorHandlerTarget:(id)target action:(SEL)action 84 | { 85 | errorHandlerTarget = target; /* Deliberately don't retain to avoid potential retain cycles */ 86 | errorHandlerAction = action; 87 | } 88 | 89 | - (void) handleErrors:(NSError *)error 90 | { 91 | [[self class] handleErrors:error]; 92 | } 93 | 94 | @end 95 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Core/MagicalRecord+Options.h: -------------------------------------------------------------------------------- 1 | // 2 | // MagicalRecord+Options.h 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/6/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "MagicalRecord.h" 10 | 11 | @interface MagicalRecord (Options) 12 | 13 | //global options 14 | // enable/disable logging 15 | // add logging provider 16 | // autocreate new PSC per Store 17 | // autoassign new instances to default store 18 | 19 | + (BOOL) shouldAutoCreateManagedObjectModel; 20 | + (void) setShouldAutoCreateManagedObjectModel:(BOOL)shouldAutoCreate; 21 | + (BOOL) shouldAutoCreateDefaultPersistentStoreCoordinator; 22 | + (void) setShouldAutoCreateDefaultPersistentStoreCoordinator:(BOOL)shouldAutoCreate; 23 | + (void) setShouldDeleteStoreOnModelMismatch:(BOOL)shouldDeleteStoreOnModelMismatch; 24 | 25 | /*! 26 | @method shouldDeleteStoreOnModelMistmatch 27 | @abstract If true, when configuring the persistant store coordinator, and Magical Record encounters a store that does not match the model, it will attempt to remove it and re-create a new store. 28 | This is extremely useful during development where every model change could potentially require a delete/reinstall of the app. 29 | */ 30 | + (BOOL) shouldDeleteStoreOnModelMismatch; 31 | 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Core/MagicalRecord+Options.m: -------------------------------------------------------------------------------- 1 | // 2 | // MagicalRecord+Options.m 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/6/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "MagicalRecord+Options.h" 10 | 11 | static BOOL shouldAutoCreateManagedObjectModel_; 12 | static BOOL shouldAutoCreateDefaultPersistentStoreCoordinator_; 13 | static BOOL shouldDeleteStoreOnModelMismatch_; 14 | 15 | @implementation MagicalRecord (Options) 16 | 17 | #pragma mark - Options 18 | 19 | + (BOOL) shouldAutoCreateManagedObjectModel; 20 | { 21 | return shouldAutoCreateManagedObjectModel_; 22 | } 23 | 24 | + (void) setShouldAutoCreateManagedObjectModel:(BOOL)shouldAutoCreate; 25 | { 26 | shouldAutoCreateManagedObjectModel_ = shouldAutoCreate; 27 | } 28 | 29 | + (BOOL) shouldAutoCreateDefaultPersistentStoreCoordinator; 30 | { 31 | return shouldAutoCreateDefaultPersistentStoreCoordinator_; 32 | } 33 | 34 | + (void) setShouldAutoCreateDefaultPersistentStoreCoordinator:(BOOL)shouldAutoCreate; 35 | { 36 | shouldAutoCreateDefaultPersistentStoreCoordinator_ = shouldAutoCreate; 37 | } 38 | 39 | + (BOOL) shouldDeleteStoreOnModelMismatch; 40 | { 41 | return shouldDeleteStoreOnModelMismatch_; 42 | } 43 | 44 | + (void) setShouldDeleteStoreOnModelMismatch:(BOOL)shouldDeleteStoreOnModelMismatch 45 | { 46 | shouldDeleteStoreOnModelMismatch_ = shouldDeleteStoreOnModelMismatch; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Core/MagicalRecord+Setup.h: -------------------------------------------------------------------------------- 1 | // 2 | // MagicalRecord+Setup.h 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/7/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "MagicalRecord.h" 10 | 11 | @interface MagicalRecord (Setup) 12 | 13 | + (void) setupCoreDataStack; 14 | + (void) setupCoreDataStackWithInMemoryStore; 15 | + (void) setupAutoMigratingCoreDataStack; 16 | 17 | + (void) setupCoreDataStackWithStoreNamed:(NSString *)storeName; 18 | + (void) setupCoreDataStackWithAutoMigratingSqliteStoreNamed:(NSString *)storeName; 19 | 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Core/MagicalRecord+Setup.m: -------------------------------------------------------------------------------- 1 | // 2 | // MagicalRecord+Setup.m 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/7/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "MagicalRecord+Setup.h" 10 | #import "NSManagedObject+MagicalRecord.h" 11 | #import "NSPersistentStoreCoordinator+MagicalRecord.h" 12 | #import "NSManagedObjectContext+MagicalRecord.h" 13 | 14 | @implementation MagicalRecord (Setup) 15 | 16 | + (void) setupCoreDataStack 17 | { 18 | [self setupCoreDataStackWithStoreNamed:[self defaultStoreName]]; 19 | } 20 | 21 | + (void) setupAutoMigratingCoreDataStack 22 | { 23 | [self setupCoreDataStackWithAutoMigratingSqliteStoreNamed:[self defaultStoreName]]; 24 | } 25 | 26 | + (void) setupCoreDataStackWithStoreNamed:(NSString *)storeName 27 | { 28 | if ([NSPersistentStoreCoordinator MR_defaultStoreCoordinator] != nil) return; 29 | 30 | NSPersistentStoreCoordinator *coordinator = [NSPersistentStoreCoordinator MR_coordinatorWithSqliteStoreNamed:storeName]; 31 | [NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:coordinator]; 32 | 33 | [NSManagedObjectContext MR_initializeDefaultContextWithCoordinator:coordinator]; 34 | } 35 | 36 | + (void) setupCoreDataStackWithAutoMigratingSqliteStoreNamed:(NSString *)storeName 37 | { 38 | if ([NSPersistentStoreCoordinator MR_defaultStoreCoordinator] != nil) return; 39 | 40 | NSPersistentStoreCoordinator *coordinator = [NSPersistentStoreCoordinator MR_coordinatorWithAutoMigratingSqliteStoreNamed:storeName]; 41 | [NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:coordinator]; 42 | 43 | [NSManagedObjectContext MR_initializeDefaultContextWithCoordinator:coordinator]; 44 | } 45 | 46 | + (void) setupCoreDataStackWithInMemoryStore; 47 | { 48 | if ([NSPersistentStoreCoordinator MR_defaultStoreCoordinator] != nil) return; 49 | 50 | NSPersistentStoreCoordinator *coordinator = [NSPersistentStoreCoordinator MR_coordinatorWithInMemoryStore]; 51 | [NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:coordinator]; 52 | 53 | [NSManagedObjectContext MR_initializeDefaultContextWithCoordinator:coordinator]; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Core/MagicalRecord+ShorthandSupport.h: -------------------------------------------------------------------------------- 1 | // 2 | // MagicalRecord+ShorthandSupport.h 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/6/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "MagicalRecord.h" 10 | 11 | @interface MagicalRecord (ShorthandSupport) 12 | 13 | #ifdef MR_SHORTHAND 14 | + (void) swizzleShorthandMethods; 15 | #endif 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Core/MagicalRecord+ShorthandSupport.m: -------------------------------------------------------------------------------- 1 | // 2 | // MagicalRecord+ShorthandSupport.m 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/6/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "MagicalRecord+ShorthandSupport.h" 10 | #import 11 | 12 | 13 | static NSString * const kMagicalRecordCategoryPrefix = @"MR_"; 14 | #ifdef MR_SHORTHAND 15 | static BOOL methodsHaveBeenSwizzled = NO; 16 | #endif 17 | 18 | 19 | //Dynamic shorthand method helpers 20 | BOOL addMagicalRecordShortHandMethodToPrefixedClassMethod(Class class, SEL selector); 21 | BOOL addMagicalRecordShorthandMethodToPrefixedInstanceMethod(Class klass, SEL originalSelector); 22 | 23 | void swizzleInstanceMethods(Class originalClass, SEL originalSelector, Class targetClass, SEL newSelector); 24 | void replaceSelectorForTargetWithSourceImpAndSwizzle(Class originalClass, SEL originalSelector, Class newClass, SEL newSelector); 25 | 26 | 27 | @implementation MagicalRecord (ShorthandSupport) 28 | 29 | #pragma mark - Support methods for shorthand methods 30 | 31 | #ifdef MR_SHORTHAND 32 | + (BOOL) MR_resolveClassMethod:(SEL)originalSelector 33 | { 34 | BOOL resolvedClassMethod = [self MR_resolveClassMethod:originalSelector]; 35 | if (!resolvedClassMethod) 36 | { 37 | resolvedClassMethod = addMagicalRecordShortHandMethodToPrefixedClassMethod(self, originalSelector); 38 | } 39 | return resolvedClassMethod; 40 | } 41 | 42 | + (BOOL) MR_resolveInstanceMethod:(SEL)originalSelector 43 | { 44 | BOOL resolvedClassMethod = [self MR_resolveInstanceMethod:originalSelector]; 45 | if (!resolvedClassMethod) 46 | { 47 | resolvedClassMethod = addMagicalRecordShorthandMethodToPrefixedInstanceMethod(self, originalSelector); 48 | } 49 | return resolvedClassMethod; 50 | } 51 | 52 | //In order to add support for non-prefixed AND prefixed methods, we need to swap the existing resolveClassMethod: and resolveInstanceMethod: implementations with the one in this class. 53 | + (void) updateResolveMethodsForClass:(Class)klass 54 | { 55 | replaceSelectorForTargetWithSourceImpAndSwizzle(self, @selector(MR_resolveClassMethod:), klass, @selector(resolveClassMethod:)); 56 | replaceSelectorForTargetWithSourceImpAndSwizzle(self, @selector(MR_resolveInstanceMethod:), klass, @selector(resolveInstanceMethod:)); 57 | } 58 | 59 | + (void) swizzleShorthandMethods; 60 | { 61 | if (methodsHaveBeenSwizzled) return; 62 | 63 | NSArray *classes = [NSArray arrayWithObjects: 64 | [NSManagedObject class], 65 | [NSManagedObjectContext class], 66 | [NSManagedObjectModel class], 67 | [NSPersistentStore class], 68 | [NSPersistentStoreCoordinator class], nil]; 69 | 70 | [classes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 71 | Class klass = (Class)obj; 72 | 73 | [self updateResolveMethodsForClass:klass]; 74 | }]; 75 | methodsHaveBeenSwizzled = YES; 76 | } 77 | #endif 78 | 79 | @end 80 | 81 | #pragma mark - Support functions for runtime shorthand Method calling 82 | 83 | void replaceSelectorForTargetWithSourceImpAndSwizzle(Class sourceClass, SEL sourceSelector, Class targetClass, SEL targetSelector) 84 | { 85 | Method sourceClassMethod = class_getClassMethod(sourceClass, sourceSelector); 86 | Method targetClassMethod = class_getClassMethod(targetClass, targetSelector); 87 | 88 | Class targetMetaClass = objc_getMetaClass([NSStringFromClass(targetClass) cStringUsingEncoding:NSUTF8StringEncoding]); 89 | 90 | BOOL methodWasAdded = class_addMethod(targetMetaClass, sourceSelector, 91 | method_getImplementation(targetClassMethod), 92 | method_getTypeEncoding(targetClassMethod)); 93 | 94 | if (methodWasAdded) 95 | { 96 | class_replaceMethod(targetMetaClass, targetSelector, 97 | method_getImplementation(sourceClassMethod), 98 | method_getTypeEncoding(sourceClassMethod)); 99 | } 100 | } 101 | 102 | BOOL addMagicalRecordShorthandMethodToPrefixedInstanceMethod(Class klass, SEL originalSelector) 103 | { 104 | NSString *originalSelectorString = NSStringFromSelector(originalSelector); 105 | if ([originalSelectorString hasPrefix:@"_"] || [originalSelectorString hasPrefix:@"init"]) return NO; 106 | 107 | if (![originalSelectorString hasPrefix:kMagicalRecordCategoryPrefix]) 108 | { 109 | NSString *prefixedSelector = [kMagicalRecordCategoryPrefix stringByAppendingString:originalSelectorString]; 110 | Method existingMethod = class_getInstanceMethod(klass, NSSelectorFromString(prefixedSelector)); 111 | 112 | if (existingMethod) 113 | { 114 | BOOL methodWasAdded = class_addMethod(klass, 115 | originalSelector, 116 | method_getImplementation(existingMethod), 117 | method_getTypeEncoding(existingMethod)); 118 | 119 | return methodWasAdded; 120 | } 121 | } 122 | return NO; 123 | } 124 | 125 | 126 | BOOL addMagicalRecordShortHandMethodToPrefixedClassMethod(Class klass, SEL originalSelector) 127 | { 128 | NSString *originalSelectorString = NSStringFromSelector(originalSelector); 129 | if (![originalSelectorString hasPrefix:kMagicalRecordCategoryPrefix]) 130 | { 131 | NSString *prefixedSelector = [kMagicalRecordCategoryPrefix stringByAppendingString:originalSelectorString]; 132 | Method existingMethod = class_getClassMethod(klass, NSSelectorFromString(prefixedSelector)); 133 | 134 | if (existingMethod) 135 | { 136 | Class metaClass = objc_getMetaClass([NSStringFromClass(klass) cStringUsingEncoding:NSUTF8StringEncoding]); 137 | BOOL methodWasAdded = class_addMethod(metaClass, 138 | originalSelector, 139 | method_getImplementation(existingMethod), 140 | method_getTypeEncoding(existingMethod)); 141 | 142 | return methodWasAdded; 143 | } 144 | } 145 | return NO; 146 | } 147 | 148 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Core/MagicalRecord+iCloud.h: -------------------------------------------------------------------------------- 1 | // 2 | // MagicalRecord+iCloud.h 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/7/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "MagicalRecord.h" 10 | 11 | @interface MagicalRecord (iCloud) 12 | 13 | + (BOOL) isICloudEnabled; 14 | 15 | + (void) setupCoreDataStackWithiCloudContainer:(NSString *)icloudBucket localStoreNamed:(NSString *)localStore; 16 | + (void) setupCoreDataStackWithiCloudContainer:(NSString *)containerID contentNameKey:(NSString *)contentNameKey localStoreNamed:(NSString *)localStoreName cloudStorePathComponent:(NSString *)pathSubcomponent; 17 | + (void) setupCoreDataStackWithiCloudContainer:(NSString *)containerID contentNameKey:(NSString *)contentNameKey localStoreNamed:(NSString *)localStoreName cloudStorePathComponent:(NSString *)pathSubcomponent completion:(void(^)(void))completion; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Core/MagicalRecord+iCloud.m: -------------------------------------------------------------------------------- 1 | // 2 | // MagicalRecord+iCloud.m 3 | // Magical Record 4 | // 5 | // Created by Saul Mora on 3/7/12. 6 | // Copyright (c) 2012 Magical Panda Software LLC. All rights reserved. 7 | // 8 | 9 | #import "MagicalRecord+iCloud.h" 10 | #import "NSPersistentStoreCoordinator+MagicalRecord.h" 11 | #import "NSManagedObjectContext+MagicalRecord.h" 12 | 13 | static BOOL _iCloudEnabled = NO; 14 | 15 | @implementation MagicalRecord (iCloud) 16 | 17 | #pragma mark - iCloud Methods 18 | 19 | + (BOOL) isICloudEnabled; 20 | { 21 | return _iCloudEnabled; 22 | } 23 | 24 | + (void) setICloudEnabled:(BOOL)enabled; 25 | { 26 | @synchronized(self) 27 | { 28 | _iCloudEnabled = enabled; 29 | } 30 | } 31 | 32 | + (void) setupCoreDataStackWithiCloudContainer:(NSString *)icloudBucket localStoreNamed:(NSString *)localStore; 33 | { 34 | NSString *contentNameKey = [[[NSBundle mainBundle] infoDictionary] objectForKey:(id)kCFBundleIdentifierKey]; 35 | [self setupCoreDataStackWithiCloudContainer:icloudBucket 36 | contentNameKey:contentNameKey 37 | localStoreNamed:localStore 38 | cloudStorePathComponent:nil]; 39 | } 40 | 41 | + (void) setupCoreDataStackWithiCloudContainer:(NSString *)containerID contentNameKey:(NSString *)contentNameKey localStoreNamed:(NSString *)localStoreName cloudStorePathComponent:(NSString *)pathSubcomponent; 42 | { 43 | [self setupCoreDataStackWithiCloudContainer:containerID 44 | contentNameKey:contentNameKey 45 | localStoreNamed:localStoreName 46 | cloudStorePathComponent:pathSubcomponent 47 | completion:nil]; 48 | } 49 | 50 | + (void) setupCoreDataStackWithiCloudContainer:(NSString *)containerID contentNameKey:(NSString *)contentNameKey localStoreNamed:(NSString *)localStoreName cloudStorePathComponent:(NSString *)pathSubcomponent completion:(void(^)(void))completion; 51 | { 52 | NSPersistentStoreCoordinator *coordinator = [NSPersistentStoreCoordinator MR_coordinatorWithiCloudContainerID:containerID 53 | contentNameKey:contentNameKey 54 | localStoreNamed:localStoreName 55 | cloudStorePathComponent:pathSubcomponent 56 | completion:completion]; 57 | [NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:coordinator]; 58 | [NSManagedObjectContext MR_initializeDefaultContextWithCoordinator:coordinator]; 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Core/MagicalRecord.h: -------------------------------------------------------------------------------- 1 | // 2 | // MagicalRecord.h 3 | // 4 | // Created by Saul Mora on 3/11/10. 5 | // Copyright 2010 Magical Panda Software, LLC All rights reserved. 6 | // 7 | 8 | #if TARGET_OS_IPHONE == 0 9 | #define MAC_PLATFORM_ONLY YES 10 | #endif 11 | 12 | // enable to use caches for the fetchedResultsControllers (iOS only) 13 | // #define STORE_USE_CACHE 14 | 15 | #ifndef MR_ENABLE_ACTIVE_RECORD_LOGGING 16 | /* 17 | #ifdef DEBUG 18 | #define MR_ENABLE_ACTIVE_RECORD_LOGGING 1 19 | #else 20 | #define MR_ENABLE_ACTIVE_RECORD_LOGGING 0 21 | #endif 22 | */ 23 | 24 | //Micle Mark Debug 25 | 26 | #define MR_ENABLE_ACTIVE_RECORD_LOGGING 0 27 | 28 | #endif 29 | 30 | #if MR_ENABLE_ACTIVE_RECORD_LOGGING != 0 31 | // First, check if we can use Cocoalumberjack for logging 32 | #ifdef LOG_VERBOSE 33 | // extern int ddLogLevel; 34 | #define MRLog(...) DDLogVerbose(__VA_ARGS__) 35 | #else 36 | #define MRLog(...) NSLog(@"%s(%p) %@", __PRETTY_FUNCTION__, self, [NSString stringWithFormat:__VA_ARGS__]) 37 | #endif 38 | #else 39 | #define MRLog(...) ((void)0) 40 | #endif 41 | 42 | #ifdef NS_BLOCKS_AVAILABLE 43 | 44 | @class NSManagedObjectContext; 45 | typedef void (^CoreDataBlock)(NSManagedObjectContext *context); 46 | 47 | #endif 48 | 49 | @interface MagicalRecord : NSObject 50 | 51 | + (NSString *) currentStack; 52 | 53 | + (void) cleanUp; 54 | 55 | + (void) setDefaultModelFromClass:(Class)klass; 56 | + (void) setDefaultModelNamed:(NSString *)modelName; 57 | + (NSString *) defaultStoreName; 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/Core/MagicalRecord.m: -------------------------------------------------------------------------------- 1 | // 2 | // MagicalRecord.m 3 | // 4 | // Created by Saul Mora on 3/11/10. 5 | // Copyright 2010 Magical Panda Software, LLC All rights reserved. 6 | // 7 | 8 | #import "CoreData+MagicalRecord.h" 9 | 10 | @interface MagicalRecord (Internal) 11 | 12 | + (void) cleanUpStack; 13 | + (void) cleanUpErrorHanding; 14 | 15 | @end 16 | 17 | @interface NSManagedObjectContext (MagicalRecordInternal) 18 | 19 | + (void) MR_cleanUp; 20 | 21 | @end 22 | 23 | 24 | @implementation MagicalRecord 25 | 26 | + (void) cleanUp 27 | { 28 | [self cleanUpErrorHanding]; 29 | [self cleanUpStack]; 30 | } 31 | 32 | + (void) cleanUpStack; 33 | { 34 | [NSManagedObjectContext MR_cleanUp]; 35 | [NSManagedObjectModel MR_setDefaultManagedObjectModel:nil]; 36 | [NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:nil]; 37 | [NSPersistentStore MR_setDefaultPersistentStore:nil]; 38 | } 39 | 40 | + (NSString *) currentStack 41 | { 42 | NSMutableString *status = [NSMutableString stringWithString:@"Current Default Core Data Stack: ---- \n"]; 43 | 44 | [status appendFormat:@"Model: %@\n", [[NSManagedObjectModel MR_defaultManagedObjectModel] entityVersionHashesByName]]; 45 | [status appendFormat:@"Coordinator: %@\n", [NSPersistentStoreCoordinator MR_defaultStoreCoordinator]]; 46 | [status appendFormat:@"Store: %@\n", [NSPersistentStore MR_defaultPersistentStore]]; 47 | [status appendFormat:@"Default Context: %@\n", [[NSManagedObjectContext MR_defaultContext] MR_description]]; 48 | [status appendFormat:@"Context Chain: \n%@\n", [[NSManagedObjectContext MR_defaultContext] MR_parentChain]]; 49 | 50 | return status; 51 | } 52 | 53 | + (void) setDefaultModelNamed:(NSString *)modelName; 54 | { 55 | NSManagedObjectModel *model = [NSManagedObjectModel MR_managedObjectModelNamed:modelName]; 56 | [NSManagedObjectModel MR_setDefaultManagedObjectModel:model]; 57 | } 58 | 59 | + (void) setDefaultModelFromClass:(Class)klass; 60 | { 61 | NSBundle *bundle = [NSBundle bundleForClass:klass]; 62 | NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:[NSArray arrayWithObject:bundle]]; 63 | [NSManagedObjectModel MR_setDefaultManagedObjectModel:model]; 64 | } 65 | 66 | + (NSString *) defaultStoreName; 67 | { 68 | NSString *defaultName = [[[NSBundle mainBundle] infoDictionary] valueForKey:(id)kCFBundleNameKey]; 69 | if (defaultName == nil) 70 | { 71 | defaultName = kMagicalRecordDefaultStoreFileName; 72 | } 73 | if (![defaultName hasSuffix:@"sqlite"]) 74 | { 75 | defaultName = [defaultName stringByAppendingPathExtension:@"sqlite"]; 76 | } 77 | 78 | return defaultName; 79 | } 80 | 81 | 82 | #pragma mark - initialize 83 | 84 | + (void) initialize; 85 | { 86 | if (self == [MagicalRecord class]) 87 | { 88 | #ifdef MR_SHORTHAND 89 | [self swizzleShorthandMethods]; 90 | #endif 91 | [self setShouldAutoCreateManagedObjectModel:YES]; 92 | [self setShouldAutoCreateDefaultPersistentStoreCoordinator:NO]; 93 | #ifdef DEBUG 94 | [self setShouldDeleteStoreOnModelMismatch:YES]; 95 | #else 96 | [self setShouldDeleteStoreOnModelMismatch:NO]; 97 | #endif 98 | } 99 | } 100 | 101 | @end 102 | 103 | 104 | -------------------------------------------------------------------------------- /shakefun/shakefun/MagicalRecord/CoreData+MagicalRecord.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef NS_BLOCKS_AVAILABLE 3 | #warning MagicalRecord requires blocks 4 | #endif 5 | 6 | #ifdef __OBJC__ 7 | // #if !( __has_feature(objc_arc) && __has_feature(objc_arc_weak) ) 8 | // #error MagicalRecord now requires ARC to be enabled 9 | // #endif 10 | 11 | #import 12 | #import 13 | 14 | #ifdef MR_SHORTHAND 15 | #import "MagicalRecordShorthand.h" 16 | #endif 17 | 18 | #import "MagicalRecord.h" 19 | #import "MagicalRecord+Actions.h" 20 | #import "MagicalRecord+ErrorHandling.h" 21 | #import "MagicalRecord+Options.h" 22 | #import "MagicalRecord+ShorthandSupport.h" 23 | #import "MagicalRecord+Setup.h" 24 | #import "MagicalRecord+iCloud.h" 25 | 26 | #import "NSManagedObject+MagicalRecord.h" 27 | #import "NSManagedObject+MagicalRequests.h" 28 | #import "NSManagedObject+MagicalFinders.h" 29 | #import "NSManagedObject+MagicalAggregation.h" 30 | #import "NSManagedObjectContext+MagicalRecord.h" 31 | #import "NSManagedObjectContext+MagicalObserving.h" 32 | #import "NSManagedObjectContext+MagicalSaves.h" 33 | #import "NSManagedObjectContext+MagicalThreading.h" 34 | #import "NSPersistentStoreCoordinator+MagicalRecord.h" 35 | #import "NSManagedObjectModel+MagicalRecord.h" 36 | #import "NSPersistentStore+MagicalRecord.h" 37 | 38 | #import "MagicalImportFunctions.h" 39 | #import "NSManagedObject+MagicalDataImport.h" 40 | #import "NSNumber+MagicalDataImport.h" 41 | #import "NSObject+MagicalDataImport.h" 42 | #import "NSString+MagicalDataImport.h" 43 | #import "NSAttributeDescription+MagicalDataImport.h" 44 | #import "NSRelationshipDescription+MagicalDataImport.h" 45 | #import "NSEntityDescription+MagicalDataImport.h" 46 | 47 | #endif 48 | 49 | // @see https://github.com/ccgus/fmdb/commit/aef763eeb64e6fa654e7d121f1df4c16a98d9f4f 50 | #define MRDispatchQueueRelease(q) (dispatch_release(q)) 51 | 52 | #if TARGET_OS_IPHONE 53 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000 54 | #undef MRDispatchQueueRelease 55 | #define MRDispatchQueueRelease(q) 56 | #endif 57 | #else 58 | #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 59 | #undef MRDispatchQueueRelease 60 | #define MRDispatchQueueRelease(q) 61 | #endif 62 | #endif 63 | -------------------------------------------------------------------------------- /shakefun/shakefun/PrefixHeader.pch: -------------------------------------------------------------------------------- 1 | // 2 | // PrefixHeader.pch 3 | // shakefun 4 | // 5 | // Created by zm on 15/9/9. 6 | // Copyright (c) 2015年 zm. All rights reserved. 7 | // 8 | 9 | #ifndef shakefun_PrefixHeader_pch 10 | #define shakefun_PrefixHeader_pch 11 | 12 | // Include any system framework and library headers here that should be included in all compilation units. 13 | // You will also need to set the Prefix Header build setting of one or more of your targets to reference this file. 14 | 15 | #ifdef __OBJC__ 16 | #import 17 | #import 18 | #import "CoreData+MagicalRecord.h" 19 | 20 | #endif 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /shakefun/shakefun/SVProgressHUD/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongcup/ZMConfuse/5409be7b310a301aa726a1ee0e3e98c9241090e4/shakefun/shakefun/SVProgressHUD/.DS_Store -------------------------------------------------------------------------------- /shakefun/shakefun/SVProgressHUD/SVProgressHUD.bundle/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongcup/ZMConfuse/5409be7b310a301aa726a1ee0e3e98c9241090e4/shakefun/shakefun/SVProgressHUD/SVProgressHUD.bundle/error.png -------------------------------------------------------------------------------- /shakefun/shakefun/SVProgressHUD/SVProgressHUD.bundle/error@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongcup/ZMConfuse/5409be7b310a301aa726a1ee0e3e98c9241090e4/shakefun/shakefun/SVProgressHUD/SVProgressHUD.bundle/error@2x.png -------------------------------------------------------------------------------- /shakefun/shakefun/SVProgressHUD/SVProgressHUD.bundle/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongcup/ZMConfuse/5409be7b310a301aa726a1ee0e3e98c9241090e4/shakefun/shakefun/SVProgressHUD/SVProgressHUD.bundle/success.png -------------------------------------------------------------------------------- /shakefun/shakefun/SVProgressHUD/SVProgressHUD.bundle/success@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongcup/ZMConfuse/5409be7b310a301aa726a1ee0e3e98c9241090e4/shakefun/shakefun/SVProgressHUD/SVProgressHUD.bundle/success@2x.png -------------------------------------------------------------------------------- /shakefun/shakefun/SVProgressHUD/SVProgressHUD.h: -------------------------------------------------------------------------------- 1 | // 2 | // SVProgressHUD.h 3 | // 4 | // Created by Sam Vermette on 27.03.11. 5 | // Copyright 2011 Sam Vermette. All rights reserved. 6 | // 7 | // https://github.com/samvermette/SVProgressHUD 8 | // 9 | 10 | #import 11 | #import 12 | 13 | enum { 14 | SVProgressHUDMaskTypeNone = 1, // allow user interactions while HUD is displayed 15 | SVProgressHUDMaskTypeClear, // don't allow 16 | SVProgressHUDMaskTypeBlack, // don't allow and dim the UI in the back of the HUD 17 | SVProgressHUDMaskTypeGradient // don't allow and dim the UI with a a-la-alert-view bg gradient 18 | }; 19 | 20 | typedef NSUInteger SVProgressHUDMaskType; 21 | 22 | @interface SVProgressHUD : UIView 23 | 24 | + (void)show; 25 | + (void)showWithStatus:(NSString*)status; 26 | + (void)showWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType; 27 | + (void)showWithMaskType:(SVProgressHUDMaskType)maskType; 28 | 29 | + (void)showSuccessWithStatus:(NSString*)string; 30 | + (void)showSuccessWithStatus:(NSString *)string duration:(NSTimeInterval)duration; 31 | + (void)showErrorWithStatus:(NSString *)string; 32 | + (void)showErrorWithStatus:(NSString *)string duration:(NSTimeInterval)duration; 33 | 34 | + (void)setStatus:(NSString*)string; // change the HUD loading status while it's showing 35 | 36 | + (void)dismiss; // simply dismiss the HUD with a fade+scale out animation 37 | + (void)dismissWithSuccess:(NSString*)successString; // also displays the success icon image 38 | + (void)dismissWithSuccess:(NSString*)successString afterDelay:(NSTimeInterval)seconds; 39 | + (void)dismissWithError:(NSString*)errorString; // also displays the error icon image 40 | + (void)dismissWithError:(NSString*)errorString afterDelay:(NSTimeInterval)seconds; 41 | 42 | + (BOOL)isVisible; 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /shakefun/shakefun/URLEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // URLEntity.h 3 | // shakefun 4 | // 5 | // Created by zm on 15/9/9. 6 | // Copyright (c) 2015年 zm. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | 13 | @interface URLEntity : NSManagedObject 14 | 15 | @property (nonatomic, retain) NSString * fullurl; 16 | @property (nonatomic, retain) NSString * filename; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /shakefun/shakefun/URLEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // URLEntity.m 3 | // shakefun 4 | // 5 | // Created by zm on 15/9/9. 6 | // Copyright (c) 2015年 zm. All rights reserved. 7 | // 8 | 9 | #import "URLEntity.h" 10 | 11 | 12 | @implementation URLEntity 13 | 14 | @dynamic fullurl; 15 | @dynamic filename; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /shakefun/shakefun/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // shakefun 4 | // 5 | // Created by zm on 15/9/9. 6 | // Copyright (c) 2015年 zm. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @property (weak, nonatomic) IBOutlet UIWebView *webViewBrowser; 14 | - (IBAction)buttonNextToggle:(id)sender; 15 | - (IBAction)buttonCollectToggle:(id)sender; 16 | 17 | @end 18 | 19 | @interface NSString (TMNSStringExtensionMethods) 20 | - (NSArray *)componentsSeparatedFromString:(NSString *)fromString toString:(NSString *)toString; 21 | @end 22 | -------------------------------------------------------------------------------- /shakefun/shakefun/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // shakefun 4 | // 5 | // Created by zm on 15/9/9. 6 | // Copyright (c) 2015年 zm. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /shakefun/shakefun/shakefun.xcdatamodeld/.xccurrentversion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | _XCCurrentVersionName 6 | shakefun.xcdatamodel 7 | 8 | 9 | -------------------------------------------------------------------------------- /shakefun/shakefun/shakefun.xcdatamodeld/shakefun.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /shakefun/shakefunTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | zm.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /shakefun/shakefunTests/shakefunTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // shakefunTests.m 3 | // shakefunTests 4 | // 5 | // Created by zm on 15/9/9. 6 | // Copyright (c) 2015年 zm. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface shakefunTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation shakefunTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /zmconfuse.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "#########################################" 3 | echo "File Name:zmconfuse.sh" 4 | echo "Copyright (c) 2015 ZMConfuse" 5 | echo "Email:zm53373581@163.com" 6 | echo "QQGroup:175070221" 7 | echo "Create:2015.10.14" 8 | echo "#######################################" 9 | echo "用户修改区-开始" 10 | #要替换的源代码所在的根目录,该脚本文件与根目录处于同级文件夹 11 | ROOTFOLDER="shakefun" 12 | #要排除的文件夹,例如demo中用到的第三方库AFNetworking等 13 | EXCLUDE_DIR="--exclude-dir=SVProgressHUD --exclude-dir=AFNetworking --exclude-dir=MagicalRecord --exclude-dir=Images.xcassets" 14 | echo "用户修改区-结束" 15 | 16 | #自定义的保留关键字,相当与白名单,添加到该文件中,一行一个,加入该文件的关键字将不被混淆;如工程中自定义的文件夹名称 17 | RESCUSTOM="resCustom.txt" 18 | 19 | #保留关键字文件不可删除 20 | RESERVEDKEYWORDS="./reskeys.txt" 21 | #最终的保留关键字=保留关键字+文件名 22 | RESKEYSALL="./reskeysall.txt" 23 | #提取的所有关键字 24 | SOURCECODEKEYWORDS="./srckeys.txt" 25 | #过滤后,最终要替换的关键字,混淆结束后,不删除,用于bug分析 26 | REPLACEKEYWORDS="./replacekeys.txt" 27 | 28 | #删除已经存在的临时文件 29 | rm -f $SOURCECODEKEYWORDS 30 | rm -f $REPLACEKEYWORDS 31 | rm -f $RESKEYSALL 32 | rm -f temp.res 33 | 34 | #提取文件名列表 35 | rm -f f.list 36 | find $ROOTFOLDER -type f | sed "/\/\./d" >f.list 37 | #根据要排除的文件目录,将文件列表分离 38 | #Exclude=$(echo $EXCLUDE_DIR | sed "s/--exclude-dir\=//g" |sed "s/ $//g" | sed "s/[*.]//g" | sed "s/ /\\\|/g") 39 | Exclude=$(echo $EXCLUDE_DIR | sed "s/--exclude-dir\=//g" |sed "s/ $//g" | sed "s/ /\\\|/g") 40 | #保留文件列表 41 | rm -f f_res.list 42 | cat f.list | grep "$Exclude" >f_res.list 43 | #混淆文件列表 44 | rm -f f_rep.list 45 | cat f.list | grep -v "$Exclude" >f_rep.list 46 | rm -f f.list 47 | #提取文件名 48 | rm -f filter_file.txt 49 | cat f_rep.list | awk -F/ '{print $NF;}'| awk -F. '{print $1;}' | sed "/^$/d" | sort | uniq >filter_file.txt 50 | 51 | #从源代码目录中提取要过滤的函数关键字 52 | rm -f filter_fun.txt 53 | grep -h -r -I "^[-+]" $ROOTFOLDER $EXCLUDE_DIR --include '*.[mh]' |sed "s/[+-]//g"|sed "s/[();,: *\^\/\{]/ /g"|sed "s/[ ]*filter_fun.txt 54 | 55 | #从源代码目录中提取要过滤的属性关键字 56 | rm -f filter_property.txt 57 | grep -r -h -I ^@property $ROOTFOLDER $EXCLUDE_DIR --include '*.[mh]' | sed "s/(.*)/ /g" | sed "s/<.*>//g" |sed "s/[,*;]/ /g" | sed "s/IBOutlet/ /g" |awk '{split($0,s," ");print s[3];}'|sed "/^$/d" | sort |uniq >filter_property.txt 58 | 59 | #从源代码目录中提取要过滤的类关键字 60 | rm -f filter_class.txt 61 | grep -h -r -I "^@interface" $ROOTFOLDER $EXCLUDE_DIR --include '*.[mh]' | sed "s/[:(]/ /" |awk '{split($0,s," ");print s[2];}'|sort|uniq >filter_class.txt 62 | 63 | #从源代码目录中提取要过滤的协议关键字 64 | grep -h -r -I "^@protocol" $ROOTFOLDER $EXCLUDE_DIR --include '*.[mh]'| sed "s/[\<,;].*$//g"|awk '{print $2;}' | sort | uniq >>filter_class.txt 65 | 66 | #合并要过滤的关键字,并重新排序过滤 67 | rm -f $SOURCECODEKEYWORDS 68 | cat filter_fun.txt filter_property.txt filter_class.txt filter_file.txt |sed "/^$/d" | sort | uniq >$SOURCECODEKEYWORDS 69 | rm -f filter_fun.txt 70 | rm -f filter_class.txt 71 | rm -f filter_file.txt 72 | 73 | #自动获取保留字,工程名等 74 | rm -f temp.res 75 | cat `cat f_rep.list | grep project.pbxproj` | grep -w productName | sed "s/;//g"|awk '{print $NF;}'>temp.res 76 | #提取要保留的文件名 77 | cat f_res.list | awk -F/ '{print $NF;}'| awk -F. '{print $1;}' | sed "/^$/d" | sort | uniq >>temp.res 78 | rm -f f_res.list 79 | #合并自定义保留字 80 | #判断自定义保留字文件是否存在,不存在即创建一个空的 81 | if [ ! -f "$RESCUSTOM" ]; then 82 | touch "$RESCUSTOM" 83 | fi 84 | cat $RESERVEDKEYWORDS $RESCUSTOM temp.res | sort |uniq >$RESKEYSALL 85 | rm -f temp.res 86 | 87 | #过滤保留字,将需要混淆的关键字加密后写入文件 88 | rm -f $REPLACEKEYWORDS 89 | cat $SOURCECODEKEYWORDS | 90 | while read line 91 | do 92 | if grep $line $RESKEYSALL 93 | then 94 | echo filter1: $line 95 | else 96 | #使用md5对关键字进行加密 97 | md5 -r -s $line | sed s/\"//g >> $REPLACEKEYWORDS 98 | fi 99 | done 100 | rm -f $SOURCECODEKEYWORDS 101 | 102 | #开始混淆,替换源代码中的关键字为加密后的,防止开头为数字的情况 103 | cat $REPLACEKEYWORDS | 104 | while read line 105 | do 106 | var1=$(echo "$line"|awk '{print "z"$1"m"}') 107 | var2=$(echo "$line"|awk '{print $2}') 108 | rm -f rep.tmp 109 | if grep -r -n -I -w "[_]\{0,1\}$var2" $ROOTFOLDER $EXCLUDE_DIR --include="*.[mhc]" --include="*.mm" --include="*.pch" --include="*.storyboard" --include="*.xib" --include="*.nib" --include="contents" --include="*.pbxproj" >rep.tmp 110 | then 111 | cat rep.tmp | 112 | while read -r l 113 | do 114 | #获取文件路径 115 | v1=$(echo "$l"|cut -d: -f 1 ) 116 | #获取行号 117 | v2=$(echo "$l"|cut -d: -f 2 ) 118 | #获取指定行数据 119 | v3=$(sed -n "$v2"p "$v1") 120 | ##sed自带文件文本替换功能,不符合我们的期望,故放弃使用;有无适合的脚本命令,还希望脚本高手予以指点~ 121 | #sed -i '' ''"$v2"'s/'"$var2"'/'"$var1"'/g' $v1 122 | #特殊字符转义替换,echo中 输出的变量 一定要加双引号!!! 123 | v4=$(echo "$v3" | awk '{gsub(/"/, "\\\"", $0);gsub(//, "\\\>", $0);gsub(/\*/, "\\\*", $0);gsub(/\//, "\\\/", $0);gsub(/\[/, "\\\[", $0);gsub(/\]/, "\\\]", $0);gsub(/\{/, "\\\{", $0);gsub(/\}/, "\\\}", $0);gsub(/\&/, "\\\\\&", $0); print $0;}') 124 | #单词替换 125 | var3=$(./zmreplacewords.run "$v4" "$var2" "$var1") 126 | #整行替换 127 | sed -i '' "$v2"'s/.*/'"$var3"'/g' "$v1" 128 | echo "step2:$l" 129 | done 130 | else 131 | echo "step2:do not find:$var2" 132 | fi 133 | done 134 | rm -f tmp.txt 135 | 136 | #过滤保留字,用于属性设置函数混淆,将需要混淆的关键字加密后写入文件 137 | rm -f repProperty.txt 138 | cat filter_property.txt | 139 | while read line 140 | do 141 | if grep $line $RESKEYSALL 142 | then 143 | echo filter1: $line 144 | else 145 | md5 -r -s $line | sed s/\"//g >> repProperty.txt 146 | fi 147 | done 148 | rm -f filter_property.txt 149 | 150 | #开始混淆,替换属性前带下划线的地方 151 | cat repProperty.txt | 152 | while read line 153 | do 154 | ar=(`echo "$line"|cut -f 1-2 -d " "`) 155 | lastFind=`echo _${ar[1]}` 156 | lastRep=`echo _z${ar[0]}m` 157 | rm -f rep.tmp 158 | if grep -r -n -I -w "$lastFind" $ROOTFOLDER $EXCLUDE_DIR --include="*.[mhc]" --include="*.mm" --include="*.storyboard" --include="*.xib" >rep.tmp 159 | then 160 | cat rep.tmp | 161 | while read l 162 | do 163 | v1=$(echo "$l"|cut -d: -f 1 ) 164 | v2=$(echo "$l"|cut -d: -f 2 ) 165 | sed -i '' ''"$v2"'s/'"$lastFind"'/'"$lastRep"'/g' $v1 166 | echo "step3:"$l 167 | done 168 | else 169 | echo "step3:do not find:"$lastFind 170 | fi 171 | done 172 | rm -f rep.tmp 173 | 174 | #开始混淆,替换属性设置函数 175 | cat repProperty.txt | 176 | while read line 177 | do 178 | ar=(`echo "$line"|cut -f 1-2 -d " "`) 179 | first=`echo ${ar[1]}|cut -c -1| sed "y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/"` 180 | second=`echo ${ar[1]}|cut -c 2-` 181 | lastFind=`echo set$first$second` 182 | lastRep=`echo setZ${ar[0]}m` 183 | rm -f rep.tmp 184 | if grep -r -n -I -w "$lastFind" $ROOTFOLDER $EXCLUDE_DIR --include="*.[mhc]" --include="*.mm" --include="*.storyboard" --include="*.xib" >rep.tmp 185 | then 186 | cat rep.tmp | 187 | while read l 188 | do 189 | v1=$(echo "$l"|cut -d: -f 1 ) 190 | v2=$(echo "$l"|cut -d: -f 2 ) 191 | sed -i '' ''"$v2"'s/'"$lastFind"'/'"$lastRep"'/g' $v1 192 | echo "step3:"$l 193 | done 194 | else 195 | echo "step3:do not find:"$lastFind 196 | fi 197 | done 198 | rm -f rep.tmp 199 | rm -f repProperty.txt 200 | 201 | cat f_rep.list | 202 | while read line 203 | do 204 | echo "old name:"$line 205 | #获取文件名,带后缀 206 | v1=$(echo "$line" | sed "s/\// /g" | awk '{print $NF}') 207 | echo "v1="$v1 208 | #获取文件名,不带后缀 209 | v2=$(echo $v1 | sed "s/\./ /g" | awk '{print $1}') 210 | echo "v2="$v2 211 | if grep -w $v2 $RESKEYSALL 212 | then 213 | echo "find." 214 | else 215 | #获取后缀 216 | v3=$(echo $v1 | sed "s/\./ /g" | awk '{print "."$2}') 217 | echo "v3="$v3 218 | #对不带后缀的文件名加密 219 | v4=$(md5 -q -s "$v2" | sed "s/.*/z&m/g") 220 | echo "v4="$v4 221 | #获取路径 222 | v5=$(echo "$line" | sed "s/"$v1"//g") 223 | echo "v5="$v5 224 | #修改文件名 225 | mv $line $v5$v4$v3 226 | echo "new name:"$v5$v4$v3 227 | fi 228 | done 229 | rm -f f_rep.list 230 | 231 | rm -f $RESKEYSALL 232 | 233 | exit 234 | -------------------------------------------------------------------------------- /zmreplacewords.run: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongcup/ZMConfuse/5409be7b310a301aa726a1ee0e3e98c9241090e4/zmreplacewords.run -------------------------------------------------------------------------------- /zmreplacewords/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kongcup/ZMConfuse/5409be7b310a301aa726a1ee0e3e98c9241090e4/zmreplacewords/.DS_Store -------------------------------------------------------------------------------- /zmreplacewords/zmreplacewords.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 985347B81C71C33800AC6ECE /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 985347B71C71C33800AC6ECE /* main.c */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | 985347B21C71C33800AC6ECE /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 985347B41C71C33800AC6ECE /* zmreplacewords */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = zmreplacewords; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 985347B71C71C33800AC6ECE /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | 985347B11C71C33800AC6ECE /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | 985347AB1C71C33800AC6ECE = { 42 | isa = PBXGroup; 43 | children = ( 44 | 985347B61C71C33800AC6ECE /* zmreplacewords */, 45 | 985347B51C71C33800AC6ECE /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | 985347B51C71C33800AC6ECE /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | 985347B41C71C33800AC6ECE /* zmreplacewords */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | 985347B61C71C33800AC6ECE /* zmreplacewords */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | 985347B71C71C33800AC6ECE /* main.c */, 61 | ); 62 | path = zmreplacewords; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | 985347B31C71C33800AC6ECE /* zmreplacewords */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = 985347BB1C71C33800AC6ECE /* Build configuration list for PBXNativeTarget "zmreplacewords" */; 71 | buildPhases = ( 72 | 985347B01C71C33800AC6ECE /* Sources */, 73 | 985347B11C71C33800AC6ECE /* Frameworks */, 74 | 985347B21C71C33800AC6ECE /* CopyFiles */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = zmreplacewords; 81 | productName = zmreplacewords; 82 | productReference = 985347B41C71C33800AC6ECE /* zmreplacewords */; 83 | productType = "com.apple.product-type.tool"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | 985347AC1C71C33800AC6ECE /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastUpgradeCheck = 0720; 92 | ORGANIZATIONNAME = zm; 93 | TargetAttributes = { 94 | 985347B31C71C33800AC6ECE = { 95 | CreatedOnToolsVersion = 7.2; 96 | }; 97 | }; 98 | }; 99 | buildConfigurationList = 985347AF1C71C33800AC6ECE /* Build configuration list for PBXProject "zmreplacewords" */; 100 | compatibilityVersion = "Xcode 3.2"; 101 | developmentRegion = English; 102 | hasScannedForEncodings = 0; 103 | knownRegions = ( 104 | en, 105 | ); 106 | mainGroup = 985347AB1C71C33800AC6ECE; 107 | productRefGroup = 985347B51C71C33800AC6ECE /* Products */; 108 | projectDirPath = ""; 109 | projectRoot = ""; 110 | targets = ( 111 | 985347B31C71C33800AC6ECE /* zmreplacewords */, 112 | ); 113 | }; 114 | /* End PBXProject section */ 115 | 116 | /* Begin PBXSourcesBuildPhase section */ 117 | 985347B01C71C33800AC6ECE /* Sources */ = { 118 | isa = PBXSourcesBuildPhase; 119 | buildActionMask = 2147483647; 120 | files = ( 121 | 985347B81C71C33800AC6ECE /* main.c in Sources */, 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | /* End PBXSourcesBuildPhase section */ 126 | 127 | /* Begin XCBuildConfiguration section */ 128 | 985347B91C71C33800AC6ECE /* Debug */ = { 129 | isa = XCBuildConfiguration; 130 | buildSettings = { 131 | ALWAYS_SEARCH_USER_PATHS = NO; 132 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 133 | CLANG_CXX_LIBRARY = "libc++"; 134 | CLANG_ENABLE_MODULES = YES; 135 | CLANG_ENABLE_OBJC_ARC = YES; 136 | CLANG_WARN_BOOL_CONVERSION = YES; 137 | CLANG_WARN_CONSTANT_CONVERSION = YES; 138 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 139 | CLANG_WARN_EMPTY_BODY = YES; 140 | CLANG_WARN_ENUM_CONVERSION = YES; 141 | CLANG_WARN_INT_CONVERSION = YES; 142 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 143 | CLANG_WARN_UNREACHABLE_CODE = YES; 144 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 145 | CODE_SIGN_IDENTITY = "-"; 146 | COPY_PHASE_STRIP = NO; 147 | DEBUG_INFORMATION_FORMAT = dwarf; 148 | ENABLE_STRICT_OBJC_MSGSEND = YES; 149 | ENABLE_TESTABILITY = YES; 150 | GCC_C_LANGUAGE_STANDARD = gnu99; 151 | GCC_DYNAMIC_NO_PIC = NO; 152 | GCC_NO_COMMON_BLOCKS = YES; 153 | GCC_OPTIMIZATION_LEVEL = 0; 154 | GCC_PREPROCESSOR_DEFINITIONS = ( 155 | "DEBUG=1", 156 | "$(inherited)", 157 | ); 158 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 159 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 160 | GCC_WARN_UNDECLARED_SELECTOR = YES; 161 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 162 | GCC_WARN_UNUSED_FUNCTION = YES; 163 | GCC_WARN_UNUSED_VARIABLE = YES; 164 | MACOSX_DEPLOYMENT_TARGET = 10.10; 165 | MTL_ENABLE_DEBUG_INFO = YES; 166 | ONLY_ACTIVE_ARCH = YES; 167 | SDKROOT = macosx; 168 | }; 169 | name = Debug; 170 | }; 171 | 985347BA1C71C33800AC6ECE /* Release */ = { 172 | isa = XCBuildConfiguration; 173 | buildSettings = { 174 | ALWAYS_SEARCH_USER_PATHS = NO; 175 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 176 | CLANG_CXX_LIBRARY = "libc++"; 177 | CLANG_ENABLE_MODULES = YES; 178 | CLANG_ENABLE_OBJC_ARC = YES; 179 | CLANG_WARN_BOOL_CONVERSION = YES; 180 | CLANG_WARN_CONSTANT_CONVERSION = YES; 181 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 182 | CLANG_WARN_EMPTY_BODY = YES; 183 | CLANG_WARN_ENUM_CONVERSION = YES; 184 | CLANG_WARN_INT_CONVERSION = YES; 185 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 186 | CLANG_WARN_UNREACHABLE_CODE = YES; 187 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 188 | CODE_SIGN_IDENTITY = "-"; 189 | COPY_PHASE_STRIP = NO; 190 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 191 | ENABLE_NS_ASSERTIONS = NO; 192 | ENABLE_STRICT_OBJC_MSGSEND = YES; 193 | GCC_C_LANGUAGE_STANDARD = gnu99; 194 | GCC_NO_COMMON_BLOCKS = YES; 195 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 196 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 197 | GCC_WARN_UNDECLARED_SELECTOR = YES; 198 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 199 | GCC_WARN_UNUSED_FUNCTION = YES; 200 | GCC_WARN_UNUSED_VARIABLE = YES; 201 | MACOSX_DEPLOYMENT_TARGET = 10.10; 202 | MTL_ENABLE_DEBUG_INFO = NO; 203 | SDKROOT = macosx; 204 | }; 205 | name = Release; 206 | }; 207 | 985347BC1C71C33800AC6ECE /* Debug */ = { 208 | isa = XCBuildConfiguration; 209 | buildSettings = { 210 | PRODUCT_NAME = "$(TARGET_NAME)"; 211 | }; 212 | name = Debug; 213 | }; 214 | 985347BD1C71C33800AC6ECE /* Release */ = { 215 | isa = XCBuildConfiguration; 216 | buildSettings = { 217 | PRODUCT_NAME = "$(TARGET_NAME)"; 218 | }; 219 | name = Release; 220 | }; 221 | /* End XCBuildConfiguration section */ 222 | 223 | /* Begin XCConfigurationList section */ 224 | 985347AF1C71C33800AC6ECE /* Build configuration list for PBXProject "zmreplacewords" */ = { 225 | isa = XCConfigurationList; 226 | buildConfigurations = ( 227 | 985347B91C71C33800AC6ECE /* Debug */, 228 | 985347BA1C71C33800AC6ECE /* Release */, 229 | ); 230 | defaultConfigurationIsVisible = 0; 231 | defaultConfigurationName = Release; 232 | }; 233 | 985347BB1C71C33800AC6ECE /* Build configuration list for PBXNativeTarget "zmreplacewords" */ = { 234 | isa = XCConfigurationList; 235 | buildConfigurations = ( 236 | 985347BC1C71C33800AC6ECE /* Debug */, 237 | 985347BD1C71C33800AC6ECE /* Release */, 238 | ); 239 | defaultConfigurationIsVisible = 0; 240 | }; 241 | /* End XCConfigurationList section */ 242 | }; 243 | rootObject = 985347AC1C71C33800AC6ECE /* Project object */; 244 | } 245 | -------------------------------------------------------------------------------- /zmreplacewords/zmreplacewords.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /zmreplacewords/zmreplacewords/main.c: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // zmreplacewords 4 | // 5 | // Created by zm on 16/2/15. 6 | // Copyright © 2016年 zm. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | char *g_dictWords = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; 14 | 15 | //单词替换 16 | char *zmWordsReplace(char *src, char *old, char *new); 17 | //字符串替换 18 | char *zmStringReplace(char *src, char *old, char *new); 19 | 20 | int main(int argc, const char * argv[]) { 21 | // //打印参数信息 22 | // for (int i = 0; i < argc; ++i) { 23 | // printf("%d:%s\n", i + 1, argv[i]); 24 | // } 25 | if (argc != 4) { 26 | printf("Arguments error.For example:./zmreplacewords \"This is test cases.\" is are\n"); 27 | return 0; 28 | } 29 | 30 | #if 1 31 | char *rawString = (char *)argv[1]; 32 | char *old = (char *)argv[2]; 33 | char *new = (char *)argv[3]; 34 | #else 35 | char *rawString = " 9854747A1BA00B5600A892C8 /* CollectViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 985474791BA00B5600A892C8 /* CollectViewController.m */; };"; 36 | char *old = "CollectViewController"; 37 | char *new = "aaaaaaaaaaaa"; 38 | #endif 39 | 40 | //单词替换 41 | char *newString = zmWordsReplace(rawString, old, new); 42 | char *retString = newString; 43 | 44 | // //特殊字符转义 45 | // //char *specialChar = "<>/*"; 46 | // char *specialChar = ""; 47 | // char spcialCharArrayOld[2] = {""}; 48 | // char spcialCharArrayNew[3] = {"\\*"}; 49 | // for (int j = 0; j < strlen(specialChar); ++j) { 50 | // spcialCharArrayOld[0] = specialChar[j]; 51 | // spcialCharArrayNew[1] = specialChar[j]; 52 | // retString = zmStringReplace(newString, spcialCharArrayOld, spcialCharArrayNew); 53 | // if (retString != newString) { 54 | // if (olds != newString) { 55 | // free(newString); 56 | // } 57 | // newString = retString; 58 | // } 59 | // } 60 | printf("%s\n", retString); 61 | if (rawString != retString) { 62 | free(retString); 63 | } 64 | return 0; 65 | } 66 | 67 | //单词替换,如:This is a good news.==>is -> are ==> This are a good news. 68 | char *zmWordsReplace(char *src, char *old, char *new) 69 | { 70 | int iReplaceCount = 0; 71 | //char *olds = src; 72 | char pre = '\0'; 73 | char aft = '\0'; 74 | char *pFindChar = NULL; 75 | char *pStart = src; 76 | 77 | char *newString = src; 78 | char *newStringTmp = NULL; 79 | //step :首先统计要替换的单词数量 80 | char *pFindWord = strstr(pStart, old); 81 | while (pFindWord != NULL) { 82 | //取出前后字符 83 | if (pFindWord == pStart) { 84 | pre = '\0'; 85 | } 86 | else 87 | { 88 | pre = *(pFindWord - 1); 89 | } 90 | aft = *(pFindWord + strlen(old)); 91 | 92 | pFindChar = strchr(g_dictWords, pre); 93 | if (!pFindChar || pre == '\0') { 94 | pFindChar = strchr(g_dictWords, aft); 95 | if (!pFindChar || aft == '\0') { 96 | //printf("i am here: pPre=%c find=%s pAft=%c\n", pre, find, aft); 97 | iReplaceCount++; 98 | } 99 | } 100 | //查找位置向前移动 101 | pFindWord = strstr(pFindWord + strlen(old), old); 102 | pre = '\0'; 103 | aft = '\0'; 104 | } 105 | 106 | if (iReplaceCount > 0) { 107 | //step :根据统计大小,为新的字符串申请空间 108 | unsigned long iNewLenght = strlen(src) + (strlen(new) - strlen(old)) * iReplaceCount; 109 | //printf("iReplaceCount is %d totol lenth = %lu\n", iReplaceCount, iNewLenght); 110 | newString = (char *)calloc(iNewLenght, 1); 111 | newStringTmp = newString; 112 | 113 | //step :根据原始字符串,填充新的字符串 114 | pStart = src; 115 | pFindWord = strstr(pStart, old); 116 | while (pFindWord != NULL) { 117 | //取出前后字符 118 | if (pFindWord == pStart) { 119 | pre = '\0'; 120 | } 121 | else 122 | { 123 | pre = *(pFindWord - 1); 124 | } 125 | aft = *(pFindWord + strlen(old)); 126 | 127 | pFindChar = strchr(g_dictWords, pre); 128 | if (!pFindChar || pre == '\0') { 129 | pFindChar = strchr(g_dictWords, aft); 130 | if (!pFindChar || aft == '\0') { 131 | //拷贝找到的字符串之前的字符串 132 | strncpy(newStringTmp, pStart, pFindWord - pStart); 133 | //向新自负串中追加替换后的字符串 134 | strcat(newStringTmp, new); 135 | //printf("i am here: pPre=%c find=%s pAft=%c newString=%s\n", pre, pFindWord, aft, newStringTmp); 136 | //开始位置向前移动 137 | pStart = pFindWord + strlen(old); 138 | newStringTmp = newString + strlen(newString); 139 | } 140 | } 141 | //查找位置向前移动 142 | pFindWord = strstr(pFindWord + strlen(old), old); 143 | pre = '\0'; 144 | aft = '\0'; 145 | } 146 | 147 | //step :追加最后一部分字符串 148 | if (pStart != src) { 149 | strcat(newString, pStart); 150 | } 151 | 152 | //printf("last string is :%s\n", newString); 153 | //free(newString); 154 | } 155 | 156 | return newString; 157 | } 158 | 159 | //字符串替换,如:This is a good news.==>is -> are ==> Thare are a good news. 160 | char *zmStringReplace(char *src, char *old, char *new) 161 | { 162 | int iReplaceCount = 0; 163 | char *pStart = src; 164 | 165 | char *newString = src; 166 | char *newStringTmp = NULL; 167 | //step :首先统计要替换的字符串数量 168 | char *pFindWord = strstr(pStart, old); 169 | while (pFindWord != NULL) { 170 | iReplaceCount++; 171 | //查找位置向前移动 172 | pFindWord = strstr(pFindWord + strlen(old), old); 173 | 174 | } 175 | 176 | if (iReplaceCount > 0) { 177 | //step :根据统计大小,为新的字符串申请空间 178 | unsigned long iNewLenght = strlen(src) + (strlen(new) - strlen(old)) * iReplaceCount; 179 | //printf("iReplaceCount is %d totol lenth = %lu\n", iReplaceCount, iNewLenght); 180 | newString = (char *)calloc(iNewLenght, 1); 181 | newStringTmp = newString; 182 | 183 | //step :根据原始字符串,填充新的字符串 184 | pStart = src; 185 | pFindWord = strstr(pStart, old); 186 | while (pFindWord != NULL) { 187 | //拷贝找到的字符串之前的字符串 188 | strncpy(newStringTmp, pStart, pFindWord - pStart); 189 | //向新自负串中追加替换后的字符串 190 | strcat(newStringTmp, new); 191 | //printf("i am here: pPre=%c find=%s pAft=%c newString=%s\n", pre, pFindWord, aft, newStringTmp); 192 | //开始位置向前移动 193 | pStart = pFindWord + strlen(old); 194 | newStringTmp = newString + strlen(newString); 195 | 196 | //查找位置向前移动 197 | pFindWord = strstr(pFindWord + strlen(old), old); 198 | } 199 | 200 | //step :追加最后一部分字符串 201 | if (pStart != src) { 202 | strcat(newString, pStart); 203 | } 204 | 205 | //printf("last string is :%s\n", newString); 206 | //free(newString); 207 | } 208 | 209 | return newString; 210 | } 211 | --------------------------------------------------------------------------------