appjam 0.1.8.8 → 0.1.8.9
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +22 -62
- data/lib/appjam/generators/gist.yml +1 -1
- data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/project.pbxproj +1166 -482
- data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/project.xcworkspace/xcuserdata/eiffel.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/EiffelApplication-Prefix.pch.tt +26 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/AwesomeMenu.h +52 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/AwesomeMenu.m +412 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/AwesomeMenuItem.h +44 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/AwesomeMenuItem.m +97 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-addbutton-highlighted.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-addbutton-highlighted@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-addbutton.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-addbutton@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-menuitem-highlighted.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-menuitem-highlighted@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-menuitem.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-menuitem@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-plus-highlighted.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-plus-highlighted@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-plus.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-plus@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-star.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-star@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/CMPopTipView/CMPopTipView.h +167 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/CMPopTipView/CMPopTipView.m +639 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/FXLabel/FXLabel.h +97 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/FXLabel/FXLabel.m +1080 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MBProgressHUD/MBProgressHUD.h +451 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MBProgressHUD/MBProgressHUD.m +865 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/FacingView.h +42 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/FacingView.m +56 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/FoldView.h +90 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/FoldView.m +316 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/MultiFoldView.h +104 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/MultiFoldView.m +516 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldConstants.h +49 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldNavigationController.h +18 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldNavigationController.m +88 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldResources.bundle/swipe_guide_left.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldResources.bundle/swipe_guide_left@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldResources.bundle/swipe_guide_right.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldResources.bundle/swipe_guide_right@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldSwipeHintView.h +25 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldSwipeHintView.m +76 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldView.h +131 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldView.m +941 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/Resources/swipe_guide.psd +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/Resources/swipe_guide2.psd +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/ShadowView.h +46 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/ShadowView.m +82 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/TouchThroughUIView.h +39 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/TouchThroughUIView.m +72 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/UIView+Screenshot.h +42 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/UIView+Screenshot.m +100 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/NSBubbleData.h +34 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/NSBubbleData.m +140 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleHeaderTableViewCell.h +17 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleHeaderTableViewCell.m +57 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableView.h +30 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableView.m +233 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableViewCell.h +19 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableViewCell.m +122 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableViewDataSource.h +24 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTypingTableViewCell.h +20 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTypingTableViewCell.m +56 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/bubbleMine.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/bubbleMine@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/bubbleSomeone.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/bubbleSomeone@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/missingAvatar.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/missingAvatar@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/typingMine.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/typingMine@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/typingSomeone.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/typingSomeone@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIGlossyButton/UIGlossyButton.h +124 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIGlossyButton/UIGlossyButton.m +545 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIGlossyButton/UIView+LayerEffects.h +22 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIGlossyButton/UIView+LayerEffects.m +32 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFIncrementalStore/AFIncrementalStore.h +344 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFIncrementalStore/AFIncrementalStore.m +848 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFIncrementalStore/AFRESTClient.h +135 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFIncrementalStore/AFRESTClient.m +441 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/InflectorKit/NSString+InflectorKit.h +40 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/InflectorKit/NSString+InflectorKit.m +36 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/InflectorKit/TTTStringInflector.h +76 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/InflectorKit/TTTStringInflector.m +270 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/MKAnnotationView+WebCache.h +95 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/MKAnnotationView+WebCache.m +78 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDImageCache.h +144 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDImageCache.m +311 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageCompat.h +40 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageCompat.m +54 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDecoder.h +18 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDecoder.m +70 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDownloader.h +102 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDownloader.m +226 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDownloaderOperation.h +25 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDownloaderOperation.m +339 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageManager.h +167 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageManager.m +244 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageOperation.h +15 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImagePrefetcher.h +58 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImagePrefetcher.m +127 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/UIButton+WebCache.h +173 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/UIButton+WebCache.m +129 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/UIImageView+WebCache.h +140 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/UIImageView+WebCache.m +84 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/CPAnimationProgram.h +28 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/CPAnimationSequence.h +28 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/CPAnimationStep.h +49 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/private/CPAnimationProgram.m +100 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/private/CPAnimationSequence.m +85 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/private/CPAnimationStep.m +122 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaAsyncSocket/GCDAsyncSocket.h +1074 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaAsyncSocket/GCDAsyncSocket.m +7430 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDData.h +14 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDData.m +158 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDNumber.h +12 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDNumber.m +88 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDRange.h +56 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDRange.m +104 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPAuthenticationRequest.h +45 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPAuthenticationRequest.m +195 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPConnection.h +119 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPConnection.m +2708 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPLogging.h +136 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPMessage.h +48 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPMessage.m +113 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPResponse.h +149 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPServer.h +205 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPServer.m +772 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartFormDataParser.h +65 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartFormDataParser.m +529 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartMessageHeader.h +33 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartMessageHeader.m +86 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartMessageHeaderField.h +23 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartMessageHeaderField.m +211 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPAsyncFileResponse.h +75 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPAsyncFileResponse.m +405 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPDataResponse.h +13 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPDataResponse.m +79 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPDynamicFileResponse.h +52 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPDynamicFileResponse.m +292 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPErrorResponse.h +9 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPErrorResponse.m +38 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPFileResponse.h +25 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPFileResponse.m +237 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPRedirectResponse.h +12 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPRedirectResponse.m +73 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/WebSocket.h +105 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/WebSocket.m +791 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DAVConnection.h +7 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DAVConnection.m +160 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DAVResponse.h +11 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DAVResponse.m +372 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DELETEResponse.h +7 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DELETEResponse.m +49 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/PUTResponse.h +8 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/PUTResponse.m +69 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/TFHpple.h +54 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/TFHpple.m +102 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/TFHppleElement.h +103 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/TFHppleElement.m +200 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/XPathQuery.h +10 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/XPathQuery.m +197 -0
- data/lib/appjam/version.rb +1 -1
- metadata +164 -3
@@ -0,0 +1,135 @@
|
|
1
|
+
// AFRESTClient.h
|
2
|
+
//
|
3
|
+
// Copyright (c) 2012 Mattt Thompson (http://mattt.me)
|
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 "AFHTTPClient.h"
|
24
|
+
#import "AFHTTPRequestOperation.h"
|
25
|
+
#import "AFIncrementalStore.h"
|
26
|
+
#import "TTTStringInflector.h"
|
27
|
+
|
28
|
+
@protocol AFPaginator;
|
29
|
+
|
30
|
+
/**
|
31
|
+
`AFRESTClient` is a subclass of `AFHTTPClient` that implements the `AFIncrementalStoreHTTPClient` protocol in a way that follows the conventions of a RESTful web service.
|
32
|
+
*/
|
33
|
+
@interface AFRESTClient : AFHTTPClient <AFIncrementalStoreHTTPClient>
|
34
|
+
|
35
|
+
/**
|
36
|
+
|
37
|
+
*/
|
38
|
+
@property (nonatomic, strong) id <AFPaginator> paginator;
|
39
|
+
|
40
|
+
/**
|
41
|
+
|
42
|
+
*/
|
43
|
+
@property (readonly, nonatomic, strong) TTTStringInflector *inflector;
|
44
|
+
|
45
|
+
///------------------------
|
46
|
+
/// @name Determining Paths
|
47
|
+
///------------------------
|
48
|
+
|
49
|
+
/**
|
50
|
+
Returns the request path for a collection of resources of the specified entity. By default, this returns an imprecise pluralization of the entity name.
|
51
|
+
|
52
|
+
@discussion The return value of this method is used as the `path` parameter in other `AFHTTPClient` methods.
|
53
|
+
|
54
|
+
@param entity The entity used to determine the resources path.
|
55
|
+
|
56
|
+
@return An `NSString` representing the request path.
|
57
|
+
*/
|
58
|
+
- (NSString *)pathForEntity:(NSEntityDescription *)entity;
|
59
|
+
|
60
|
+
/**
|
61
|
+
Returns the request path for the resource of a particular managed object. By default, this returns an imprecise pluralization of the entity name, with the additional path component of the resource identifier corresponding to the managed object.
|
62
|
+
|
63
|
+
@discussion The return value of this method is used as the `path` parameter in other `AFHTTPClient` methods.
|
64
|
+
|
65
|
+
@param object The managed object used to determine the resource path.
|
66
|
+
|
67
|
+
@return An `NSString` representing the request path.
|
68
|
+
*/
|
69
|
+
- (NSString *)pathForObject:(NSManagedObject *)object;
|
70
|
+
|
71
|
+
/**
|
72
|
+
Returns the request path for the resource of a particular managed object. By default, this returns an imprecise pluralization of the entity name, with the additional path component of either an imprecise pluralization of the relationship destination entity name if the relationship is to-many, or the relationship destination entity name if to-one.
|
73
|
+
|
74
|
+
@discussion The return value of this method is used as the `path` parameter in other `AFHTTPClient` methods.
|
75
|
+
|
76
|
+
@param relationship The relationship used to determine the resource path
|
77
|
+
@param object The managed object used to determine the resource path.
|
78
|
+
|
79
|
+
@return An `NSString` representing the request path.
|
80
|
+
*/
|
81
|
+
- (NSString *)pathForRelationship:(NSRelationshipDescription *)relationship
|
82
|
+
forObject:(NSManagedObject *)object;
|
83
|
+
|
84
|
+
@end
|
85
|
+
|
86
|
+
///----------------
|
87
|
+
/// @name Functions
|
88
|
+
///----------------
|
89
|
+
|
90
|
+
/**
|
91
|
+
|
92
|
+
*/
|
93
|
+
extern NSDate * AFDateFromISO8601String(NSString *ISO8601String);
|
94
|
+
|
95
|
+
///-----------------
|
96
|
+
/// @name Pagination
|
97
|
+
///-----------------
|
98
|
+
|
99
|
+
/**
|
100
|
+
|
101
|
+
*/
|
102
|
+
@protocol AFPaginator <NSObject>
|
103
|
+
- (NSDictionary *)parametersForFetchRequest:(NSFetchRequest *)fetchRequest;
|
104
|
+
@end
|
105
|
+
|
106
|
+
/**
|
107
|
+
|
108
|
+
*/
|
109
|
+
@interface AFLimitAndOffsetPaginator : NSObject <AFPaginator>
|
110
|
+
|
111
|
+
@property (readonly, nonatomic, copy) NSString *limitParameter;
|
112
|
+
@property (readonly, nonatomic, copy) NSString *offsetParameter;
|
113
|
+
|
114
|
+
+ (instancetype)paginatorWithLimitParameter:(NSString *)limitParameterName
|
115
|
+
offsetParameter:(NSString *)offsetParameterName;
|
116
|
+
@end
|
117
|
+
|
118
|
+
/**
|
119
|
+
|
120
|
+
*/
|
121
|
+
@interface AFPageAndPerPagePaginator : NSObject <AFPaginator>
|
122
|
+
|
123
|
+
@property (readonly, nonatomic, copy) NSString *pageParameter;
|
124
|
+
@property (readonly, nonatomic, copy) NSString *perPageParameter;
|
125
|
+
|
126
|
+
+ (instancetype)paginatorWithPageParameter:(NSString *)pageParameterName
|
127
|
+
perPageParameter:(NSString *)perPageParameterName;
|
128
|
+
@end
|
129
|
+
|
130
|
+
/**
|
131
|
+
|
132
|
+
*/
|
133
|
+
@interface AFBlockPaginator : NSObject <AFPaginator>
|
134
|
+
+ (instancetype)paginatorWithBlock:(NSDictionary * (^)(NSFetchRequest *fetchRequest))block;
|
135
|
+
@end
|
@@ -0,0 +1,441 @@
|
|
1
|
+
// AFRESTClient.m
|
2
|
+
//
|
3
|
+
// Copyright (c) 2012 Mattt Thompson (http://mattt.me)
|
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 "AFRESTClient.h"
|
24
|
+
#include <time.h>
|
25
|
+
#include <xlocale.h>
|
26
|
+
|
27
|
+
#define AF_ISO8601_MAX_LENGTH 25
|
28
|
+
|
29
|
+
// Adopted from SSToolkit NSDate+SSToolkitAdditions
|
30
|
+
// Created by Sam Soffes
|
31
|
+
// Copyright (c) 2008-2012 Sam Soffes
|
32
|
+
// https://github.com/soffes/sstoolkit/
|
33
|
+
NSDate * AFDateFromISO8601String(NSString *ISO8601String) {
|
34
|
+
if (!ISO8601String) {
|
35
|
+
return nil;
|
36
|
+
}
|
37
|
+
|
38
|
+
const char *str = [ISO8601String cStringUsingEncoding:NSUTF8StringEncoding];
|
39
|
+
char newStr[AF_ISO8601_MAX_LENGTH];
|
40
|
+
bzero(newStr, AF_ISO8601_MAX_LENGTH);
|
41
|
+
|
42
|
+
size_t len = strlen(str);
|
43
|
+
if (len == 0) {
|
44
|
+
return nil;
|
45
|
+
}
|
46
|
+
|
47
|
+
// UTC dates ending with Z
|
48
|
+
if (len == 20 && str[len - 1] == 'Z') {
|
49
|
+
memcpy(newStr, str, len - 1);
|
50
|
+
strncpy(newStr + len - 1, "+0000\0", 6);
|
51
|
+
}
|
52
|
+
|
53
|
+
// Timezone includes a semicolon (not supported by strptime)
|
54
|
+
else if (len == 25 && str[22] == ':') {
|
55
|
+
memcpy(newStr, str, 22);
|
56
|
+
memcpy(newStr + 22, str + 23, 2);
|
57
|
+
}
|
58
|
+
|
59
|
+
// Fallback: date was already well-formatted OR any other case (bad-formatted)
|
60
|
+
else {
|
61
|
+
memcpy(newStr, str, len > AF_ISO8601_MAX_LENGTH - 1 ? AF_ISO8601_MAX_LENGTH - 1 : len);
|
62
|
+
}
|
63
|
+
|
64
|
+
// Add null terminator
|
65
|
+
newStr[sizeof(newStr) - 1] = 0;
|
66
|
+
|
67
|
+
struct tm tm = {
|
68
|
+
.tm_sec = 0,
|
69
|
+
.tm_min = 0,
|
70
|
+
.tm_hour = 0,
|
71
|
+
.tm_mday = 0,
|
72
|
+
.tm_mon = 0,
|
73
|
+
.tm_year = 0,
|
74
|
+
.tm_wday = 0,
|
75
|
+
.tm_yday = 0,
|
76
|
+
.tm_isdst = -1,
|
77
|
+
};
|
78
|
+
|
79
|
+
strptime_l(newStr, "%FT%T%z", &tm, NULL);
|
80
|
+
|
81
|
+
return [NSDate dateWithTimeIntervalSince1970:mktime(&tm)];
|
82
|
+
}
|
83
|
+
|
84
|
+
static NSString * AFQueryByAppendingParameters(NSString *query, NSDictionary *parameters) {
|
85
|
+
static NSCharacterSet *_componentSeparatorCharacterSet = nil;
|
86
|
+
static dispatch_once_t onceToken;
|
87
|
+
dispatch_once(&onceToken, ^{
|
88
|
+
_componentSeparatorCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@"&"];
|
89
|
+
});
|
90
|
+
|
91
|
+
if (!parameters || [parameters count] == 0) {
|
92
|
+
return query;
|
93
|
+
}
|
94
|
+
|
95
|
+
query = query ? [[query stringByTrimmingCharactersInSet:_componentSeparatorCharacterSet] stringByAppendingString:@"&"] : @"";
|
96
|
+
|
97
|
+
NSMutableArray *mutablePairs = [NSMutableArray arrayWithCapacity:[parameters count]];
|
98
|
+
[parameters enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL *stop) {
|
99
|
+
[mutablePairs addObject:[NSString stringWithFormat:@"%@=%@", field, value]];
|
100
|
+
}];
|
101
|
+
|
102
|
+
return [query stringByAppendingString:[mutablePairs componentsJoinedByString:@"&"]];
|
103
|
+
}
|
104
|
+
|
105
|
+
@interface AFRESTClient ()
|
106
|
+
@property (readwrite, nonatomic, strong) TTTStringInflector *inflector;
|
107
|
+
@end
|
108
|
+
|
109
|
+
@implementation AFRESTClient
|
110
|
+
@synthesize paginator = _paginator;
|
111
|
+
@synthesize inflector = _inflector;
|
112
|
+
|
113
|
+
- (id)initWithBaseURL:(NSURL *)url {
|
114
|
+
self = [super initWithBaseURL:url];
|
115
|
+
if (!self) {
|
116
|
+
return nil;
|
117
|
+
}
|
118
|
+
|
119
|
+
self.inflector = [TTTStringInflector defaultInflector];
|
120
|
+
|
121
|
+
return self;
|
122
|
+
}
|
123
|
+
|
124
|
+
#pragma mark -
|
125
|
+
|
126
|
+
- (NSString *)pathForEntity:(NSEntityDescription *)entity {
|
127
|
+
return [self.inflector pluralize:[entity.name lowercaseString]];
|
128
|
+
}
|
129
|
+
|
130
|
+
- (NSString *)pathForObject:(NSManagedObject *)object {
|
131
|
+
NSString *resourceIdentifier = AFResourceIdentifierFromReferenceObject([(NSIncrementalStore *)object.objectID.persistentStore referenceObjectForObjectID:object.objectID]);
|
132
|
+
return [[self pathForEntity:object.entity] stringByAppendingPathComponent:[resourceIdentifier lastPathComponent]];
|
133
|
+
}
|
134
|
+
|
135
|
+
- (NSString *)pathForRelationship:(NSRelationshipDescription *)relationship
|
136
|
+
forObject:(NSManagedObject *)object
|
137
|
+
{
|
138
|
+
return [[self pathForObject:object] stringByAppendingPathComponent:relationship.name];
|
139
|
+
}
|
140
|
+
|
141
|
+
#pragma mark - AFIncrementalStoreHTTPClient
|
142
|
+
|
143
|
+
#pragma mark Read Methods
|
144
|
+
|
145
|
+
- (id)representationOrArrayOfRepresentationsOfEntity:(NSEntityDescription *)entity
|
146
|
+
fromResponseObject:(id)responseObject
|
147
|
+
{
|
148
|
+
if ([responseObject isKindOfClass:[NSArray class]]) {
|
149
|
+
return responseObject;
|
150
|
+
} else if ([responseObject isKindOfClass:[NSDictionary class]]) {
|
151
|
+
id value = nil;
|
152
|
+
|
153
|
+
value = [responseObject valueForKey:[entity.name lowercaseString]];
|
154
|
+
if (value && [value isKindOfClass:[NSDictionary class]]) {
|
155
|
+
return value;
|
156
|
+
}
|
157
|
+
|
158
|
+
value = [responseObject valueForKey:[self.inflector pluralize:[entity.name lowercaseString]]];
|
159
|
+
if (value && [value isKindOfClass:[NSArray class]]) {
|
160
|
+
return value;
|
161
|
+
}
|
162
|
+
|
163
|
+
return responseObject;
|
164
|
+
}
|
165
|
+
|
166
|
+
return responseObject;
|
167
|
+
}
|
168
|
+
|
169
|
+
- (NSDictionary *)representationsForRelationshipsFromRepresentation:(NSDictionary *)representation
|
170
|
+
ofEntity:(NSEntityDescription *)entity
|
171
|
+
fromResponse:(NSHTTPURLResponse *)response
|
172
|
+
{
|
173
|
+
NSMutableDictionary *mutableRelationshipRepresentations = [NSMutableDictionary dictionaryWithCapacity:[entity.relationshipsByName count]];
|
174
|
+
[entity.relationshipsByName enumerateKeysAndObjectsUsingBlock:^(id name, id relationship, BOOL *stop) {
|
175
|
+
id value = [representation valueForKey:name];
|
176
|
+
if (value) {
|
177
|
+
if ([relationship isToMany]) {
|
178
|
+
NSArray *arrayOfRelationshipRepresentations = nil;
|
179
|
+
if ([value isKindOfClass:[NSArray class]]) {
|
180
|
+
arrayOfRelationshipRepresentations = value;
|
181
|
+
} else {
|
182
|
+
arrayOfRelationshipRepresentations = [NSArray arrayWithObject:value];
|
183
|
+
}
|
184
|
+
|
185
|
+
[mutableRelationshipRepresentations setValue:arrayOfRelationshipRepresentations forKey:name];
|
186
|
+
} else {
|
187
|
+
[mutableRelationshipRepresentations setValue:value forKey:name];
|
188
|
+
}
|
189
|
+
}
|
190
|
+
}];
|
191
|
+
|
192
|
+
return mutableRelationshipRepresentations;
|
193
|
+
}
|
194
|
+
|
195
|
+
- (NSString *)resourceIdentifierForRepresentation:(NSDictionary *)representation
|
196
|
+
ofEntity:(NSEntityDescription *)entity
|
197
|
+
fromResponse:(NSHTTPURLResponse *)response
|
198
|
+
{
|
199
|
+
static NSArray *_candidateKeys = nil;
|
200
|
+
static dispatch_once_t onceToken;
|
201
|
+
dispatch_once(&onceToken, ^{
|
202
|
+
_candidateKeys = [[NSArray alloc] initWithObjects:@"id", @"_id", @"identifier", @"url", @"URL", nil];
|
203
|
+
});
|
204
|
+
|
205
|
+
NSString *key = [[representation allKeys] firstObjectCommonWithArray:_candidateKeys];
|
206
|
+
if (key) {
|
207
|
+
id value = [representation valueForKey:key];
|
208
|
+
if (value) {
|
209
|
+
return [value description];
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
return nil;
|
214
|
+
}
|
215
|
+
|
216
|
+
- (NSDictionary *)attributesForRepresentation:(NSDictionary *)representation
|
217
|
+
ofEntity:(NSEntityDescription *)entity
|
218
|
+
fromResponse:(NSHTTPURLResponse *)response
|
219
|
+
{
|
220
|
+
if ([representation isEqual:[NSNull null]]) {
|
221
|
+
return nil;
|
222
|
+
}
|
223
|
+
|
224
|
+
NSMutableDictionary *mutableAttributes = [representation mutableCopy];
|
225
|
+
@autoreleasepool {
|
226
|
+
NSMutableSet *mutableKeys = [NSMutableSet setWithArray:[representation allKeys]];
|
227
|
+
[mutableKeys minusSet:[NSSet setWithArray:[[entity attributesByName] allKeys]]];
|
228
|
+
[mutableAttributes removeObjectsForKeys:[mutableKeys allObjects]];
|
229
|
+
|
230
|
+
NSSet *keysWithNestedValues = [mutableAttributes keysOfEntriesPassingTest:^BOOL(id key, id obj, BOOL *stop) {
|
231
|
+
return [obj isKindOfClass:[NSArray class]] || [obj isKindOfClass:[NSDictionary class]];
|
232
|
+
}];
|
233
|
+
[mutableAttributes removeObjectsForKeys:[keysWithNestedValues allObjects]];
|
234
|
+
}
|
235
|
+
|
236
|
+
[[entity attributesByName] enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
|
237
|
+
if ([(NSAttributeDescription *)obj attributeType] == NSDateAttributeType) {
|
238
|
+
id value = [mutableAttributes valueForKey:key];
|
239
|
+
if (value && ![value isEqual:[NSNull null]]) {
|
240
|
+
[mutableAttributes setValue:AFDateFromISO8601String(value) forKey:key];
|
241
|
+
}
|
242
|
+
}
|
243
|
+
}];
|
244
|
+
|
245
|
+
return mutableAttributes;
|
246
|
+
}
|
247
|
+
|
248
|
+
- (NSMutableURLRequest *)requestForFetchRequest:(NSFetchRequest *)fetchRequest
|
249
|
+
withContext:(NSManagedObjectContext *)context
|
250
|
+
{
|
251
|
+
NSMutableDictionary *mutableParameters = [NSMutableDictionary dictionary];
|
252
|
+
if (self.paginator) {
|
253
|
+
[mutableParameters addEntriesFromDictionary:[self.paginator parametersForFetchRequest:fetchRequest]];
|
254
|
+
}
|
255
|
+
|
256
|
+
NSMutableURLRequest *mutableRequest = [self requestWithMethod:@"GET" path:[self pathForEntity:fetchRequest.entity] parameters:[mutableParameters count] == 0 ? nil : mutableParameters];
|
257
|
+
|
258
|
+
return mutableRequest;
|
259
|
+
}
|
260
|
+
|
261
|
+
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
|
262
|
+
pathForObjectWithID:(NSManagedObjectID *)objectID
|
263
|
+
withContext:(NSManagedObjectContext *)context
|
264
|
+
{
|
265
|
+
NSManagedObject *object = [context objectWithID:objectID];
|
266
|
+
return [self requestWithMethod:method path:[self pathForObject:object] parameters:nil];
|
267
|
+
}
|
268
|
+
|
269
|
+
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
|
270
|
+
pathForRelationship:(NSRelationshipDescription *)relationship
|
271
|
+
forObjectWithID:(NSManagedObjectID *)objectID
|
272
|
+
withContext:(NSManagedObjectContext *)context
|
273
|
+
{
|
274
|
+
NSManagedObject *object = [context objectWithID:objectID];
|
275
|
+
return [self requestWithMethod:method path:[self pathForRelationship:relationship forObject:object] parameters:nil];
|
276
|
+
}
|
277
|
+
|
278
|
+
- (BOOL)shouldFetchRemoteValuesForRelationship:(NSRelationshipDescription *)relationship
|
279
|
+
forObjectWithID:(NSManagedObjectID *)objectID
|
280
|
+
inManagedObjectContext:(NSManagedObjectContext *)context
|
281
|
+
{
|
282
|
+
return [relationship isToMany] || ![relationship inverseRelationship];
|
283
|
+
}
|
284
|
+
|
285
|
+
#pragma mark Write Methods
|
286
|
+
|
287
|
+
- (NSDictionary *)representationOfAttributes:(NSDictionary *)attributes
|
288
|
+
ofManagedObject:(NSManagedObject *)managedObject
|
289
|
+
{
|
290
|
+
NSMutableDictionary *mutableAttributes = [attributes mutableCopy];
|
291
|
+
[attributes enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
|
292
|
+
// Use NSString representation of NSDate to avoid NSInvalidArgumentException when serializing JSON
|
293
|
+
if ([obj isKindOfClass:[NSDate class]]) {
|
294
|
+
[mutableAttributes setObject:[obj description] forKey:key];
|
295
|
+
}
|
296
|
+
}];
|
297
|
+
|
298
|
+
return mutableAttributes;
|
299
|
+
}
|
300
|
+
|
301
|
+
- (NSMutableURLRequest *)requestForInsertedObject:(NSManagedObject *)insertedObject {
|
302
|
+
return [self requestWithMethod:@"POST" path:[self pathForEntity:insertedObject.entity] parameters:[self representationOfAttributes:[insertedObject dictionaryWithValuesForKeys:[insertedObject.entity.attributesByName allKeys]] ofManagedObject:insertedObject]];
|
303
|
+
}
|
304
|
+
|
305
|
+
- (NSMutableURLRequest *)requestForUpdatedObject:(NSManagedObject *)updatedObject {
|
306
|
+
NSMutableSet *mutableChangedAttributeKeys = [NSMutableSet setWithArray:[[updatedObject changedValues] allKeys]];
|
307
|
+
[mutableChangedAttributeKeys intersectSet:[NSSet setWithArray:[updatedObject.entity.attributesByName allKeys]]];
|
308
|
+
|
309
|
+
return [self requestWithMethod:@"PUT" path:[self pathForObject:updatedObject] parameters:[self representationOfAttributes:[[updatedObject changedValues] dictionaryWithValuesForKeys:[mutableChangedAttributeKeys allObjects]] ofManagedObject:updatedObject]];
|
310
|
+
}
|
311
|
+
|
312
|
+
- (NSMutableURLRequest *)requestForDeletedObject:(NSManagedObject *)deletedObject {
|
313
|
+
return [self requestWithMethod:@"DELETE" path:[self pathForObject:deletedObject] parameters:nil];
|
314
|
+
}
|
315
|
+
|
316
|
+
#pragma mark - AFHTTPClient
|
317
|
+
|
318
|
+
- (void)enqueueBatchOfHTTPRequestOperations:(NSArray *)operations
|
319
|
+
progressBlock:(void (^)(NSUInteger, NSUInteger))progressBlock
|
320
|
+
completionBlock:(void (^)(NSArray *))completionBlock
|
321
|
+
{
|
322
|
+
for (AFHTTPRequestOperation *operation in operations) {
|
323
|
+
if ([operation isKindOfClass:[AFHTTPRequestOperation class]]) {
|
324
|
+
if (!operation.successCallbackQueue) {
|
325
|
+
operation.successCallbackQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
|
326
|
+
}
|
327
|
+
|
328
|
+
if (!operation.failureCallbackQueue) {
|
329
|
+
operation.failureCallbackQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
|
330
|
+
}
|
331
|
+
}
|
332
|
+
}
|
333
|
+
|
334
|
+
[super enqueueBatchOfHTTPRequestOperations:operations progressBlock:progressBlock completionBlock:completionBlock];
|
335
|
+
}
|
336
|
+
|
337
|
+
@end
|
338
|
+
|
339
|
+
#pragma mark -
|
340
|
+
|
341
|
+
@interface AFLimitAndOffsetPaginator ()
|
342
|
+
@property (readwrite, nonatomic, copy) NSString *limitParameter;
|
343
|
+
@property (readwrite, nonatomic, copy) NSString *offsetParameter;
|
344
|
+
@end
|
345
|
+
|
346
|
+
@implementation AFLimitAndOffsetPaginator
|
347
|
+
|
348
|
+
+ (instancetype)paginatorWithLimitParameter:(NSString *)limitParameterName
|
349
|
+
offsetParameter:(NSString *)offsetParameterName
|
350
|
+
{
|
351
|
+
NSParameterAssert(offsetParameterName);
|
352
|
+
NSParameterAssert(limitParameterName);
|
353
|
+
|
354
|
+
AFLimitAndOffsetPaginator *paginator = [[AFLimitAndOffsetPaginator alloc] init];
|
355
|
+
paginator.limitParameter = limitParameterName;
|
356
|
+
paginator.offsetParameter = offsetParameterName;
|
357
|
+
|
358
|
+
return paginator;
|
359
|
+
}
|
360
|
+
|
361
|
+
- (NSDictionary *)parametersForFetchRequest:(NSFetchRequest *)fetchRequest {
|
362
|
+
NSMutableDictionary *mutableParameters = [NSMutableDictionary dictionary];
|
363
|
+
if (fetchRequest.fetchOffset > 0) {
|
364
|
+
[mutableParameters setValue:[NSString stringWithFormat:@"%u", fetchRequest.fetchOffset] forKey:self.offsetParameter];
|
365
|
+
}
|
366
|
+
|
367
|
+
if (fetchRequest.fetchLimit > 0) {
|
368
|
+
[mutableParameters setValue:[NSString stringWithFormat:@"%u", fetchRequest.fetchLimit] forKey:self.limitParameter];
|
369
|
+
}
|
370
|
+
|
371
|
+
return mutableParameters;
|
372
|
+
}
|
373
|
+
|
374
|
+
@end
|
375
|
+
|
376
|
+
#pragma mark -
|
377
|
+
|
378
|
+
static NSUInteger const kAFPaginationDefaultPage = 1;
|
379
|
+
static NSUInteger const kAFPaginationDefaultPerPage = 20;
|
380
|
+
|
381
|
+
@interface AFPageAndPerPagePaginator ()
|
382
|
+
@property (readwrite, nonatomic, copy) NSString *pageParameter;
|
383
|
+
@property (readwrite, nonatomic, copy) NSString *perPageParameter;
|
384
|
+
@end
|
385
|
+
|
386
|
+
@implementation AFPageAndPerPagePaginator
|
387
|
+
|
388
|
+
+ (instancetype)paginatorWithPageParameter:(NSString *)pageParameterName
|
389
|
+
perPageParameter:(NSString *)perPageParameterName
|
390
|
+
{
|
391
|
+
NSParameterAssert(pageParameterName);
|
392
|
+
NSParameterAssert(perPageParameterName);
|
393
|
+
|
394
|
+
AFPageAndPerPagePaginator *paginator = [[AFPageAndPerPagePaginator alloc] init];
|
395
|
+
paginator.pageParameter = pageParameterName;
|
396
|
+
paginator.perPageParameter = perPageParameterName;
|
397
|
+
|
398
|
+
return paginator;
|
399
|
+
}
|
400
|
+
|
401
|
+
- (NSDictionary *)parametersForFetchRequest:(NSFetchRequest *)fetchRequest {
|
402
|
+
NSUInteger perPage = fetchRequest.fetchLimit == 0 ? kAFPaginationDefaultPerPage : fetchRequest.fetchLimit;
|
403
|
+
NSUInteger page = fetchRequest.fetchOffset == 0 ? kAFPaginationDefaultPage : (NSUInteger)floorf((float)fetchRequest.fetchOffset / (float)perPage) + 1;
|
404
|
+
|
405
|
+
NSMutableDictionary *mutableParameters = [NSMutableDictionary dictionary];
|
406
|
+
[mutableParameters setValue:[NSString stringWithFormat:@"%u", page] forKey:self.pageParameter];
|
407
|
+
[mutableParameters setValue:[NSString stringWithFormat:@"%u", perPage] forKey:self.perPageParameter];
|
408
|
+
|
409
|
+
return mutableParameters;
|
410
|
+
}
|
411
|
+
|
412
|
+
@end
|
413
|
+
|
414
|
+
#pragma mark -
|
415
|
+
|
416
|
+
typedef NSDictionary * (^AFPaginationParametersBlock)(NSFetchRequest *fetchRequest);
|
417
|
+
|
418
|
+
@interface AFBlockPaginator ()
|
419
|
+
@property (readwrite, nonatomic, copy) AFPaginationParametersBlock paginationParameters;
|
420
|
+
@end
|
421
|
+
|
422
|
+
@implementation AFBlockPaginator
|
423
|
+
|
424
|
+
+ (instancetype)paginatorWithBlock:(NSDictionary * (^)(NSFetchRequest *fetchRequest))block {
|
425
|
+
NSParameterAssert(block);
|
426
|
+
|
427
|
+
AFBlockPaginator *paginator = [[AFBlockPaginator alloc] init];
|
428
|
+
paginator.paginationParameters = block;
|
429
|
+
|
430
|
+
return paginator;
|
431
|
+
}
|
432
|
+
|
433
|
+
- (NSDictionary *)parametersForFetchRequest:(NSFetchRequest *)fetchRequest {
|
434
|
+
if (self.paginationParameters) {
|
435
|
+
return self.paginationParameters(fetchRequest);
|
436
|
+
}
|
437
|
+
|
438
|
+
return nil;
|
439
|
+
}
|
440
|
+
|
441
|
+
@end
|