├── .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 | 
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/[ ]*"|awk '{split($0,b," ");print b[2];}'| sort|uniq |sed "/^$/d"|sed "/^init/d" >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);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 |
--------------------------------------------------------------------------------