Repository: wangyingbo/YBPasterImage Branch: master Commit: d4eea364aaf2 Files: 188 Total size: 550.8 KB Directory structure: gitextract_v1bw8za9/ ├── Podfile ├── Pods/ │ ├── BlocksKit/ │ │ ├── BlocksKit/ │ │ │ ├── BlocksKit+MessageUI.h │ │ │ ├── BlocksKit+UIKit.h │ │ │ ├── BlocksKit.h │ │ │ ├── Core/ │ │ │ │ ├── BKMacros.h │ │ │ │ ├── NSArray+BlocksKit.h │ │ │ │ ├── NSArray+BlocksKit.m │ │ │ │ ├── NSDictionary+BlocksKit.h │ │ │ │ ├── NSDictionary+BlocksKit.m │ │ │ │ ├── NSIndexSet+BlocksKit.h │ │ │ │ ├── NSIndexSet+BlocksKit.m │ │ │ │ ├── NSInvocation+BlocksKit.h │ │ │ │ ├── NSInvocation+BlocksKit.m │ │ │ │ ├── NSMutableArray+BlocksKit.h │ │ │ │ ├── NSMutableArray+BlocksKit.m │ │ │ │ ├── NSMutableDictionary+BlocksKit.h │ │ │ │ ├── NSMutableDictionary+BlocksKit.m │ │ │ │ ├── NSMutableIndexSet+BlocksKit.h │ │ │ │ ├── NSMutableIndexSet+BlocksKit.m │ │ │ │ ├── NSMutableOrderedSet+BlocksKit.h │ │ │ │ ├── NSMutableOrderedSet+BlocksKit.m │ │ │ │ ├── NSMutableSet+BlocksKit.h │ │ │ │ ├── NSMutableSet+BlocksKit.m │ │ │ │ ├── NSObject+BKAssociatedObjects.h │ │ │ │ ├── NSObject+BKAssociatedObjects.m │ │ │ │ ├── NSObject+BKBlockExecution.h │ │ │ │ ├── NSObject+BKBlockExecution.m │ │ │ │ ├── NSObject+BKBlockObservation.h │ │ │ │ ├── NSObject+BKBlockObservation.m │ │ │ │ ├── NSOrderedSet+BlocksKit.h │ │ │ │ ├── NSOrderedSet+BlocksKit.m │ │ │ │ ├── NSSet+BlocksKit.h │ │ │ │ ├── NSSet+BlocksKit.m │ │ │ │ ├── NSTimer+BlocksKit.h │ │ │ │ └── NSTimer+BlocksKit.m │ │ │ ├── DynamicDelegate/ │ │ │ │ ├── A2BlockInvocation.h │ │ │ │ ├── A2BlockInvocation.m │ │ │ │ ├── A2DynamicDelegate.h │ │ │ │ ├── A2DynamicDelegate.m │ │ │ │ ├── Foundation/ │ │ │ │ │ ├── NSCache+BlocksKit.h │ │ │ │ │ ├── NSCache+BlocksKit.m │ │ │ │ │ ├── NSURLConnection+BlocksKit.h │ │ │ │ │ └── NSURLConnection+BlocksKit.m │ │ │ │ ├── NSObject+A2BlockDelegate.h │ │ │ │ ├── NSObject+A2BlockDelegate.m │ │ │ │ ├── NSObject+A2DynamicDelegate.h │ │ │ │ └── NSObject+A2DynamicDelegate.m │ │ │ ├── MessageUI/ │ │ │ │ ├── MFMailComposeViewController+BlocksKit.h │ │ │ │ ├── MFMailComposeViewController+BlocksKit.m │ │ │ │ ├── MFMessageComposeViewController+BlocksKit.h │ │ │ │ └── MFMessageComposeViewController+BlocksKit.m │ │ │ └── UIKit/ │ │ │ ├── UIActionSheet+BlocksKit.h │ │ │ ├── UIActionSheet+BlocksKit.m │ │ │ ├── UIAlertView+BlocksKit.h │ │ │ ├── UIAlertView+BlocksKit.m │ │ │ ├── UIBarButtonItem+BlocksKit.h │ │ │ ├── UIBarButtonItem+BlocksKit.m │ │ │ ├── UIControl+BlocksKit.h │ │ │ ├── UIControl+BlocksKit.m │ │ │ ├── UIGestureRecognizer+BlocksKit.h │ │ │ ├── UIGestureRecognizer+BlocksKit.m │ │ │ ├── UIImagePickerController+BlocksKit.h │ │ │ ├── UIImagePickerController+BlocksKit.m │ │ │ ├── UIPopoverController+BlocksKit.h │ │ │ ├── UIPopoverController+BlocksKit.m │ │ │ ├── UITextField+BlocksKit.h │ │ │ ├── UITextField+BlocksKit.m │ │ │ ├── UIView+BlocksKit.h │ │ │ ├── UIView+BlocksKit.m │ │ │ ├── UIWebView+BlocksKit.h │ │ │ └── UIWebView+BlocksKit.m │ │ ├── LICENSE │ │ └── README.md │ ├── Local Podspecs/ │ │ └── NBSwipePageView.podspec.json │ ├── NBSwipePageView/ │ │ ├── NBSwipePageView/ │ │ │ ├── NBSwipePageView.h │ │ │ ├── NBSwipePageView.m │ │ │ ├── NBSwipePageViewSheet.h │ │ │ └── NBSwipePageViewSheet.m │ │ └── README.md │ ├── Pods.xcodeproj/ │ │ ├── project.pbxproj │ │ └── xcuserdata/ │ │ ├── vipstore.xcuserdatad/ │ │ │ └── xcschemes/ │ │ │ ├── BlocksKit.xcscheme │ │ │ ├── NBSwipePageView.xcscheme │ │ │ ├── Pods-testPasterImage.xcscheme │ │ │ └── xcschememanagement.plist │ │ └── wangyingbo.xcuserdatad/ │ │ └── xcschemes/ │ │ ├── BlocksKit.xcscheme │ │ ├── NBSwipePageView.xcscheme │ │ ├── Pods-testPasterImage.xcscheme │ │ └── xcschememanagement.plist │ └── Target Support Files/ │ ├── BlocksKit/ │ │ ├── BlocksKit-dummy.m │ │ ├── BlocksKit-prefix.pch │ │ └── BlocksKit.xcconfig │ ├── NBSwipePageView/ │ │ ├── NBSwipePageView-dummy.m │ │ ├── NBSwipePageView-prefix.pch │ │ └── NBSwipePageView.xcconfig │ └── Pods-testPasterImage/ │ ├── Pods-testPasterImage-acknowledgements.markdown │ ├── Pods-testPasterImage-acknowledgements.plist │ ├── Pods-testPasterImage-dummy.m │ ├── Pods-testPasterImage-frameworks.sh │ ├── Pods-testPasterImage-resources.sh │ ├── Pods-testPasterImage.debug.xcconfig │ └── Pods-testPasterImage.release.xcconfig ├── README.md ├── files/ │ └── README发帖专用.md ├── testPasterImage/ │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets/ │ │ ├── 1.imageset/ │ │ │ └── Contents.json │ │ ├── 2.imageset/ │ │ │ └── Contents.json │ │ ├── 3.imageset/ │ │ │ └── Contents.json │ │ ├── 4.imageset/ │ │ │ └── Contents.json │ │ ├── 5.imageset/ │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset/ │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── bt_paster_delete.imageset/ │ │ │ └── Contents.json │ │ ├── bt_paster_transform.imageset/ │ │ │ └── Contents.json │ │ ├── dogs.imageset/ │ │ │ └── Contents.json │ │ ├── gao4.imageset/ │ │ │ └── Contents.json │ │ └── gaoyuanyuan.imageset/ │ │ └── Contents.json │ ├── Base.lproj/ │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Categories/ │ │ ├── UIImage+AddFunction.h │ │ ├── UIImage+AddFunction.m │ │ ├── UIViewController+Example.h │ │ ├── UIViewController+Example.m │ │ ├── UIViewController+Extension.h │ │ ├── UIViewController+Extension.m │ │ ├── UIViewController+Swizzling.h │ │ └── UIViewController+Swizzling.m │ ├── Controllers/ │ │ ├── ViewController.h │ │ ├── ViewController.m │ │ ├── YBBaseViewController.h │ │ ├── YBBaseViewController.m │ │ ├── YBPasterImageVC.h │ │ └── YBPasterImageVC.m │ ├── Info.plist │ ├── Libs/ │ │ └── FilterImageLibs/ │ │ ├── ColorMatrix.h │ │ ├── ImageUtil.h │ │ ├── ImageUtil.m │ │ └── UIImage-Extensions/ │ │ ├── .svn/ │ │ │ ├── entries │ │ │ ├── format │ │ │ └── pristine/ │ │ │ ├── 06/ │ │ │ │ └── 062d14b8b3d1573c2d8c9d30257fd9b0b84bd59c.svn-base │ │ │ ├── 39/ │ │ │ │ └── 3944926a8fe582382d834a9fecb902c171a9a76e.svn-base │ │ │ ├── 43/ │ │ │ │ └── 43a6e58f03ebdbe417f3c5028d4dc1b936e030b4.svn-base │ │ │ ├── 5d/ │ │ │ │ └── 5deb2d07c4dd4089e7ade0df1f5278a51efb71cf.svn-base │ │ │ ├── 74/ │ │ │ │ └── 7403967df71a9ffaa67500af6a610523742bfd53.svn-base │ │ │ ├── 9e/ │ │ │ │ └── 9e08c4f172f233df24ad098fd5059cdaf5ad8268.svn-base │ │ │ ├── a3/ │ │ │ │ └── a31a6fddf40b76b94df05097d799e55a769d8440.svn-base │ │ │ ├── be/ │ │ │ │ └── becc3c813720214cae048c91b03d26dba76ff1ca.svn-base │ │ │ ├── c8/ │ │ │ │ └── c8496f35a02cbd4ef1b2a81af9b5ca802b339a3a.svn-base │ │ │ ├── d8/ │ │ │ │ └── d878290233a5ccddb800ee8a4f409b373e187859.svn-base │ │ │ ├── dc/ │ │ │ │ └── dc06ddf7d7a2ad296ab0a741fcc7c3bc6d34b0e3.svn-base │ │ │ └── ee/ │ │ │ └── ee255ad5f9f4f575fb733f734606d7eb9e0efeac.svn-base │ │ ├── UIImage+Alpha.h │ │ ├── UIImage+Alpha.m │ │ ├── UIImage+Cut.h │ │ ├── UIImage+Cut.m │ │ ├── UIImage+Resize.h │ │ ├── UIImage+Resize.m │ │ ├── UIImage+RoundedCorner.h │ │ ├── UIImage+RoundedCorner.m │ │ ├── UIImage+SplitImageIntoTwoParts.h │ │ └── UIImage+SplitImageIntoTwoParts.m │ ├── Views/ │ │ ├── YBCustomViews/ │ │ │ ├── YBCustomButton.h │ │ │ └── YBCustomButton.m │ │ ├── YBFilterImage/ │ │ │ ├── YBFilterScrollView.h │ │ │ └── YBFilterScrollView.m │ │ └── YBPasterImage/ │ │ ├── YBPasterScrollView.h │ │ ├── YBPasterScrollView.m │ │ ├── YBPasterView.h │ │ └── YBPasterView.m │ └── main.m ├── testPasterImage.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata/ │ │ ├── vipstore.xcuserdatad/ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── wangyingbo.xcuserdatad/ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata/ │ ├── vipstore.xcuserdatad/ │ │ ├── xcdebugger/ │ │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes/ │ │ ├── testPasterImage.xcscheme │ │ └── xcschememanagement.plist │ └── wangyingbo.xcuserdatad/ │ └── xcschemes/ │ ├── testPasterImage.xcscheme │ └── xcschememanagement.plist ├── testPasterImage.xcworkspace/ │ ├── contents.xcworkspacedata │ ├── xcshareddata/ │ │ └── testPasterImage.xcscmblueprint │ └── xcuserdata/ │ ├── vipstore.xcuserdatad/ │ │ ├── UserInterfaceState.xcuserstate │ │ └── xcdebugger/ │ │ └── Breakpoints_v2.xcbkptlist │ └── wangyingbo.xcuserdatad/ │ └── UserInterfaceState.xcuserstate ├── testPasterImageTests/ │ ├── Info.plist │ └── testPasterImageTests.m └── testPasterImageUITests/ ├── Info.plist └── testPasterImageUITests.m ================================================ FILE CONTENTS ================================================ ================================================ FILE: Podfile ================================================ platform :ios, '8.0' target 'testPasterImage' do pod 'BlocksKit', '~> 2.2.5' pod 'NBSwipePageView', :git => 'https://github.com/xuzhe/NBSwipePageView.git' end ================================================ FILE: Pods/BlocksKit/BlocksKit/BlocksKit+MessageUI.h ================================================ // // BlocksKit+MessageUI // // The Objective-C block utilities you always wish you had. // // Copyright (c) 2011-2012, 2013-2014 Zachary Waldowski // Copyright (c) 2012-2013 Pandamonia LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // #import #import ================================================ FILE: Pods/BlocksKit/BlocksKit/BlocksKit+UIKit.h ================================================ // // BlocksKit+UIKit // // The Objective-C block utilities you always wish you had. // // Copyright (c) 2011-2012, 2013-2014 Zachary Waldowski // Copyright (c) 2012-2013 Pandamonia LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // #import #import #import #import #import #import #import #import #import #import #import ================================================ FILE: Pods/BlocksKit/BlocksKit/BlocksKit.h ================================================ // // BlocksKit // // The Objective-C block utilities you always wish you had. // // Copyright (c) 2011-2012, 2013-2014 Zachary Waldowski // Copyright (c) 2012-2013 Pandamonia LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/BKMacros.h ================================================ // // BKMacros.h // BlocksKit // // Includes code by Michael Ash. . // #import "NSArray+BlocksKit.h" #import "NSSet+BlocksKit.h" #import "NSDictionary+BlocksKit.h" #import "NSIndexSet+BlocksKit.h" #ifndef __BLOCKSKIT_MACROS__ #define __BLOCKSKIT_MACROS__ #define __BK_EACH_WRAPPER(...) (^{ __block CFMutableDictionaryRef BK_eachTable = nil; \ (void)BK_eachTable; \ __typeof__(__VA_ARGS__) BK_retval = __VA_ARGS__; \ if(BK_eachTable) \ CFRelease(BK_eachTable); \ return BK_retval; \ }()) #define __BK_EACH_WRAPPER_VOID(...) (^{ __block CFMutableDictionaryRef BK_eachTable = nil; \ (void)BK_eachTable; \ __VA_ARGS__; \ if(BK_eachTable) \ CFRelease(BK_eachTable); \ }()) #define BK_EACH(collection, ...) __BK_EACH_WRAPPER_VOID([collection bk_each:^(id obj) { __VA_ARGS__ }]) #define BK_MAP(collection, ...) __BK_EACH_WRAPPER([collection bk_map:^id(id obj) { return (__VA_ARGS__); }]) #define BK_SELECT(collection, ...) __BK_EACH_WRAPPER([collection bk_select: ^BOOL (id obj) { return (__VA_ARGS__) != 0; }]) #define BK_REJECT(collection, ...) __BK_EACH_WRAPPER([collection bk_select: ^BOOL (id obj) { return (__VA_ARGS__) == 0; }]) #define BK_MATCH(collection, ...) __BK_EACH_WRAPPER([collection bk_match: ^BOOL (id obj) { return (__VA_ARGS__) != 0; }]) #define BK_REDUCE(collection, initial, ...) __BK_EACH_WRAPPER([collection bk_reduce: (initial) withBlock: ^id (id a, id b) { return (__VA_ARGS__); }]) // BK_APPLY is not wrapped, because we don't guarantee that the order matches the current collection during parallel execution. #define BK_APPLY(collection, ...) [collection bk_apply:^(id obj) { __VA_ARGS__ }] static inline id BKNextHelper(NSArray *array, CFMutableDictionaryRef *eachTablePtr) { if (!*eachTablePtr) { CFDictionaryKeyCallBacks keycb = { 0, kCFTypeDictionaryKeyCallBacks.retain, kCFTypeDictionaryKeyCallBacks.release, kCFTypeDictionaryKeyCallBacks.copyDescription, NULL, NULL }; *eachTablePtr = CFDictionaryCreateMutable(NULL, 0, &keycb, &kCFTypeDictionaryValueCallBacks); } NSEnumerator *enumerator = (__bridge id)CFDictionaryGetValue(*eachTablePtr, (__bridge CFArrayRef)array); if (!enumerator) { enumerator = [array objectEnumerator]; CFDictionarySetValue(*eachTablePtr, (__bridge CFArrayRef)array, (__bridge void *)enumerator); } return [enumerator nextObject]; } #define BK_NEXT(array) BKNextHelper(array, &BK_eachTable) #ifndef EACH #define EACH BK_EACH #endif #ifndef APPLY #define APPLY BK_APPLY #endif #ifndef MAP #define MAP BK_MAP #endif #ifndef SELECT #define SELECT BK_SELECT #endif #ifndef REJECT #define REJECT BK_REJECT #endif #ifndef MATCH #define MATCH BK_MATCH #endif #ifndef REDUCE #define REDUCE BK_REDUCE #endif #ifndef NEXT #define NEXT BK_NEXT #endif #endif ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSArray+BlocksKit.h ================================================ // // NSArray+BlocksKit.h // BlocksKit // #import #import /** Block extensions for NSArray. Both inspired by and resembling Smalltalk syntax, these utilities allows for iteration of an array in a concise way that saves quite a bit of boilerplate code for filtering or finding objects or an object. Includes code by the following: - [Robin Lu](https://github.com/robin) - [Michael Ash](https://github.com/mikeash) - [Aleks Nesterow](https://github.com/nesterow) - [Zach Waldowski](https://github.com/zwaldowski) @see NSDictionary(BlocksKit) @see NSSet(BlocksKit) */ @interface NSArray (BlocksKit) /** Loops through an array and executes the given block with each object. @param block A single-argument, void-returning code block. */ - (void)bk_each:(void (^)(id obj))block; /** Enumerates through an array concurrently and executes the given block once for each object. Enumeration will occur on appropriate background queues. This will have a noticeable speed increase, especially on dual-core devices, but you *must* be aware of the thread safety of the objects you message from within the block. Be aware that the order of objects is not necessarily the order each block will be called in. @param block A single-argument, void-returning code block. */ - (void)bk_apply:(void (^)(id obj))block; /** Loops through an array to find the object matching the block. bk_match: is functionally identical to bk_select:, but will stop and return on the first match. @param block A single-argument, `BOOL`-returning code block. @return Returns the object, if found, or `nil`. @see bk_select: */ - (id)bk_match:(BOOL (^)(id obj))block; /** Loops through an array to find the objects matching the block. @param block A single-argument, BOOL-returning code block. @return Returns an array of the objects found. @see bk_match: */ - (NSArray *)bk_select:(BOOL (^)(id obj))block; /** Loops through an array to find the objects not matching the block. This selector performs *literally* the exact same function as bk_select: but in reverse. This is useful, as one may expect, for removing objects from an array. NSArray *new = [computers bk_reject:^BOOL(id obj) { return ([obj isUgly]); }]; @param block A single-argument, BOOL-returning code block. @return Returns an array of all objects not found. */ - (NSArray *)bk_reject:(BOOL (^)(id obj))block; /** Call the block once for each object and create an array of the return values. This is sometimes referred to as a transform, mutating one of each object: NSArray *new = [stringArray bk_map:^id(id obj) { return [obj stringByAppendingString:@".png"]); }]; @param block A single-argument, object-returning code block. @return Returns an array of the objects returned by the block. */ - (NSArray *)bk_map:(id (^)(id obj))block; /** Arbitrarily accumulate objects using a block. The concept of this selector is difficult to illustrate in words. The sum can be any NSObject, including (but not limited to) a string, number, or value. For example, you can concentate the strings in an array: NSString *concentrated = [stringArray bk_reduce:@"" withBlock:^id(id sum, id obj) { return [sum stringByAppendingString:obj]; }]; You can also do something like summing the lengths of strings in an array: NSUInteger value = [[[stringArray bk_reduce:nil withBlock:^id(id sum, id obj) { return @([sum integerValue] + obj.length); }]] unsignedIntegerValue]; @param initial The value of the reduction at its start. @param block A block that takes the current sum and the next object to return the new sum. @return An accumulated value. */ - (id)bk_reduce:(id)initial withBlock:(id (^)(id sum, id obj))block; /** Sometimes we just want to loop an objects list and reduce one property, where each result is a primitive type. For example, say we want to calculate the total age of a list of people. Code without using block will be something like: NSArray *peoples = @[p1, p2, p3]; NSInteger totalAge = 0; for (People *people in peoples) { totalAge += [people age]; } We can use a block to make it simpler: NSArray *peoples = @[p1, p2, p3]; NSInteger totalAge = [peoples reduceInteger:0 withBlock:^(NSInteger result, id obj, NSInteger index) { return result + [obj age]; }]; */ - (NSInteger)bk_reduceInteger:(NSInteger)initial withBlock:(NSInteger(^)(NSInteger result, id obj))block; /** Sometimes we just want to loop an objects list and reduce one property, where each result is a primitive type. For instance, say we want to caculate the total balance from a list of people. Code without using a block will be something like: NSArray *peoples = @[p1, p2, p3]; CGFloat totalBalance = 0; for (People *people in peoples) { totalBalance += [people balance]; } We can use a block to make it simpler: NSArray *peoples = @[p1, p2, p3]; CGFloat totalBalance = [peoples reduceFloat:.0f WithBlock:^CGFloat(CGFloat result, id obj, NSInteger index) { return result + [obj balance]; }]; */ - (CGFloat)bk_reduceFloat:(CGFloat)inital withBlock:(CGFloat(^)(CGFloat result, id obj))block; /** Loops through an array to find whether any object matches the block. This method is similar to the Scala list `exists`. It is functionally identical to bk_match: but returns a `BOOL` instead. It is not recommended to use bk_any: as a check condition before executing bk_match:, since it would require two loops through the array. For example, you can find if a string in an array starts with a certain letter: NSString *letter = @"A"; BOOL containsLetter = [stringArray bk_any:^(id obj) { return [obj hasPrefix:@"A"]; }]; @param block A single-argument, BOOL-returning code block. @return YES for the first time the block returns YES for an object, NO otherwise. */ - (BOOL)bk_any:(BOOL (^)(id obj))block; /** Loops through an array to find whether no objects match the block. This selector performs *literally* the exact same function as bk_all: but in reverse. @param block A single-argument, BOOL-returning code block. @return YES if the block returns NO for all objects in the array, NO otherwise. */ - (BOOL)bk_none:(BOOL (^)(id obj))block; /** Loops through an array to find whether all objects match the block. @param block A single-argument, BOOL-returning code block. @return YES if the block returns YES for all objects in the array, NO otherwise. */ - (BOOL)bk_all:(BOOL (^)(id obj))block; /** Tests whether every element of this array relates to the corresponding element of another array according to match by block. For example, finding if a list of numbers corresponds to their sequenced string values; NSArray *numbers = @[ @(1), @(2), @(3) ]; NSArray *letters = @[ @"1", @"2", @"3" ]; BOOL doesCorrespond = [numbers bk_corresponds:letters withBlock:^(id number, id letter) { return [[number stringValue] isEqualToString:letter]; }]; @param list An array of objects to compare with. @param block A two-argument, BOOL-returning code block. @return Returns a BOOL, true if every element of array relates to corresponding element in another array. */ - (BOOL)bk_corresponds:(NSArray *)list withBlock:(BOOL (^)(id obj1, id obj2))block; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSArray+BlocksKit.m ================================================ // // NSArray+BlocksKit.m // BlocksKit // #import "NSArray+BlocksKit.h" @implementation NSArray (BlocksKit) - (void)bk_each:(void (^)(id obj))block { NSParameterAssert(block != nil); [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { block(obj); }]; } - (void)bk_apply:(void (^)(id obj))block { NSParameterAssert(block != nil); [self enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id obj, NSUInteger idx, BOOL *stop) { block(obj); }]; } - (id)bk_match:(BOOL (^)(id obj))block { NSParameterAssert(block != nil); NSUInteger index = [self indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) { return block(obj); }]; if (index == NSNotFound) return nil; return self[index]; } - (NSArray *)bk_select:(BOOL (^)(id obj))block { NSParameterAssert(block != nil); return [self objectsAtIndexes:[self indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) { return block(obj); }]]; } - (NSArray *)bk_reject:(BOOL (^)(id obj))block { NSParameterAssert(block != nil); return [self bk_select:^BOOL(id obj) { return !block(obj); }]; } - (NSArray *)bk_map:(id (^)(id obj))block { NSParameterAssert(block != nil); NSMutableArray *result = [NSMutableArray arrayWithCapacity:self.count]; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { id value = block(obj) ?: [NSNull null]; [result addObject:value]; }]; return result; } - (id)bk_reduce:(id)initial withBlock:(id (^)(id sum, id obj))block { NSParameterAssert(block != nil); __block id result = initial; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { result = block(result, obj); }]; return result; } - (NSInteger)bk_reduceInteger:(NSInteger)initial withBlock:(NSInteger (^)(NSInteger, id))block { NSParameterAssert(block != nil); __block NSInteger result = initial; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { result = block(result, obj); }]; return result; } - (CGFloat)bk_reduceFloat:(CGFloat)inital withBlock:(CGFloat (^)(CGFloat, id))block { NSParameterAssert(block != nil); __block CGFloat result = inital; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { result = block(result, obj); }]; return result; } - (BOOL)bk_any:(BOOL (^)(id obj))block { return [self bk_match:block] != nil; } - (BOOL)bk_none:(BOOL (^)(id obj))block { return [self bk_match:block] == nil; } - (BOOL)bk_all:(BOOL (^)(id obj))block { NSParameterAssert(block != nil); __block BOOL result = YES; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { if (!block(obj)) { result = NO; *stop = YES; } }]; return result; } - (BOOL)bk_corresponds:(NSArray *)list withBlock:(BOOL (^)(id obj1, id obj2))block { NSParameterAssert(block != nil); __block BOOL result = NO; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { if (idx < list.count) { id obj2 = list[idx]; result = block(obj, obj2); } else { result = NO; } *stop = !result; }]; return result; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSDictionary+BlocksKit.h ================================================ // // NSDictionary+BlocksKit.h // BlocksKit // #import /** Block extension for NSDictionary. Both inspired by and resembling Smalltalk syntax, this utility allows iteration of a dictionary in a concise way that saves quite a bit of boilerplate code. Includes code by the following: - [Mirko Kiefer](https://github.com/mirkok) - [Zach Waldowski](https://github.com/zwaldowski) @see NSArray(BlocksKit) @see NSSet(BlocksKit) */ @interface NSDictionary (BlocksKit) /** Loops through the dictionary and executes the given block using each item. @param block A block that performs an action using a key/value pair. */ - (void)bk_each:(void (^)(id key, id obj))block; /** Enumerates through the dictionary concurrently and executes the given block once for each pair. Enumeration will occur on appropriate background queues; the system will spawn threads as need for execution. This will have a noticeable speed increase, especially on dual-core devices, but you *must* be aware of the thread safety of the objects you message from within the block. @param block A block that performs an action using a key/value pair. */ - (void)bk_apply:(void (^)(id key, id obj))block; /** Loops through a dictionary to find the first key/value pair matching the block. bk_match: is functionally identical to bk_select:, but will stop and return the value on the first match. @param block A BOOL-returning code block for a key/value pair. @return The value of the first pair found; */ - (id)bk_match:(BOOL (^)(id key, id obj))block; /** Loops through a dictionary to find the key/value pairs matching the block. @param block A BOOL-returning code block for a key/value pair. @return Returns a dictionary of the objects found. */ - (NSDictionary *)bk_select:(BOOL (^)(id key, id obj))block; /** Loops through a dictionary to find the key/value pairs not matching the block. This selector performs *literally* the exact same function as bk_select: but in reverse. This is useful, as one may expect, for filtering objects. NSDictionary *strings = [userData bk_reject:^BOOL(id key, id value) { return ([obj isKindOfClass:[NSString class]]); }]; @param block A BOOL-returning code block for a key/value pair. @return Returns a dictionary of all objects not found. */ - (NSDictionary *)bk_reject:(BOOL (^)(id key, id obj))block; /** Call the block once for each object and create a dictionary with the same keys and a new set of values. @param block A block that returns a new value for a key/value pair. @return Returns a dictionary of the objects returned by the block. */ - (NSDictionary *)bk_map:(id (^)(id key, id obj))block; /** Loops through a dictionary to find whether any key/value pair matches the block. This method is similar to the Scala list `exists`. It is functionally identical to bk_match: but returns a `BOOL` instead. It is not recommended to use bk_any: as a check condition before executing bk_match:, since it would require two loops through the dictionary. @param block A two-argument, BOOL-returning code block. @return YES for the first time the block returns YES for a key/value pair, NO otherwise. */ - (BOOL)bk_any:(BOOL (^)(id key, id obj))block; /** Loops through a dictionary to find whether no key/value pairs match the block. This selector performs *literally* the exact same function as bk_all: but in reverse. @param block A two-argument, BOOL-returning code block. @return YES if the block returns NO for all key/value pairs in the dictionary, NO otherwise. */ - (BOOL)bk_none:(BOOL (^)(id key, id obj))block; /** Loops through a dictionary to find whether all key/value pairs match the block. @param block A two-argument, BOOL-returning code block. @return YES if the block returns YES for all key/value pairs in the dictionary, NO otherwise. */ - (BOOL)bk_all:(BOOL (^)(id key, id obj))block; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSDictionary+BlocksKit.m ================================================ // // NSDictionary+BlocksKit.m // BlocksKit // #import "NSDictionary+BlocksKit.h" @implementation NSDictionary (BlocksKit) - (void)bk_each:(void (^)(id key, id obj))block { NSParameterAssert(block != nil); [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { block(key, obj); }]; } - (void)bk_apply:(void (^)(id key, id obj))block { NSParameterAssert(block != nil); [self enumerateKeysAndObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id key, id obj, BOOL *stop) { block(key, obj); }]; } - (id)bk_match:(BOOL (^)(id key, id obj))block { NSParameterAssert(block != nil); return self[[[self keysOfEntriesPassingTest:^(id key, id obj, BOOL *stop) { if (block(key, obj)) { *stop = YES; return YES; } return NO; }] anyObject]]; } - (NSDictionary *)bk_select:(BOOL (^)(id key, id obj))block { NSParameterAssert(block != nil); NSArray *keys = [[self keysOfEntriesPassingTest:^(id key, id obj, BOOL *stop) { return block(key, obj); }] allObjects]; NSArray *objects = [self objectsForKeys:keys notFoundMarker:[NSNull null]]; return [NSDictionary dictionaryWithObjects:objects forKeys:keys]; } - (NSDictionary *)bk_reject:(BOOL (^)(id key, id obj))block { NSParameterAssert(block != nil); return [self bk_select:^BOOL(id key, id obj) { return !block(key, obj); }]; } - (NSDictionary *)bk_map:(id (^)(id key, id obj))block { NSParameterAssert(block != nil); NSMutableDictionary *result = [NSMutableDictionary dictionaryWithCapacity:self.count]; [self bk_each:^(id key, id obj) { id value = block(key, obj) ?: [NSNull null]; result[key] = value; }]; return result; } - (BOOL)bk_any:(BOOL (^)(id key, id obj))block { return [self bk_match:block] != nil; } - (BOOL)bk_none:(BOOL (^)(id key, id obj))block { return [self bk_match:block] == nil; } - (BOOL)bk_all:(BOOL (^)(id key, id obj))block { NSParameterAssert(block != nil); __block BOOL result = YES; [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { if (!block(key, obj)) { result = NO; *stop = YES; } }]; return result; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSIndexSet+BlocksKit.h ================================================ // // NSIndexSet+BlocksKit.h // BlocksKit // #import /** Block extensions for NSIndexSet. Both inspired by and resembling Smalltalk syntax, these utilities allows for iteration of an array in a concise way that saves quite a bit of boilerplate code for filtering or finding objects or an object. Includes code by the following: - [Robin Lu](https://github.com/robin) - [Michael Ash](https://github.com/mikeash) - [Zach Waldowski](https://github.com/zwaldowski) - [Kaelin Colclasure] @see NSArray(BlocksKit) @see NSDictionary(BlocksKit) @see NSSet(BlocksKit) */ @interface NSIndexSet (BlocksKit) /** Loops through an index set and executes the given block at each index. @param block A single-argument, void-returning code block. */ - (void)bk_each:(void (^)(NSUInteger index))block; /** Enumerates each index in an index set concurrently and executes the given block once per index. Enumeration will occur on appropriate background queues. Be aware that the block will not necessarily be executed in order for each index. @param block A single-argument, void-returning code block. */ - (void)bk_apply:(void (^)(NSUInteger index))block; /** Loops through an array and returns the index matching the block. @param block A single-argument, `BOOL`-returning code block. @return Returns the index if found, `NSNotFound` otherwise. @see bk_select: */ - (NSUInteger)bk_match:(BOOL (^)(NSUInteger index))block; /** Loops through an index set and returns an all indexes matching the block. @param block A single-argument, BOOL-returning code block. @return Returns an index set of matching indexes found. @see bk_match: */ - (NSIndexSet *)bk_select:(BOOL (^)(NSUInteger index))block; /** Loops through an index set and returns an all indexes but the ones matching the block. This selector performs *literally* the exact same function as bk_select: but in reverse. @param block A single-argument, BOOL-returning code block. @return Returns an index set of all indexes but those matched. */ - (NSIndexSet *)bk_reject:(BOOL (^)(NSUInteger index))block; /** Call the block once for each index and create an index set with the new values. @param block A block that returns a new index for an index. @return An index set of the indexes returned by the block. */ - (NSIndexSet *)bk_map:(NSUInteger (^)(NSUInteger index))block; /** Call the block once for each index and create an array of the return values. This method allows transforming indexes into objects: int values[10] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 }; NSIndexSet *idxs = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 10)]; NSArray *new = [idxs mapIndex:^id(NSUInteger index) { return [NSNumber numberWithInt:values[index]]); }]; @param block A block that returns an object for an index. @return Returns an array of the objects returned by the block. */ - (NSArray *)bk_mapIndex:(id (^)(NSUInteger index))block; /** Loops through an index set to find whether any of the indexes matche the block. This method is similar to the Scala list `exists`. It is functionally identical to bk_match: but returns a `BOOL` instead. It is not recommended to use bk_any: as a check condition before executing bk_match:, since it would require two loops through the index set. @param block A single-argument, BOOL-returning code block. @return YES for the first time the block returns YES for an index, NO otherwise. */ - (BOOL)bk_any:(BOOL (^)(NSUInteger index))block; /** Loops through an index set to find whether all objects match the block. @param block A single-argument, BOOL-returning code block. @return YES if the block returns YES for all indexes in the array, NO otherwise. */ - (BOOL)bk_all:(BOOL (^)(NSUInteger index))block; /** Loops through an index set to find whether no objects match the block. This selector performs *literally* the exact same function as bk_all: but in reverse. @param block A single-argument, BOOL-returning code block. @return YES if the block returns NO for all indexes in the array, NO otherwise. */ - (BOOL)bk_none:(BOOL (^)(NSUInteger index))block; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSIndexSet+BlocksKit.m ================================================ // // NSIndexSet+BlocksKit.m // BlocksKit // #import "NSIndexSet+BlocksKit.h" @implementation NSIndexSet (BlocksKit) - (void)bk_each:(void (^)(NSUInteger index))block { NSParameterAssert(block != nil); [self enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { block(idx); }]; } - (void)bk_apply:(void (^)(NSUInteger index))block { NSParameterAssert(block != nil); [self enumerateIndexesWithOptions:NSEnumerationConcurrent usingBlock:^(NSUInteger idx, BOOL *stop) { block(idx); }]; } - (NSUInteger)bk_match:(BOOL (^)(NSUInteger index))block { NSParameterAssert(block != nil); return [self indexPassingTest:^BOOL(NSUInteger idx, BOOL *stop) { return block(idx); }]; } - (NSIndexSet *)bk_select:(BOOL (^)(NSUInteger index))block { NSParameterAssert(block != nil); NSIndexSet *list = [self indexesPassingTest:^BOOL(NSUInteger idx, BOOL *stop) { return block(idx); }]; if (!list.count) return nil; return list; } - (NSIndexSet *)bk_reject:(BOOL (^)(NSUInteger index))block { NSParameterAssert(block != nil); return [self bk_select:^BOOL(NSUInteger idx) { return !block(idx); }]; } - (NSIndexSet *)bk_map:(NSUInteger (^)(NSUInteger index))block { NSParameterAssert(block != nil); NSMutableIndexSet *list = [NSMutableIndexSet indexSet]; [self enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { [list addIndex:block(idx)]; }]; if (!list.count) return nil; return list; } - (NSArray *)bk_mapIndex:(id (^)(NSUInteger index))block { NSParameterAssert(block != nil); NSMutableArray *result = [NSMutableArray arrayWithCapacity:self.count]; [self enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { id value = block(idx) ?: [NSNull null]; [result addObject:value]; }]; return result; } - (BOOL)bk_any:(BOOL (^)(NSUInteger index))block { return [self bk_match:block] != NSNotFound; } - (BOOL)bk_none:(BOOL (^)(NSUInteger index))block { return [self bk_match:block] == NSNotFound; } - (BOOL)bk_all:(BOOL (^)(NSUInteger index))block { NSParameterAssert(block != nil); __block BOOL result = YES; [self enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { if (!block(idx)) { result = NO; *stop = YES; } }]; return result; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSInvocation+BlocksKit.h ================================================ // // NSInvocation+BlocksKit.h // BlocksKit // #import /** BlocksKit extensions for NSInvocation. */ @interface NSInvocation (BlocksKit) /** Generates a forwarding `NSInvocation` instance for a given method call encapsulated by the given block. NSInvocation *invocation = [NSInvocation invocationWithTarget:target block:^(id myObject) { [myObject someMethodWithArg:42.0]; }]; This returns an invocation with the appropriate target, selector, and arguments without creating the buffers yourself. It is only recommended to call a method on the argument to the block only once. More complicated forwarding machinery can be accomplished by the A2DynamicDelegate family of classes included in BlocksKit. Created by [Jonathan Rentzch](https://github.com/rentzsch) as `NSInvocation-blocks`. @param target The object to "grab" the block invocation from. @param block A code block. @return A fully-prepared instance of NSInvocation ready to be invoked. */ + (NSInvocation *)bk_invocationWithTarget:(id)target block:(void (^)(id target))block; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSInvocation+BlocksKit.m ================================================ // // NSInvocation+BlocksKit.m // BlocksKit // #import "NSInvocation+BlocksKit.h" @interface BKInvocationGrabber : NSProxy + (BKInvocationGrabber *)grabberWithTarget:(id)target; @property (nonatomic, strong) id target; @property (nonatomic, strong) NSInvocation *invocation; @end @implementation BKInvocationGrabber + (BKInvocationGrabber *)grabberWithTarget:(id)target { BKInvocationGrabber *instance = [BKInvocationGrabber alloc]; instance.target = target; return instance; } - (NSMethodSignature*)methodSignatureForSelector:(SEL)selector { return [self.target methodSignatureForSelector:selector]; } - (void)forwardInvocation:(NSInvocation*)invocation { [invocation setTarget:self.target]; NSParameterAssert(self.invocation == nil); self.invocation = invocation; } @end @implementation NSInvocation (BlocksKit) + (NSInvocation *)bk_invocationWithTarget:(id)target block:(void (^)(id target))block { NSParameterAssert(block != nil); BKInvocationGrabber *grabber = [BKInvocationGrabber grabberWithTarget:target]; block(grabber); return grabber.invocation; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSMutableArray+BlocksKit.h ================================================ // // NSMutableArray+BlocksKit.h // BlocksKit // #import /** Block extensions for NSMutableArray. These utilities expound upon the BlocksKit additions to the immutable superclass by allowing certain utilities to work on an instance of the mutable class, saving memory by not creating an immutable copy of the results. Includes code by the following: - [Martin Schürrer](https://github.com/MSch) - [Zach Waldowski](https://github.com/zwaldowski) @see NSArray(BlocksKit) */ @interface NSMutableArray (BlocksKit) /** Filters a mutable array to the objects matching the block. @param block A single-argument, BOOL-returning code block. @see bk_reject: */ - (void)bk_performSelect:(BOOL (^)(id obj))block; /** Filters a mutable array to all objects but the ones matching the block, the logical inverse to bk_select:. @param block A single-argument, BOOL-returning code block. @see bk_select: */ - (void)bk_performReject:(BOOL (^)(id obj))block; /** Transform the objects in the array to the results of the block. This is sometimes referred to as a transform, mutating one of each object: [foo bk_performMap:^id(id obj) { return [dateTransformer dateFromString:obj]; }]; @param block A single-argument, object-returning code block. @see bk_map: */ - (void)bk_performMap:(id (^)(id obj))block; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSMutableArray+BlocksKit.m ================================================ // // NSMutableArray+BlocksKit.m // BlocksKit // #import "NSMutableArray+BlocksKit.h" @implementation NSMutableArray (BlocksKit) - (void)bk_performSelect:(BOOL (^)(id obj))block { NSParameterAssert(block != nil); NSIndexSet *list = [self indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) { return !block(obj); }]; if (!list.count) return; [self removeObjectsAtIndexes:list]; } - (void)bk_performReject:(BOOL (^)(id obj))block { NSParameterAssert(block != nil); return [self bk_performSelect:^BOOL(id obj) { return !block(obj); }]; } - (void)bk_performMap:(id (^)(id obj))block { NSParameterAssert(block != nil); NSMutableArray *new = [self mutableCopy]; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { id value = block(obj) ?: [NSNull null]; if ([value isEqual:obj]) return; new[idx] = value; }]; [self setArray:new]; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSMutableDictionary+BlocksKit.h ================================================ // // NSMutableDictionary+BlocksKit.h // BlocksKit // #import /** Block extensions for NSMutableDictionary. These utilities expound upon the BlocksKit additions to the immutable superclass by allowing certain utilities to work on an instance of the mutable class, saving memory by not creating an immutable copy of the results. Includes code by the following: - [Martin Schürrer](https://github.com/MSch) - [Zach Waldowski](https://github.com/zwaldowski) @see NSDictionary(BlocksKit) */ @interface NSMutableDictionary (BlocksKit) /** Filters a mutable dictionary to the key/value pairs matching the block. @param block A BOOL-returning code block for a key/value pair. @see bk_reject: */ - (void)bk_performSelect:(BOOL (^)(id key, id obj))block; /** Filters a mutable dictionary to the key/value pairs not matching the block, the logical inverse to bk_select:. @param block A BOOL-returning code block for a key/value pair. @see bk_select: */ - (void)bk_performReject:(BOOL (^)(id key, id obj))block; /** Transform each value of the dictionary to a new value, as returned by the block. @param block A block that returns a new value for a given key/value pair. @see bk_map: */ - (void)bk_performMap:(id (^)(id key, id obj))block; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSMutableDictionary+BlocksKit.m ================================================ // // NSMutableDictionary+BlocksKit.m // BlocksKit // #import "NSMutableDictionary+BlocksKit.h" @implementation NSMutableDictionary (BlocksKit) - (void)bk_performSelect:(BOOL (^)(id key, id obj))block { NSParameterAssert(block != nil); NSArray *keys = [[self keysOfEntriesWithOptions:NSEnumerationConcurrent passingTest:^BOOL(id key, id obj, BOOL *stop) { return !block(key, obj); }] allObjects]; [self removeObjectsForKeys:keys]; } - (void)bk_performReject:(BOOL (^)(id key, id obj))block { NSParameterAssert(block != nil); [self bk_performSelect:^BOOL(id key, id obj) { return !block(key, obj); }]; } - (void)bk_performMap:(id (^)(id key, id obj))block { NSParameterAssert(block != nil); NSMutableDictionary *new = [self mutableCopy]; [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { id value = block(key, obj) ?: [NSNull null]; if ([value isEqual:obj]) return; new[key] = value; }]; [self setDictionary:new]; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSMutableIndexSet+BlocksKit.h ================================================ // // NSMutableIndexSet+BlocksKit.h // BlocksKit // #import /** Block extensions for NSMutableIndexSet. These utilities expound upon the BlocksKit additions to the immutable superclass by allowing certain utilities to work on an instance of the mutable class, saving memory by not creating an immutable copy of the results. @see NSIndexSet(BlocksKit) */ @interface NSMutableIndexSet (BlocksKit) /** Filters a mutable index set to the indexes matching the block. @param block A single-argument, BOOL-returning code block. @see bk_reject: */ - (void)bk_performSelect:(BOOL (^)(NSUInteger index))block; /** Filters a mutable index set to all indexes but the ones matching the block, the logical inverse to bk_select:. @param block A single-argument, BOOL-returning code block. @see bk_select: */ - (void)bk_performReject:(BOOL (^)(NSUInteger index))block; /** Transform each index of the index set to a new index, as returned by the block. @param block A block that returns a new index for a index. @see bk_map: */ - (void)bk_performMap:(NSUInteger (^)(NSUInteger index))block; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSMutableIndexSet+BlocksKit.m ================================================ // // NSMutableIndexSet+BlocksKit.m // BlocksKit // #import "NSMutableIndexSet+BlocksKit.h" @implementation NSMutableIndexSet (BlocksKit) - (void)bk_performSelect:(BOOL (^)(NSUInteger index))block { NSParameterAssert(block != nil); NSIndexSet *list = [self indexesPassingTest:^BOOL(NSUInteger idx, BOOL *stop) { return !block(idx); }]; if (!list.count) return; [self removeIndexes:list]; } - (void)bk_performReject:(BOOL (^)(NSUInteger index))block { NSParameterAssert(block != nil); return [self bk_performSelect:^BOOL(NSUInteger idx) { return !block(idx); }]; } - (void)bk_performMap:(NSUInteger (^)(NSUInteger index))block { NSParameterAssert(block != nil); NSMutableIndexSet *new = [self mutableCopy]; [self enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { [new addIndex:block(idx)]; }]; [self removeAllIndexes]; [self addIndexes:new]; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSMutableOrderedSet+BlocksKit.h ================================================ // // NSMutableOrderedSet+BlocksKit.h // BlocksKit // #import /** Block extensions for NSMutableOrderedSet. These utilities expound upon the BlocksKit additions to the immutable superclass by allowing certain utilities to work on an instance of the mutable class, saving memory by not creating an immutable copy of the results. Includes code by the following: - [Martin Schürrer](https://github.com/MSch) - [Zach Waldowski](https://github.com/zwaldowski) @see NSOrderedSet(BlocksKit) */ @interface NSMutableOrderedSet (BlocksKit) /** Filters a mutable ordered set to the objects matching the block. @param block A single-argument, BOOL-returning code block. @see bk_reject: */ - (void)bk_performSelect:(BOOL (^)(id obj))block; /** Filters a mutable ordered set to all objects but the ones matching the block, the logical inverse to bk_select:. @param block A single-argument, BOOL-returning code block. @see bk_select: */ - (void)bk_performReject:(BOOL (^)(id obj))block; /** Transform the objects in the ordered set to the results of the block. This is sometimes referred to as a transform, mutating one of each object: [foo bk_performMap:^id(id obj) { return [dateTransformer dateFromString:obj]; }]; @param block A single-argument, object-returning code block. @see bk_map: */ - (void)bk_performMap:(id (^)(id obj))block; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSMutableOrderedSet+BlocksKit.m ================================================ // // NSMutableOrderedSet+BlocksKit.m // BlocksKit // #import "NSMutableOrderedSet+BlocksKit.h" @implementation NSMutableOrderedSet (BlocksKit) - (void)bk_performSelect:(BOOL (^)(id obj))block { NSParameterAssert(block != nil); NSIndexSet *list = [self indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) { return !block(obj); }]; if (!list.count) return; [self removeObjectsAtIndexes:list]; } - (void)bk_performReject:(BOOL (^)(id obj))block { NSParameterAssert(block != nil); return [self bk_performSelect:^BOOL(id obj) { return !block(obj); }]; } - (void)bk_performMap:(id (^)(id obj))block { NSParameterAssert(block != nil); NSMutableIndexSet *newIndexes = [NSMutableIndexSet indexSet]; NSMutableArray *newObjects = [NSMutableArray arrayWithCapacity:self.count]; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { id value = block(obj) ?: [NSNull null]; if ([value isEqual:obj]) return; [newIndexes addIndex:idx]; [newObjects addObject:obj]; }]; [self replaceObjectsAtIndexes:newIndexes withObjects:newObjects]; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSMutableSet+BlocksKit.h ================================================ // // NSMutableSet+BlocksKit.h // BlocksKit // #import /** Block extensions for NSMutableSet. These utilities expound upon the BlocksKit additions to the immutable superclass by allowing certain utilities to work on an instance of the mutable class, saving memory by not creating an immutable copy of the results. Includes code by the following: - [Martin Schürrer](https://github.com/MSch) - [Zach Waldowski](https://github.com/zwaldowski) @see NSSet(BlocksKit) */ @interface NSMutableSet (BlocksKit) /** Filters a mutable set to the objects matching the block. @param block A single-argument, BOOL-returning code block. @see bk_reject: */ - (void)bk_performSelect:(BOOL (^)(id obj))block; /** Filters a mutable set to all objects but the ones matching the block, the logical inverse to bk_select:. @param block A single-argument, BOOL-returning code block. @see bk_select: */ - (void)bk_performReject:(BOOL (^)(id obj))block; /** Transform the objects in the set to the results of the block. This is sometimes referred to as a transform, mutating one of each object: [controllers bk_map:^id(id obj) { return [obj view]; }]; @param block A single-argument, object-returning code block. @see bk_map: */ - (void)bk_performMap:(id (^)(id obj))block; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSMutableSet+BlocksKit.m ================================================ // // NSMutableSet+BlocksKit.m // BlocksKit // #import "NSMutableSet+BlocksKit.h" @implementation NSMutableSet (BlocksKit) - (void)bk_performSelect:(BOOL (^)(id obj))block { NSParameterAssert(block != nil); NSSet *list = [self objectsPassingTest:^BOOL(id obj, BOOL *stop) { return block(obj); }]; [self setSet:list]; } - (void)bk_performReject:(BOOL (^)(id obj))block { NSParameterAssert(block != nil); [self bk_performSelect:^BOOL(id obj) { return !block(obj); }]; } - (void)bk_performMap:(id (^)(id obj))block { NSParameterAssert(block != nil); NSMutableSet *new = [NSMutableSet setWithCapacity:self.count]; [self enumerateObjectsUsingBlock:^(id obj, BOOL *stop) { id value = block(obj); if (!value) return; [new addObject:value]; }]; [self setSet:new]; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSObject+BKAssociatedObjects.h ================================================ // // NSObject+BKAssociatedObjects.h // BlocksKit // #import /** Objective-C wrapper for 10.6+ associated object API. In Mac OS X Snow Leopard and iOS 3.0, Apple introduced an addition to the Objective-C Runtime called associated objects. Associated objects allow for the pairing of a random key and object pair to be saved on an instance. In BlocksKit, associated objects allow us to emulate instance variables in the ategories we use. Class methods also exist for each association. These associations are unique to each class, and exist for the lifetime of the application unless set to `nil`. Each class is a unique meta-object; the ultimate singleton. Created by [Andy Matuschak](https://github.com/andymatuschak) as `AMAssociatedObjects`. */ @interface NSObject (BKAssociatedObjects) /** Strongly associates an object with the reciever. The associated value is retained as if it were a property synthesized with `nonatomic` and `retain`. Using retained association is strongly recommended for most Objective-C object derivative of NSObject, particularly when it is subject to being externally released or is in an `NSAutoreleasePool`. @param value Any object. @param key A unique key pointer. */ - (void)bk_associateValue:(id)value withKey:(const void *)key; /** Strongly associates an object with the receiving class. @see associateValue:withKey: @param value Any object. @param key A unique key pointer. */ + (void)bk_associateValue:(id)value withKey:(const void *)key; /** Strongly, thread-safely associates an object with the reciever. The associated value is retained as if it were a property synthesized with `atomic` and `retain`. Using retained association is strongly recommended for most Objective-C object derivative of NSObject, particularly when it is subject to being externally released or is in an `NSAutoreleasePool`. @see associateValue:withKey: @param value Any object. @param key A unique key pointer. */ - (void)bk_atomicallyAssociateValue:(id)value withKey:(const void *)key; /** Strongly, thread-safely associates an object with the receiving class. @see associateValue:withKey: @param value Any object. @param key A unique key pointer. */ + (void)bk_atomicallyAssociateValue:(id)value withKey:(const void *)key; /** Associates a copy of an object with the reciever. The associated value is copied as if it were a property synthesized with `nonatomic` and `copy`. Using copied association is recommended for a block or otherwise `NSCopying`-compliant instances like NSString. @param value Any object, pointer, or value. @param key A unique key pointer. */ - (void)bk_associateCopyOfValue:(id)value withKey:(const void *)key; /** Associates a copy of an object with the receiving class. @see associateCopyOfValue:withKey: @param value Any object, pointer, or value. @param key A unique key pointer. */ + (void)bk_associateCopyOfValue:(id)value withKey:(const void *)key; /** Thread-safely associates a copy of an object with the reciever. The associated value is copied as if it were a property synthesized with `atomic` and `copy`. Using copied association is recommended for a block or otherwise `NSCopying`-compliant instances like NSString. @see associateCopyOfValue:withKey: @param value Any object, pointer, or value. @param key A unique key pointer. */ - (void)bk_atomicallyAssociateCopyOfValue:(id)value withKey:(const void *)key; /** Thread-safely associates a copy of an object with the receiving class. @see associateCopyOfValue:withKey: @param value Any object, pointer, or value. @param key A unique key pointer. */ + (void)bk_atomicallyAssociateCopyOfValue:(id)value withKey:(const void *)key; /** Weakly associates an object with the reciever. A weak association will cause the pointer to be set to zero or nil upon the disappearance of what it references; in other words, the associated object is not kept alive. @param value Any object. @param key A unique key pointer. */ - (void)bk_weaklyAssociateValue:(__autoreleasing id)value withKey:(const void *)key; /** Weakly associates an object with the receiving class. @see weaklyAssociateValue:withKey: @param value Any object. @param key A unique key pointer. */ + (void)bk_weaklyAssociateValue:(__autoreleasing id)value withKey:(const void *)key; /** Returns the associated value for a key on the reciever. @param key A unique key pointer. @return The object associated with the key, or `nil` if not found. */ - (id)bk_associatedValueForKey:(const void *)key; /** Returns the associated value for a key on the receiving class. @see associatedValueForKey: @param key A unique key pointer. @return The object associated with the key, or `nil` if not found. */ + (id)bk_associatedValueForKey:(const void *)key; /** Returns the reciever to a clean state by removing all associated objects, releasing them if necessary. */ - (void)bk_removeAllAssociatedObjects; /** Returns the recieving class to a clean state by removing all associated objects, releasing them if necessary. */ + (void)bk_removeAllAssociatedObjects; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSObject+BKAssociatedObjects.m ================================================ // // NSObject+BKAssociatedObjects.m // BlocksKit // #import #import "NSObject+BKAssociatedObjects.h" #pragma mark - Weak support @interface _BKWeakAssociatedObject : NSObject @property (nonatomic, weak) id value; @end @implementation _BKWeakAssociatedObject @end @implementation NSObject (BKAssociatedObjects) #pragma mark - Instance Methods - (void)bk_associateValue:(id)value withKey:(const void *)key { objc_setAssociatedObject(self, key, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (void)bk_atomicallyAssociateValue:(id)value withKey:(const void *)key { objc_setAssociatedObject(self, key, value, OBJC_ASSOCIATION_RETAIN); } - (void)bk_associateCopyOfValue:(id)value withKey:(const void *)key { objc_setAssociatedObject(self, key, value, OBJC_ASSOCIATION_COPY_NONATOMIC); } - (void)bk_atomicallyAssociateCopyOfValue:(id)value withKey:(const void *)key { objc_setAssociatedObject(self, key, value, OBJC_ASSOCIATION_COPY); } - (void)bk_weaklyAssociateValue:(__autoreleasing id)value withKey:(const void *)key { _BKWeakAssociatedObject *assoc = objc_getAssociatedObject(self, key); if (!assoc) { assoc = [_BKWeakAssociatedObject new]; [self bk_associateValue:assoc withKey:key]; } assoc.value = value; } - (id)bk_associatedValueForKey:(const void *)key { id value = objc_getAssociatedObject(self, key); if (value && [value isKindOfClass:[_BKWeakAssociatedObject class]]) { return [(_BKWeakAssociatedObject *)value value]; } return value; } - (void)bk_removeAllAssociatedObjects { objc_removeAssociatedObjects(self); } #pragma mark - Class Methods + (void)bk_associateValue:(id)value withKey:(const void *)key { objc_setAssociatedObject(self, key, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } + (void)bk_atomicallyAssociateValue:(id)value withKey:(const void *)key { objc_setAssociatedObject(self, key, value, OBJC_ASSOCIATION_RETAIN); } + (void)bk_associateCopyOfValue:(id)value withKey:(const void *)key { objc_setAssociatedObject(self, key, value, OBJC_ASSOCIATION_COPY_NONATOMIC); } + (void)bk_atomicallyAssociateCopyOfValue:(id)value withKey:(const void *)key { objc_setAssociatedObject(self, key, value, OBJC_ASSOCIATION_COPY); } + (void)bk_weaklyAssociateValue:(__autoreleasing id)value withKey:(const void *)key { _BKWeakAssociatedObject *assoc = objc_getAssociatedObject(self, key); if (!assoc) { assoc = [_BKWeakAssociatedObject new]; [self bk_associateValue:assoc withKey:key]; } assoc.value = value; } + (id)bk_associatedValueForKey:(const void *)key { id value = objc_getAssociatedObject(self, key); if (value && [value isKindOfClass:[_BKWeakAssociatedObject class]]) { return [(_BKWeakAssociatedObject *)value value]; } return value; } + (void)bk_removeAllAssociatedObjects { objc_removeAssociatedObjects(self); } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSObject+BKBlockExecution.h ================================================ // // NSObject+BKBlockExecution.h // BlocksKit // #import /** Block execution on *any* object. This category overhauls the `performSelector:` utilities on NSObject to instead use blocks. Not only are the blocks performed extremely speedily, thread-safely, and asynchronously using Grand Central Dispatch, but each convenience method also returns a pointer that can be used to cancel the execution before it happens! Includes code by the following: - [Peter Steinberger](https://github.com/steipete) - [Zach Waldowski](https://github.com/zwaldowski) */ @interface NSObject (BKBlockExecution) /** Executes a block after a given delay on the reciever. [array performBlock:^(id obj) { [obj addObject:self]; [self release]; } afterDelay:0.5f]; @warning *Important:* Use of the **self** reference in a block will reference the current implementation context. The block argument, `obj`, should be used instead. @param block A single-argument code block, where `obj` is the reciever. @param delay A measure in seconds. @return Returns a pointer to the block that may or may not execute the given block. */ - (id)bk_performBlock:(void (^)(id obj))block afterDelay:(NSTimeInterval)delay; /** Executes a block after a given delay. This class method is functionally identical to its instance method version. It still executes asynchronously via GCD. However, the current context is not passed so that the block is performed in a general context. Block execution is very useful, particularly for small events that you would like delayed. [object performBlock:^{ [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; } afterDelay:0.5f]; @see performBlock:afterDelay: @param block A code block. @param delay A measure in seconds. @return Returns a pointer to the block that may or may not execute the given block. */ + (id)bk_performBlock:(void (^)(void))block afterDelay:(NSTimeInterval)delay; /** Executes a block in the background after a given delay on the receiver. This class method is functionally identical to `- (id)bk_performBlock:afterDelay:`, except the block will be performed on a background thread instead of the main thread. @see performBlock:afterDelay: @param block A code block. @param delay A measure in seconds. @return Returns a pointer to the block that may or may not execute the given block. */ - (id)bk_performBlockInBackground:(void (^)(id obj))block afterDelay:(NSTimeInterval)delay; /** Executes a block in the background after a given delay. This class method is functionally identical to `+ (id)bk_performBlock:afterDelay:`, except the block will be performed on a background thread instead of the main thread. @see performBlock:afterDelay: @param block A code block. @param delay A measure in seconds. @return Returns a pointer to the block that may or may not execute the given block. */ + (id)bk_performBlockInBackground:(void (^)(void))block afterDelay:(NSTimeInterval)delay; /** Executes a block in the background after a given delay. This class method is functionally identical to `+ (id)bk_performBlock:afterDelay:`, except the block will be performed on the specified thread instead of the main thread. @see performBlock:afterDelay: @param block A code block. @param queue A background queue. @param delay A measure in seconds. @return Returns a pointer to the block that may or may not execute the given block. */ + (id)bk_performBlock:(void (^)(void))block onQueue:(dispatch_queue_t)queue afterDelay:(NSTimeInterval)delay; /** Executes a block in the background after a given delay. This class method is functionally identical to `- (id)bk_performBlock:afterDelay:`, except the block will be performed on the specified thread instead of the main thread. @see performBlock:afterDelay: @param block A code block. @param queue A background queue. @param delay A measure in seconds. @return Returns a pointer to the block that may or may not execute the given block. */ - (id)bk_performBlock:(void (^)(id obj))block onQueue:(dispatch_queue_t)queue afterDelay:(NSTimeInterval)delay; /** Cancels the potential execution of a block. @warning *Important:* It is not recommended to cancel a block executed with no delay (a delay of 0.0). While it it still possible to catch the block before GCD has executed it, it has likely already been executed and disposed of. @param block A pointer to a containing block, as returned from one of the `performBlock` selectors. */ + (void)bk_cancelBlock:(id)block; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSObject+BKBlockExecution.m ================================================ // // NSObject+BKBlockExecution.m // BlocksKit // #import "NSObject+BKBlockExecution.h" #define BKTimeDelay(t) dispatch_time(DISPATCH_TIME_NOW, (uint64_t)(NSEC_PER_SEC * t)) @implementation NSObject (BlocksKit) - (id)bk_performBlock:(void (^)(id obj))block afterDelay:(NSTimeInterval)delay { return [self bk_performBlock:block onQueue:dispatch_get_main_queue() afterDelay:delay]; } + (id)bk_performBlock:(void (^)(void))block afterDelay:(NSTimeInterval)delay { return [NSObject bk_performBlock:block onQueue:dispatch_get_main_queue() afterDelay:delay]; } - (id)bk_performBlockInBackground:(void (^)(id obj))block afterDelay:(NSTimeInterval)delay { return [self bk_performBlock:block onQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0) afterDelay:delay]; } + (id)bk_performBlockInBackground:(void (^)(void))block afterDelay:(NSTimeInterval)delay { return [NSObject bk_performBlock:block onQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0) afterDelay:delay]; } - (id)bk_performBlock:(void (^)(id obj))block onQueue:(dispatch_queue_t)queue afterDelay:(NSTimeInterval)delay { NSParameterAssert(block != nil); __block BOOL cancelled = NO; void (^wrapper)(BOOL) = ^(BOOL cancel) { if (cancel) { cancelled = YES; return; } if (!cancelled) block(self); }; dispatch_after(BKTimeDelay(delay), queue, ^{ wrapper(NO); }); return [wrapper copy]; } + (id)bk_performBlock:(void (^)(void))block onQueue:(dispatch_queue_t)queue afterDelay:(NSTimeInterval)delay { NSParameterAssert(block != nil); __block BOOL cancelled = NO; void (^wrapper)(BOOL) = ^(BOOL cancel) { if (cancel) { cancelled = YES; return; } if (!cancelled) block(); }; dispatch_after(BKTimeDelay(delay), queue, ^{ wrapper(NO); }); return [wrapper copy]; } + (void)bk_cancelBlock:(id)block { NSParameterAssert(block != nil); void (^wrapper)(BOOL) = block; wrapper(YES); } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSObject+BKBlockObservation.h ================================================ // // NSObject+BKBlockObservation.h // BlocksKit // #import /** Blocks wrapper for key-value observation. In Mac OS X Panther, Apple introduced an API called "key-value observing." It implements an [observer pattern](http://en.wikipedia.org/wiki/Observer_pattern), where an object will notify observers of any changes in state. NSNotification is a rudimentary form of this design style; KVO, however, allows for the observation of any change in key-value state. The API for key-value observation, however, is flawed, ugly, and lengthy. Like most of the other block abilities in BlocksKit, observation saves and a bunch of code and a bunch of potential bugs. Includes code by the following: - [Andy Matuschak](https://github.com/andymatuschak) - [Jon Sterling](https://github.com/jonsterling) - [Zach Waldowski](https://github.com/zwaldowski) - [Jonathan Wight](https://github.com/schwa) */ @interface NSObject (BlockObservation) /** Adds an observer to an object conforming to NSKeyValueObserving. Adds a block observer that executes a block upon a state change. @param keyPath The property to observe, relative to the reciever. @param task A block with no return argument, and a single parameter: the reciever. @return Returns a globally unique process identifier for removing observation with removeObserverWithBlockToken:. @see addObserverForKeyPath:identifier:options:task: */ - (NSString *)bk_addObserverForKeyPath:(NSString *)keyPath task:(void (^)(id target))task; /** Adds an observer to an object conforming to NSKeyValueObserving. Adds a block observer that executes the same block upon multiple state changes. @param keyPaths An array of properties to observe, relative to the reciever. @param task A block with no return argument and two parameters: the reciever and the key path of the value change. @return A unique identifier for removing observation with removeObserverWithBlockToken:. @see addObserverForKeyPath:identifier:options:task: */ - (NSString *)bk_addObserverForKeyPaths:(NSArray *)keyPaths task:(void (^)(id obj, NSString *keyPath))task; /** Adds an observer to an object conforming to NSKeyValueObserving. Adds a block observer that executes a block upon a state change with specific options. @param keyPath The property to observe, relative to the reciever. @param options The NSKeyValueObservingOptions to use. @param task A block with no return argument and two parameters: the reciever and the change dictionary. @return Returns a globally unique process identifier for removing observation with removeObserverWithBlockToken:. @see addObserverForKeyPath:identifier:options:task: */ - (NSString *)bk_addObserverForKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options task:(void (^)(id obj, NSDictionary *change))task; /** Adds an observer to an object conforming to NSKeyValueObserving. Adds a block observer that executes the same block upon multiple state changes with specific options. @param keyPaths An array of properties to observe, relative to the reciever. @param options The NSKeyValueObservingOptions to use. @param task A block with no return argument and three parameters: the reciever, the key path of the value change, and the change dictionary. @return A unique identifier for removing observation with removeObserverWithBlockToken:. @see addObserverForKeyPath:identifier:options:task: */ - (NSString *)bk_addObserverForKeyPaths:(NSArray *)keyPaths options:(NSKeyValueObservingOptions)options task:(void (^)(id obj, NSString *keyPath, NSDictionary *change))task; /** Adds an observer to an object conforming to NSKeyValueObserving. Adds a block observer that executes the block upon a state change. @param keyPath The property to observe, relative to the reciever. @param token An identifier for the observation block. @param options The NSKeyValueObservingOptions to use. @param task A block responding to the reciever and the KVO change. observation with removeObserverWithBlockToken:. @see addObserverForKeyPath:task: */ - (void)bk_addObserverForKeyPath:(NSString *)keyPath identifier:(NSString *)token options:(NSKeyValueObservingOptions)options task:(void (^)(id obj, NSDictionary *change))task; /** Adds an observer to an object conforming to NSKeyValueObserving. Adds a block observer that executes the same block upon multiple state changes. @param keyPaths An array of properties to observe, relative to the reciever. @param token An identifier for the observation block. @param options The NSKeyValueObservingOptions to use. @param task A block responding to the reciever, the key path, and the KVO change. observation with removeObserversWithIdentifier:. @see addObserverForKeyPath:task: */ - (void)bk_addObserverForKeyPaths:(NSArray *)keyPaths identifier:(NSString *)token options:(NSKeyValueObservingOptions)options task:(void (^)(id obj, NSString *keyPath, NSDictionary *change))task; /** Removes a block observer. @param keyPath The property to stop observing, relative to the reciever. @param token The unique key returned by addObserverForKeyPath:task: or the identifier given in addObserverForKeyPath:identifier:task:. @see removeObserversWithIdentifier: */ - (void)bk_removeObserverForKeyPath:(NSString *)keyPath identifier:(NSString *)token; /** Removes multiple block observers with a certain identifier. @param token A unique key returned by addObserverForKeyPath:task: and addObserverForKeyPaths:task: or the identifier given in addObserverForKeyPath:identifier:task: and addObserverForKeyPaths:identifier:task:. @see removeObserverForKeyPath:identifier: */ - (void)bk_removeObserversWithIdentifier:(NSString *)token; /** Remove all registered block observers. */ - (void)bk_removeAllBlockObservers; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSObject+BKBlockObservation.m ================================================ // // NSObject+BKBlockObservation.m // BlocksKit // #import #import #import "NSArray+BlocksKit.h" #import "NSDictionary+BlocksKit.h" #import "NSObject+BKAssociatedObjects.h" #import "NSObject+BKBlockObservation.h" #import "NSSet+BlocksKit.h" typedef NS_ENUM(int, BKObserverContext) { BKObserverContextKey, BKObserverContextKeyWithChange, BKObserverContextManyKeys, BKObserverContextManyKeysWithChange }; @interface _BKObserver : NSObject { BOOL _isObserving; } @property (nonatomic, readonly, unsafe_unretained) id observee; @property (nonatomic, readonly) NSMutableArray *keyPaths; @property (nonatomic, readonly) id task; @property (nonatomic, readonly) BKObserverContext context; - (id)initWithObservee:(id)observee keyPaths:(NSArray *)keyPaths context:(BKObserverContext)context task:(id)task; @end static void *BKObserverBlocksKey = &BKObserverBlocksKey; static void *BKBlockObservationContext = &BKBlockObservationContext; @implementation _BKObserver - (id)initWithObservee:(id)observee keyPaths:(NSArray *)keyPaths context:(BKObserverContext)context task:(id)task { if ((self = [super init])) { _observee = observee; _keyPaths = [keyPaths mutableCopy]; _context = context; _task = [task copy]; } return self; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context != BKBlockObservationContext) return; @synchronized(self) { switch (self.context) { case BKObserverContextKey: { void (^task)(id) = self.task; task(object); break; } case BKObserverContextKeyWithChange: { void (^task)(id, NSDictionary *) = self.task; task(object, change); break; } case BKObserverContextManyKeys: { void (^task)(id, NSString *) = self.task; task(object, keyPath); break; } case BKObserverContextManyKeysWithChange: { void (^task)(id, NSString *, NSDictionary *) = self.task; task(object, keyPath, change); break; } } } } - (void)startObservingWithOptions:(NSKeyValueObservingOptions)options { @synchronized(self) { if (_isObserving) return; [self.keyPaths bk_each:^(NSString *keyPath) { [self.observee addObserver:self forKeyPath:keyPath options:options context:BKBlockObservationContext]; }]; _isObserving = YES; } } - (void)stopObservingKeyPath:(NSString *)keyPath { NSParameterAssert(keyPath); @synchronized (self) { if (!_isObserving) return; if (![self.keyPaths containsObject:keyPath]) return; NSObject *observee = self.observee; if (!observee) return; [self.keyPaths removeObject: keyPath]; keyPath = [keyPath copy]; if (!self.keyPaths.count) { _task = nil; _observee = nil; _keyPaths = nil; } [observee removeObserver:self forKeyPath:keyPath context:BKBlockObservationContext]; } } - (void)_stopObservingLocked { if (!_isObserving) return; _task = nil; NSObject *observee = self.observee; NSArray *keyPaths = [self.keyPaths copy]; _observee = nil; _keyPaths = nil; [keyPaths bk_each:^(NSString *keyPath) { [observee removeObserver:self forKeyPath:keyPath context:BKBlockObservationContext]; }]; } - (void)stopObserving { if (_observee == nil) return; @synchronized (self) { [self _stopObservingLocked]; } } - (void)dealloc { if (self.keyPaths) { [self _stopObservingLocked]; } } @end @implementation NSObject (BlockObservation) - (NSString *)bk_addObserverForKeyPath:(NSString *)keyPath task:(void (^)(id target))task { NSString *token = [[NSProcessInfo processInfo] globallyUniqueString]; [self bk_addObserverForKeyPaths:@[ keyPath ] identifier:token options:0 context:BKObserverContextKey task:task]; return token; } - (NSString *)bk_addObserverForKeyPaths:(NSArray *)keyPaths task:(void (^)(id obj, NSString *keyPath))task { NSString *token = [[NSProcessInfo processInfo] globallyUniqueString]; [self bk_addObserverForKeyPaths:keyPaths identifier:token options:0 context:BKObserverContextManyKeys task:task]; return token; } - (NSString *)bk_addObserverForKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options task:(void (^)(id obj, NSDictionary *change))task { NSString *token = [[NSProcessInfo processInfo] globallyUniqueString]; [self bk_addObserverForKeyPath:keyPath identifier:token options:options task:task]; return token; } - (NSString *)bk_addObserverForKeyPaths:(NSArray *)keyPaths options:(NSKeyValueObservingOptions)options task:(void (^)(id obj, NSString *keyPath, NSDictionary *change))task { NSString *token = [[NSProcessInfo processInfo] globallyUniqueString]; [self bk_addObserverForKeyPaths:keyPaths identifier:token options:options task:task]; return token; } - (void)bk_addObserverForKeyPath:(NSString *)keyPath identifier:(NSString *)identifier options:(NSKeyValueObservingOptions)options task:(void (^)(id obj, NSDictionary *change))task { BKObserverContext context = (options == 0) ? BKObserverContextKey : BKObserverContextKeyWithChange; [self bk_addObserverForKeyPaths:@[keyPath] identifier:identifier options:options context:context task:task]; } - (void)bk_addObserverForKeyPaths:(NSArray *)keyPaths identifier:(NSString *)identifier options:(NSKeyValueObservingOptions)options task:(void (^)(id obj, NSString *keyPath, NSDictionary *change))task { BKObserverContext context = (options == 0) ? BKObserverContextManyKeys : BKObserverContextManyKeysWithChange; [self bk_addObserverForKeyPaths:keyPaths identifier:identifier options:options context:context task:task]; } - (void)bk_removeObserverForKeyPath:(NSString *)keyPath identifier:(NSString *)token { NSParameterAssert(keyPath.length); NSParameterAssert(token.length); NSMutableDictionary *dict; @synchronized (self) { dict = [self bk_observerBlocks]; if (!dict) return; } _BKObserver *observer = dict[token]; [observer stopObservingKeyPath:keyPath]; if (observer.keyPaths.count == 0) { [dict removeObjectForKey:token]; } if (dict.count == 0) [self bk_setObserverBlocks:nil]; } - (void)bk_removeObserversWithIdentifier:(NSString *)token { NSParameterAssert(token); NSMutableDictionary *dict; @synchronized (self) { dict = [self bk_observerBlocks]; if (!dict) return; } _BKObserver *observer = dict[token]; [observer stopObserving]; [dict removeObjectForKey:token]; if (dict.count == 0) [self bk_setObserverBlocks:nil]; } - (void)bk_removeAllBlockObservers { NSDictionary *dict; @synchronized (self) { dict = [[self bk_observerBlocks] copy]; [self bk_setObserverBlocks:nil]; } [dict.allValues bk_each:^(_BKObserver *trampoline) { [trampoline stopObserving]; }]; } #pragma mark - "Private"s + (NSMutableSet *)bk_observedClassesHash { static dispatch_once_t onceToken; static NSMutableSet *swizzledClasses = nil; dispatch_once(&onceToken, ^{ swizzledClasses = [[NSMutableSet alloc] init]; }); return swizzledClasses; } - (void)bk_addObserverForKeyPaths:(NSArray *)keyPaths identifier:(NSString *)identifier options:(NSKeyValueObservingOptions)options context:(BKObserverContext)context task:(id)task { NSParameterAssert(keyPaths.count); NSParameterAssert(identifier.length); NSParameterAssert(task); Class classToSwizzle = self.class; NSMutableSet *classes = self.class.bk_observedClassesHash; @synchronized (classes) { NSString *className = NSStringFromClass(classToSwizzle); if (![classes containsObject:className]) { SEL deallocSelector = sel_registerName("dealloc"); __block void (*originalDealloc)(__unsafe_unretained id, SEL) = NULL; id newDealloc = ^(__unsafe_unretained id objSelf) { [objSelf bk_removeAllBlockObservers]; if (originalDealloc == NULL) { struct objc_super superInfo = { .receiver = objSelf, .super_class = class_getSuperclass(classToSwizzle) }; void (*msgSend)(struct objc_super *, SEL) = (__typeof__(msgSend))objc_msgSendSuper; msgSend(&superInfo, deallocSelector); } else { originalDealloc(objSelf, deallocSelector); } }; IMP newDeallocIMP = imp_implementationWithBlock(newDealloc); if (!class_addMethod(classToSwizzle, deallocSelector, newDeallocIMP, "v@:")) { // The class already contains a method implementation. Method deallocMethod = class_getInstanceMethod(classToSwizzle, deallocSelector); // We need to store original implementation before setting new implementation // in case method is called at the time of setting. originalDealloc = (void(*)(__unsafe_unretained id, SEL))method_getImplementation(deallocMethod); // We need to store original implementation again, in case it just changed. originalDealloc = (void(*)(__unsafe_unretained id, SEL))method_setImplementation(deallocMethod, newDeallocIMP); } [classes addObject:className]; } } NSMutableDictionary *dict; _BKObserver *observer = [[_BKObserver alloc] initWithObservee:self keyPaths:keyPaths context:context task:task]; [observer startObservingWithOptions:options]; @synchronized (self) { dict = [self bk_observerBlocks]; if (dict == nil) { dict = [NSMutableDictionary dictionary]; [self bk_setObserverBlocks:dict]; } } dict[identifier] = observer; } - (void)bk_setObserverBlocks:(NSMutableDictionary *)dict { [self bk_associateValue:dict withKey:BKObserverBlocksKey]; } - (NSMutableDictionary *)bk_observerBlocks { return [self bk_associatedValueForKey:BKObserverBlocksKey]; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSOrderedSet+BlocksKit.h ================================================ // // NSOrderedSet+BlocksKit.h // BlocksKit // #import /** Block extensions for NSOrderedSet. Both inspired by and resembling Smalltalk syntax, these utilities allow for iteration through an ordered set (also known as a uniqued array) in a concise way that saves a ton of boilerplate code for filtering or finding objects. Includes code by the following: - Robin Lu. . 2009. - Michael Ash. . 2010. BSD. - Aleks Nesterow. . 2010. BSD. - Zach Waldowski. . 2011. @see NSArray(BlocksKit) @see NSSet(BlocksKit) */ @interface NSOrderedSet (BlocksKit) /** Loops through an ordered set and executes the given block with each object. @param block A single-argument, void-returning code block. */ - (void)bk_each:(void (^)(id obj))block; /** Enumerates through an ordered set concurrently and executes the given block once for each object. Enumeration will occur on appropriate background queues. This will have a noticeable speed increase, especially on multi-core devices, but you *must* be aware of the thread safety of the objects you message from within the block. Be aware that the order of objects is not necessarily the order each block will be called in. @param block A single-argument, void-returning code block. */ - (void)bk_apply:(void (^)(id obj))block; /** Loops through an ordered set to find the object matching the block. bk_match: is functionally identical to bk_select:, but will stop and return on the first match. @param block A single-argument, `BOOL`-returning code block. @return Returns the object, if found, or `nil`. @see bk_select: */ - (id)bk_match:(BOOL (^)(id obj))block; /** Loops through an ordered set to find the objects matching the block. @param block A single-argument, BOOL-returning code block. @return Returns an ordered set of the objects found. @see bk_match: */ - (NSOrderedSet *)bk_select:(BOOL (^)(id obj))block; /** Loops through an ordered set to to find the objects not matching the block. This selector performs *literally* the exact same function as bk_select: but in reverse. This is useful, as one may expect, for removing objects from an ordered set to. NSOrderedSet *new = [computers bk_reject:^BOOL(id obj) { return ([obj isUgly]); }]; @param block A single-argument, BOOL-returning code block. @return Returns an ordered set of all objects not found. */ - (NSOrderedSet *)bk_reject:(BOOL (^)(id obj))block; /** Call the block once for each object and create an ordered set of the return values. This is sometimes referred to as a transform, mutating one of each object: NSOrderedSet *new = [stringArray bk_map:^id(id obj) { return [obj stringByAppendingString:@".png"]); }]; @param block A single-argument, object-returning code block. @return Returns an ordered set of the objects returned by the block. */ - (NSOrderedSet *)bk_map:(id (^)(id obj))block; /** Arbitrarily accumulate objects using a block. The concept of this selector is difficult to illustrate in words. The sum can be any NSObject, including (but not limited to) a string, number, or value. For example, you can concentate the strings in an ordered set: NSString *concentrated = [stringArray bk_reduce:@"" withBlock:^id(id sum, id obj) { return [sum stringByAppendingString:obj]; }]; You can also do something like summing the lengths of strings in an ordered set: NSUInteger value = [[[stringArray bk_reduce:nil withBlock:^id(id sum, id obj) { return @([sum integerValue] + obj.length); }]] unsignedIntegerValue]; @param initial The value of the reduction at its start. @param block A block that takes the current sum and the next object to return the new sum. @return An accumulated value. */ - (id)bk_reduce:(id)initial withBlock:(id (^)(id sum, id obj))block; /** Loops through an ordered set to find whether any object matches the block. This method is similar to the Scala list `exists`. It is functionally identical to bk_match: but returns a `BOOL` instead. It is not recommended to use bk_any: as a check condition before executing bk_match:, since it would require two loops through the ordered set. For example, you can find if a string in an ordered set starts with a certain letter: NSString *letter = @"A"; BOOL containsLetter = [stringArray bk_any:^(id obj) { return [obj hasPrefix:@"A"]; }]; @param block A single-argument, BOOL-returning code block. @return YES for the first time the block returns YES for an object, NO otherwise. */ - (BOOL)bk_any:(BOOL (^)(id obj))block; /** Loops through an ordered set to find whether no objects match the block. This selector performs *literally* the exact same function as bk_all: but in reverse. @param block A single-argument, BOOL-returning code block. @return YES if the block returns NO for all objects in the ordered set, NO otherwise. */ - (BOOL)bk_none:(BOOL (^)(id obj))block; /** Loops through an ordered set to find whether all objects match the block. @param block A single-argument, BOOL-returning code block. @return YES if the block returns YES for all objects in the ordered set, NO otherwise. */ - (BOOL)bk_all:(BOOL (^)(id obj))block; /** Tests whether every element of this ordered set relates to the corresponding element of another array according to match by block. For example, finding if a list of numbers corresponds to their sequenced string values; NSArray *numbers = @[ @(1), @(2), @(3) ]; NSArray *letters = @[ @"1", @"2", @"3" ]; BOOL doesCorrespond = [numbers bk_corresponds:letters withBlock:^(id number, id letter) { return [[number stringValue] isEqualToString:letter]; }]; @param list An array of objects to compare with. @param block A two-argument, BOOL-returning code block. @return Returns a BOOL, true if every element of the ordered set relates to corresponding element in another ordered set. */ - (BOOL)bk_corresponds:(NSOrderedSet *)list withBlock:(BOOL (^)(id obj1, id obj2))block; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSOrderedSet+BlocksKit.m ================================================ // // NSOrderedSet+BlocksKit.m // BlocksKit // #import "NSOrderedSet+BlocksKit.h" @implementation NSOrderedSet (BlocksKit) - (void)bk_each:(void (^)(id obj))block { NSParameterAssert(block != nil); [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { block(obj); }]; } - (void)bk_apply:(void (^)(id obj))block { NSParameterAssert(block != nil); [self enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id obj, NSUInteger idx, BOOL *stop) { block(obj); }]; } - (id)bk_match:(BOOL (^)(id obj))block { NSParameterAssert(block != nil); NSUInteger index = [self indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) { return block(obj); }]; if (index == NSNotFound) return nil; return self[index]; } - (NSOrderedSet *)bk_select:(BOOL (^)(id obj))block { NSParameterAssert(block != nil); NSArray *objects = [self objectsAtIndexes:[self indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) { return block(obj); }]]; if (!objects.count) return [[self class] orderedSet]; return [[self class] orderedSetWithArray:objects]; } - (NSOrderedSet *)bk_reject:(BOOL (^)(id obj))block { NSParameterAssert(block != nil); return [self bk_select:^BOOL(id obj) { return !block(obj); }]; } - (NSOrderedSet *)bk_map:(id (^)(id obj))block { NSParameterAssert(block != nil); NSMutableOrderedSet *result = [NSMutableOrderedSet orderedSetWithCapacity:self.count]; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { id value = block(obj) ?: [NSNull null]; [result addObject:value]; }]; return result; } - (id)bk_reduce:(id)initial withBlock:(id (^)(id sum, id obj))block { NSParameterAssert(block != nil); __block id result = initial; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { result = block(result, obj); }]; return result; } - (BOOL)bk_any:(BOOL (^)(id obj))block { return [self bk_match:block] != nil; } - (BOOL)bk_none:(BOOL (^)(id obj))block { return [self bk_match:block] == nil; } - (BOOL)bk_all:(BOOL (^)(id obj))block { NSParameterAssert(block != nil); __block BOOL result = YES; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { if (!block(obj)) { result = NO; *stop = YES; } }]; return result; } - (BOOL)bk_corresponds:(NSOrderedSet *)list withBlock:(BOOL (^)(id obj1, id obj2))block { NSParameterAssert(block != nil); __block BOOL result = NO; [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { if (idx < list.count) { id obj2 = list[idx]; result = block(obj, obj2); } else { result = NO; } *stop = !result; }]; return result; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSSet+BlocksKit.h ================================================ // // NSSet+BlocksKit.h // BlocksKit // #import /** Block extensions for NSSet. Both inspired by and resembling Smalltalk syntax, these utilities allows for iteration of a set in a logical way that saves quite a bit of boilerplate code for filtering or finding objects or an object. Includes code by the following: - [Michael Ash](https://github.com/mikeash) - [Corey Floyd](https://github.com/coreyfloyd) - [Aleks Nesterow](https://github.com/nesterow) - [Zach Waldowski](https://github.com/zwaldowski) @see NSArray(BlocksKit) @see NSDictionary(BlocksKit) */ @interface NSSet (BlocksKit) /** Loops through a set and executes the given block with each object. @param block A single-argument, void-returning code block. */ - (void)bk_each:(void (^)(id obj))block; /** Enumerates through a set concurrently and executes the given block once for each object. Enumeration will occur on appropriate background queues. This will have a noticeable speed increase, especially on dual-core devices, but you *must* be aware of the thread safety of the objects you message from within the block. @param block A single-argument, void-returning code block. */ - (void)bk_apply:(void (^)(id obj))block; /** Loops through a set to find the object matching the block. bk_match: is functionally identical to bk_select:, but will stop and return on the first match. @param block A single-argument, BOOL-returning code block. @return Returns the object if found, `nil` otherwise. @see bk_select: */ - (id)bk_match:(BOOL (^)(id obj))block; /** Loops through a set to find the objects matching the block. @param block A single-argument, BOOL-returning code block. @return Returns a set of the objects found. @see bk_match: */ - (NSSet *)bk_select:(BOOL (^)(id obj))block; /** Loops through a set to find the objects not matching the block. This selector performs *literally* the exact same function as select, but in reverse. This is useful, as one may expect, for removing objects from a set: NSSet *new = [reusableWebViews bk_reject:^BOOL(id obj) { return ([obj isLoading]); }]; @param block A single-argument, BOOL-returning code block. @return Returns an array of all objects not found. */ - (NSSet *)bk_reject:(BOOL (^)(id obj))block; /** Call the block once for each object and create a set of the return values. This is sometimes referred to as a transform, mutating one of each object: NSSet *new = [mimeTypes bk_map:^id(id obj) { return [@"x-company-" stringByAppendingString:obj]); }]; @param block A single-argument, object-returning code block. @return Returns a set of the objects returned by the block. */ - (NSSet *)bk_map:(id (^)(id obj))block; /** Arbitrarily accumulate objects using a block. The concept of this selector is difficult to illustrate in words. The sum can be any NSObject, including (but not limited to) a string, number, or value. You can also do something like summing the count of an item: NSUInteger numberOfBodyParts = [[bodyList bk_reduce:nil withBlock:^id(id sum, id obj) { return @([sum integerValue] + obj.numberOfAppendages); }] unsignedIntegerValue]; @param initial The value of the reduction at its start. @param block A block that takes the current sum and the next object to return the new sum. @return An accumulated value. */ - (id)bk_reduce:(id)initial withBlock:(id (^)(id sum, id obj))block; /** Loops through a set to find whether any object matches the block. This method is similar to the Scala list `exists`. It is functionally identical to bk_match: but returns a `BOOL` instead. It is not recommended to use bk_any: as a check condition before executing bk_match:, since it would require two loops through the array. @param block A single-argument, BOOL-returning code block. @return YES for the first time the block returns YES for an object, NO otherwise. */ - (BOOL)bk_any:(BOOL (^)(id obj))block; /** Loops through a set to find whether no objects match the block. This selector performs *literally* the exact same function as bk_all: but in reverse. @param block A single-argument, BOOL-returning code block. @return YES if the block returns NO for all objects in the set, NO otherwise. */ - (BOOL)bk_none:(BOOL (^)(id obj))block; /** Loops through a set to find whether all objects match the block. @param block A single-argument, BOOL-returning code block. @return YES if the block returns YES for all objects in the set, NO otherwise. */ - (BOOL)bk_all:(BOOL (^)(id obj))block; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSSet+BlocksKit.m ================================================ // // NSSet+BlocksKit.m // BlocksKit // #import "NSSet+BlocksKit.h" @implementation NSSet (BlocksKit) - (void)bk_each:(void (^)(id obj))block { NSParameterAssert(block != nil); [self enumerateObjectsUsingBlock:^(id obj, BOOL *stop) { block(obj); }]; } - (void)bk_apply:(void (^)(id obj))block { NSParameterAssert(block != nil); [self enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id obj, BOOL *stop) { block(obj); }]; } - (id)bk_match:(BOOL (^)(id obj))block { NSParameterAssert(block != nil); return [[self objectsPassingTest:^BOOL(id obj, BOOL *stop) { if (block(obj)) { *stop = YES; return YES; } return NO; }] anyObject]; } - (NSSet *)bk_select:(BOOL (^)(id obj))block { NSParameterAssert(block != nil); return [self objectsPassingTest:^BOOL(id obj, BOOL *stop) { return block(obj); }]; } - (NSSet *)bk_reject:(BOOL (^)(id obj))block { NSParameterAssert(block != nil); return [self objectsPassingTest:^BOOL(id obj, BOOL *stop) { return !block(obj); }]; } - (NSSet *)bk_map:(id (^)(id obj))block { NSParameterAssert(block != nil); NSMutableSet *result = [NSMutableSet setWithCapacity:self.count]; [self enumerateObjectsUsingBlock:^(id obj, BOOL *stop) { id value = block(obj) ?:[NSNull null]; [result addObject:value]; }]; return result; } - (id)bk_reduce:(id)initial withBlock:(id (^)(id sum, id obj))block { NSParameterAssert(block != nil); __block id result = initial; [self enumerateObjectsUsingBlock:^(id obj, BOOL *stop) { result = block(result, obj); }]; return result; } - (BOOL)bk_any:(BOOL (^)(id obj))block { return [self bk_match:block] != nil; } - (BOOL)bk_none:(BOOL (^)(id obj))block { return [self bk_match:block] == nil; } - (BOOL)bk_all:(BOOL (^)(id obj))block { NSParameterAssert(block != nil); __block BOOL result = YES; [self enumerateObjectsUsingBlock:^(id obj, BOOL *stop) { if (!block(obj)) { result = NO; *stop = YES; } }]; return result; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSTimer+BlocksKit.h ================================================ // // NSTimer+BlocksKit.h // BlocksKit // #import /** Simple category on NSTimer to give it blocks capability. Created by [Jiva DeVoe](https://github.com/jivadevoe) as `NSTimer-Blocks`. */ @interface NSTimer (BlocksKit) /** Creates and returns a block-based NSTimer object and schedules it on the current run loop. @param inTimeInterval The number of seconds between firings of the timer. @param inBlock The block that the NSTimer fires. @param inRepeats If YES, the timer will repeatedly reschedule itself until invalidated. If NO, the timer will be invalidated after it fires. @return A new NSTimer object, configured according to the specified parameters. */ + (NSTimer *)bk_scheduledTimerWithTimeInterval:(NSTimeInterval)inTimeInterval block:(void (^)(NSTimer *timer))inBlock repeats:(BOOL)inRepeats; /** Creates and returns a block-based NSTimer initialized with the specified block. You must add the new timer to a run loop, using `-addTimer:forMode:`. Then, after seconds seconds have elapsed, the timer fires the block. If the timer is configured to repeat, there is no need to subsequently re-add the timer. @param inTimeInterval The number of seconds between firings of the timer. @param inBlock The block that the NSTimer fires. @param inRepeats If YES, the timer will repeatedly reschedule itself until invalidated. If NO, the timer will be invalidated after it fires. @return A new NSTimer object, configured according to the specified parameters. */ + (NSTimer *)bk_timerWithTimeInterval:(NSTimeInterval)inTimeInterval block:(void (^)(NSTimer *timer))inBlock repeats:(BOOL)inRepeats; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/Core/NSTimer+BlocksKit.m ================================================ // // NSTimer+BlocksKit.m // BlocksKit // #import "NSTimer+BlocksKit.h" @interface NSTimer (BlocksKitPrivate) + (void)bk_executeBlockFromTimer:(NSTimer *)aTimer; @end @implementation NSTimer (BlocksKit) + (id)bk_scheduledTimerWithTimeInterval:(NSTimeInterval)inTimeInterval block:(void (^)(NSTimer *timer))block repeats:(BOOL)inRepeats { NSParameterAssert(block != nil); return [self scheduledTimerWithTimeInterval:inTimeInterval target:self selector:@selector(bk_executeBlockFromTimer:) userInfo:[block copy] repeats:inRepeats]; } + (id)bk_timerWithTimeInterval:(NSTimeInterval)inTimeInterval block:(void (^)(NSTimer *timer))block repeats:(BOOL)inRepeats { NSParameterAssert(block != nil); return [self timerWithTimeInterval:inTimeInterval target:self selector:@selector(bk_executeBlockFromTimer:) userInfo:[block copy] repeats:inRepeats]; } + (void)bk_executeBlockFromTimer:(NSTimer *)aTimer { void (^block)(NSTimer *) = [aTimer userInfo]; if (block) block(aTimer); } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/DynamicDelegate/A2BlockInvocation.h ================================================ // // A2BlockInvocation.h // BlocksKit // #import /// If a block invocation is instiated with an invalid method signature, /// an `NSInvalidArgumentException` is thrown containing this key in the /// user info. extern NSString *const A2IncompatibleMethodSignatureKey; /** An `A2BlockInvocation` is an Objective-C block call rendered static, that is, it is an action turned into an object. `A2BlockInvocation` objects are used to store and forward closure invocations between objects, primarily by the `A2DynamicDelegate` system. A block invocation object can be repeatedly dispatched with multiple sets of arguments with the same flexibility as NSInvocation. This design makes `A2BlockInvocation` extremely useful, because blocks can be used to capture scope and a block invocation can be used to save it for later. Like `NSInvocation`, `A2BlockInvocation` does not support invocations of methods with variadic arguments or union arguments. */ @interface A2BlockInvocation : NSObject /** Inspects the given block literal and returns a compatible method signature. The returned method signature is suitable for use in the Foundation forwarding system to link a method call to a block invocation. @param block An Objective-C block literal @return A method signature matching the declared prototype for the block */ + (NSMethodSignature *)methodSignatureForBlock:(id)block; /** @name Creating A2BlockInvocation Objects */ /** Returns a block invocation object able to construct calls to a given block. This method synthesizes a compatible method signature for the given block. @param block A block literal @return An initialized block invocation object @see methodSignatureForBlock */ - (instancetype)initWithBlock:(id)block; /** Returns a block invocation object able to construct calls to a given block using a given Objective-C method signature. The method signature given must be compatible with the signature of the block; that is, equal to the block signature but with a `SEL` (`':'`) as the second parameter. Passing in an incompatible method signature will raise an exception. An example method returning a string for an integer argument would have the following properties: - Block type signature of `NSString *(^)(int)` - Block function definition of `NSString *(*)(id, int)` - Block signature of `"@@?i"` - Method signature of `"@:i"` or `"@i"` @param block An Objective-C block literal @param methodSignature An method signature matching the block @return An initialized block invocation object */ - (instancetype)initWithBlock:(id)block methodSignature:(NSMethodSignature *)methodSignature; /** @name Getting the Block and Method Signatures */ /// The receiver's method signature, reflecting the block with a selector. /// Appropriate for use in `-methodSignatureForSelector:`. @property (nonatomic, strong, readonly) NSMethodSignature *methodSignature; /// Returns the receiver's block. @property (nonatomic, copy, readonly) id block; /** Calls the receiver's block with the arguments from the given invocation, providing a buffer containing the block's return value upon return. @param inv An instance of NSInvocation with values for its arguments set. @param returnValue On return, the block's return value, or `nil` for a void return type. @param NO if the buffer copies necessary for invocation failed, YES otherwise. @see invokeWithInvocation:returnValue: */ - (BOOL)invokeWithInvocation:(NSInvocation *)inv returnValue:(out NSValue **)returnValue; /** Calls the receiver's block with the arguments from the given invocation and sets the return value on the given invocation. @param inv An instance of NSInvocation with values for its arguments set. @see invokeWithInvocation:returnValue: */ - (void)invokeWithInvocation:(NSInvocation *)inv; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/DynamicDelegate/A2BlockInvocation.m ================================================ // // A2BlockInvocation.m // BlocksKit // #import "A2BlockInvocation.h" NSString *const A2IncompatibleMethodSignatureKey = @"incompatibleMethodSignature"; #ifndef NSFoundationVersionNumber10_8 #define NSFoundationVersionNumber10_8 945.00 #endif #ifndef NSFoundationVersionNumber_iOS_6_0 #define NSFoundationVersionNumber_iOS_6_0 993.00 #endif #pragma mark Block Internals typedef NS_OPTIONS(int, BKBlockFlags) { BKBlockFlagsHasCopyDisposeHelpers = (1 << 25), BKBlockFlagsHasSignature = (1 << 30) }; typedef struct _BKBlock { __unused Class isa; BKBlockFlags flags; __unused int reserved; void (__unused *invoke)(struct _BKBlock *block, ...); struct { unsigned long int reserved; unsigned long int size; // requires BKBlockFlagsHasCopyDisposeHelpers void (*copy)(void *dst, const void *src); void (*dispose)(const void *); // requires BKBlockFlagsHasSignature const char *signature; const char *layout; } *descriptor; // imported variables } *BKBlockRef; @interface A2BlockInvocation () @property (nonatomic, readonly) NSMethodSignature *blockSignature; @end @implementation A2BlockInvocation /** Determines if two given signatures (block or method) are compatible. A signature is compatible with another signature if their return types and parameter types are equal, minus the parameter types dedicated to the Obj-C method reciever and selector or a block literal argument. @param signatureA Any signature object reflecting a block or method signature @param signatureB Any signature object reflecting a block or method signature @return YES if the given signatures may be used to dispatch for one another */ + (BOOL)isSignature:(NSMethodSignature *)signatureA compatibleWithSignature:(NSMethodSignature *)signatureB __attribute__((pure)) { if (!signatureA || !signatureB) return NO; if ([signatureA isEqual:signatureB]) return YES; if (signatureA.methodReturnType[0] != signatureB.methodReturnType[0]) return NO; NSMethodSignature *methodSignature = nil, *blockSignature = nil; if (signatureA.numberOfArguments > signatureB.numberOfArguments) { methodSignature = signatureA; blockSignature = signatureB; } else if (signatureB.numberOfArguments > signatureA.numberOfArguments) { methodSignature = signatureB; blockSignature = signatureA; } else { return NO; } NSUInteger numberOfArguments = methodSignature.numberOfArguments; for (NSUInteger i = 2; i < numberOfArguments; i++) { if ([methodSignature getArgumentTypeAtIndex:i][0] != [blockSignature getArgumentTypeAtIndex:i - 1][0]) return NO; } return YES; } /** Inspects the given block literal and returns a compatible type signature. Unlike a typical method signature, a block type signature has no `self` (`'@'`) or `_cmd` (`':'`) parameter, but instead just one parameter for the block itself (`'@?'`). @param block An Objective-C block literal @return A method signature matching the declared prototype for the block */ + (NSMethodSignature *)typeSignatureForBlock:(id)block __attribute__((pure, nonnull(1))) { BKBlockRef layout = (__bridge void *)block; if (!(layout->flags & BKBlockFlagsHasSignature)) return nil; void *desc = layout->descriptor; desc += 2 * sizeof(unsigned long int); if (layout->flags & BKBlockFlagsHasCopyDisposeHelpers) desc += 2 * sizeof(void *); if (!desc) return nil; const char *signature = (*(const char **)desc); return [NSMethodSignature signatureWithObjCTypes:signature]; } /// Creates a method signature compatible with a given block signature. + (NSMethodSignature *)methodSignatureForBlockSignature:(NSMethodSignature *)original { if (!original) return nil; if (original.numberOfArguments < 1) { return nil; } if (original.numberOfArguments >= 2 && strcmp(@encode(SEL), [original getArgumentTypeAtIndex:1]) == 0) { return original; } // initial capacity is num. arguments - 1 (@? -> @) + 1 (:) + 1 (ret type) // optimistically assuming most signature components are char[1] NSMutableString *signature = [[NSMutableString alloc] initWithCapacity:original.numberOfArguments + 1]; const char *retTypeStr = original.methodReturnType; [signature appendFormat:@"%s%s%s", retTypeStr, @encode(id), @encode(SEL)]; for (NSUInteger i = 1; i < original.numberOfArguments; i++) { const char *typeStr = [original getArgumentTypeAtIndex:i]; NSString *type = [[NSString alloc] initWithBytesNoCopy:(void *)typeStr length:strlen(typeStr) encoding:NSUTF8StringEncoding freeWhenDone:NO]; [signature appendString:type]; } return [NSMethodSignature signatureWithObjCTypes:signature.UTF8String]; } + (NSMethodSignature *)methodSignatureForBlock:(id)block { NSMethodSignature *original = [self typeSignatureForBlock:block]; if (!original) return nil; return [self methodSignatureForBlockSignature:original]; } - (instancetype)initWithBlock:(id)block methodSignature:(NSMethodSignature *)methodSignature blockSignature:(NSMethodSignature *)blockSignature { self = [super init]; if (self) { _block = [block copy]; _methodSignature = methodSignature; _blockSignature = blockSignature; } return self; } - (instancetype)initWithBlock:(id)block { NSParameterAssert(block); NSMethodSignature *blockSignature = [[self class] typeSignatureForBlock:block]; NSMethodSignature *methodSignature = [[self class] methodSignatureForBlockSignature:blockSignature]; NSAssert(methodSignature, @"Incompatible block: %@", block); return (self = [self initWithBlock:block methodSignature:methodSignature blockSignature:blockSignature]); } - (instancetype)initWithBlock:(id)block methodSignature:(NSMethodSignature *)methodSignature { NSParameterAssert(block); NSMethodSignature *blockSignature = [[self class] typeSignatureForBlock:block]; if (![[self class] isSignature:methodSignature compatibleWithSignature:blockSignature]) { @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Attempted to create block invocation with incompatible signatures" userInfo:@{A2IncompatibleMethodSignatureKey: methodSignature}]; } return (self = [self initWithBlock:block methodSignature:methodSignature blockSignature:blockSignature]); } - (BOOL)invokeWithInvocation:(NSInvocation *)outerInv returnValue:(out NSValue **)outReturnValue setOnInvocation:(BOOL)setOnInvocation { NSParameterAssert(outerInv); NSMethodSignature *sig = self.methodSignature; if (![outerInv.methodSignature isEqual:sig]) { NSAssert(0, @"Attempted to invoke block invocation with incompatible frame"); return NO; } NSInvocation *innerInv = [NSInvocation invocationWithMethodSignature:self.blockSignature]; void *argBuf = NULL; for (NSUInteger i = 2; i < sig.numberOfArguments; i++) { const char *type = [sig getArgumentTypeAtIndex:i]; NSUInteger argSize; NSGetSizeAndAlignment(type, &argSize, NULL); if (!(argBuf = reallocf(argBuf, argSize))) { return NO; } [outerInv getArgument:argBuf atIndex:i]; [innerInv setArgument:argBuf atIndex:i - 1]; } [innerInv invokeWithTarget:self.block]; NSUInteger retSize = sig.methodReturnLength; if (retSize) { if (outReturnValue || setOnInvocation) { if (!(argBuf = reallocf(argBuf, retSize))) { return NO; } [innerInv getReturnValue:argBuf]; if (setOnInvocation) { [outerInv setReturnValue:argBuf]; } if (outReturnValue) { *outReturnValue = [NSValue valueWithBytes:argBuf objCType:sig.methodReturnType]; } } } else { if (outReturnValue) { *outReturnValue = nil; } } free(argBuf); return YES; } - (void)invokeWithInvocation:(NSInvocation *)inv { [self invokeWithInvocation:inv returnValue:NULL setOnInvocation:YES]; } - (BOOL)invokeWithInvocation:(NSInvocation *)inv returnValue:(out NSValue **)returnValue { return [self invokeWithInvocation:inv returnValue:returnValue setOnInvocation:NO]; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/DynamicDelegate/A2DynamicDelegate.h ================================================ // // A2DynamicDelegate.h // BlocksKit // #import #import #import /** A2DynamicDelegate implements a class's delegate, data source, or other delegated protocol by associating protocol methods with a block implementation. - (IBAction) annoyUser { // Create an alert view UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Hello World!" message:@"This alert's delegate is implemented using blocks. That's so cool!" delegate:nil cancelButtonTitle:@"Meh." otherButtonTitles:@"Woo!", nil]; // Get the dynamic delegate A2DynamicDelegate *dd = alertView.bk_dynamicDelegate; // Implement -alertViewShouldEnableFirstOtherButton: [dd implementMethod:@selector(alertViewShouldEnableFirstOtherButton:) withBlock:^(UIAlertView *alertView) { NSLog(@"Message: %@", alertView.message); return YES; }]; // Implement -alertView:willDismissWithButtonIndex: [dd implementMethod:@selector(alertView:willDismissWithButtonIndex:) withBlock:^(UIAlertView *alertView, NSInteger buttonIndex) { NSLog(@"You pushed button #%d (%@)", buttonIndex, [alertView buttonTitleAtIndex:buttonIndex]); }]; // Set the delegate alertView.delegate = dd; [alertView show]; } A2DynamicDelegate is designed to be 'plug and play'. */ @interface A2DynamicDelegate : NSProxy /** * The designated initializer for the A2DynamicDelegate proxy. * * An instance of A2DynamicDelegate should generally not be created by the user, * but instead by calling a method in NSObject(A2DynamicDelegate). Since * delegates are usually weak references on the part of the delegating object, a * dynamic delegate would be deallocated immediately after its declaring scope * ends. NSObject(A2DynamicDelegate) creates a strong reference. * * @param protocol A protocol to which the dynamic delegate should conform. * @return An initialized delegate proxy. */ - (id)initWithProtocol:(Protocol *)protocol; /** The protocol delegating the dynamic delegate. */ @property (nonatomic, readonly) Protocol *protocol; /** A dictionary of custom handlers to be used by custom responders in a A2Dynamic(Protocol Name) subclass of A2DynamicDelegate, like `A2DynamicUIAlertViewDelegate`. */ @property (nonatomic, strong, readonly) NSMutableDictionary *handlers; /** When replacing the delegate using the A2BlockDelegate extensions, the object responding to classical delegate method implementations. */ @property (nonatomic, weak, readonly) id realDelegate; /** @name Block Instance Method Implementations */ /** The block that is to be fired when the specified selector is called on the reciever. @param selector An encoded selector. Must not be NULL. @return A code block, or nil if no block is assigned. */ - (id)blockImplementationForMethod:(SEL)selector; /** Assigns the given block to be fired when the specified selector is called on the reciever. [tableView.dynamicDataSource implementMethod:@selector(numberOfSectionsInTableView:) withBlock:NSInteger^(UITableView *tableView) { return 2; }]; @warning Starting with A2DynamicDelegate 2.0, a block will not be checked for a matching signature. A block can have less parameters than the original selector and will be ignored, but cannot have more. @param selector An encoded selector. Must not be NULL. @param block A code block with the same signature as selector. */ - (void)implementMethod:(SEL)selector withBlock:(id)block; /** Disassociates any block so that nothing will be fired when the specified selector is called on the reciever. @param selector An encoded selector. Must not be NULL. */ - (void)removeBlockImplementationForMethod:(SEL)selector; /** @name Block Class Method Implementations */ /** The block that is to be fired when the specified selector is called on the delegating object's class. @param selector An encoded selector. Must not be NULL. @return A code block, or nil if no block is assigned. */ - (id)blockImplementationForClassMethod:(SEL)selector; /** Assigns the given block to be fired when the specified selector is called on the reciever. @warning Starting with A2DynamicDelegate 2.0, a block will not be checked for a matching signature. A block can have less parameters than the original selector and will be ignored, but cannot have more. @param selector An encoded selector. Must not be NULL. @param block A code block with the same signature as selector. */ - (void)implementClassMethod:(SEL)selector withBlock:(id)block; /** Disassociates any blocks so that nothing will be fired when the specified selector is called on the delegating object's class. @param selector An encoded selector. Must not be NULL. */ - (void)removeBlockImplementationForClassMethod:(SEL)selector; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/DynamicDelegate/A2DynamicDelegate.m ================================================ // // A2DynamicDelegate.m // BlocksKit // #import #import "A2BlockInvocation.h" #import "A2DynamicDelegate.h" Protocol *a2_dataSourceProtocol(Class cls); Protocol *a2_delegateProtocol(Class cls); Protocol *a2_protocolForDelegatingObject(id obj, Protocol *protocol); static BOOL selectorsEqual(const void *item1, const void *item2, NSUInteger(*__unused size)(const void __unused *item)) { return sel_isEqual((SEL)item1, (SEL)item2); } static NSString *selectorDescribe(const void *item1) { return NSStringFromSelector((SEL)item1); } @interface NSMapTable (BKAdditions) + (instancetype)bk_selectorsToStrongObjectsMapTable; - (id)bk_objectForSelector:(SEL)aSEL; - (void)bk_removeObjectForSelector:(SEL)aSEL; - (void)bk_setObject:(id)anObject forSelector:(SEL)aSEL; @end @implementation NSMapTable (BKAdditions) + (instancetype)bk_selectorsToStrongObjectsMapTable { NSPointerFunctions *selectors = [NSPointerFunctions pointerFunctionsWithOptions:NSPointerFunctionsOpaqueMemory|NSPointerFunctionsOpaquePersonality]; selectors.isEqualFunction = selectorsEqual; selectors.descriptionFunction = selectorDescribe; NSPointerFunctions *strongObjects = [NSPointerFunctions pointerFunctionsWithOptions:NSPointerFunctionsStrongMemory|NSPointerFunctionsObjectPersonality]; return [[NSMapTable alloc] initWithKeyPointerFunctions:selectors valuePointerFunctions:strongObjects capacity:1]; } - (id)bk_objectForSelector:(SEL)aSEL { void *selAsPtr = aSEL; return [self objectForKey:(__bridge id)selAsPtr]; } - (void)bk_removeObjectForSelector:(SEL)aSEL { void *selAsPtr = aSEL; [self removeObjectForKey:(__bridge id)selAsPtr]; } - (void)bk_setObject:(id)anObject forSelector:(SEL)aSEL { void *selAsPtr = aSEL; [self setObject:anObject forKey:(__bridge id)selAsPtr]; } @end @interface A2DynamicClassDelegate : A2DynamicDelegate @property (nonatomic) Class proxiedClass; @end #pragma mark - @interface A2DynamicDelegate () @property (nonatomic) A2DynamicClassDelegate *classProxy; @property (nonatomic, readonly) NSMapTable *invocationsBySelectors; @property (nonatomic, weak, readwrite) id realDelegate; - (BOOL) isClassProxy; @end @implementation A2DynamicDelegate - (A2DynamicClassDelegate *)classProxy { if (!_classProxy) { _classProxy = [[A2DynamicClassDelegate alloc] initWithProtocol:self.protocol]; _classProxy.proxiedClass = object_getClass(self); } return _classProxy; } - (BOOL)isClassProxy { return NO; } - (Class)class { Class myClass = object_getClass(self); if (myClass == [A2DynamicDelegate class] || [myClass superclass] == [A2DynamicDelegate class]) return (Class)self.classProxy; return [super class]; } - (id)initWithProtocol:(Protocol *)protocol { _protocol = protocol; _handlers = [NSMutableDictionary dictionary]; _invocationsBySelectors = [NSMapTable bk_selectorsToStrongObjectsMapTable]; return self; } - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { A2BlockInvocation *invocation = nil; if ((invocation = [self.invocationsBySelectors bk_objectForSelector:aSelector])) return invocation.methodSignature; else if ([self.realDelegate methodSignatureForSelector:aSelector]) return [self.realDelegate methodSignatureForSelector:aSelector]; else if (class_respondsToSelector(object_getClass(self), aSelector)) return [object_getClass(self) methodSignatureForSelector:aSelector]; return [[NSObject class] methodSignatureForSelector:aSelector]; } + (NSString *)description { return @"A2DynamicDelegate"; } - (NSString *)description { return [NSString stringWithFormat:@"", (__bridge void *)self, NSStringFromProtocol(self.protocol)]; } - (void)forwardInvocation:(NSInvocation *)outerInv { SEL selector = outerInv.selector; A2BlockInvocation *innerInv = nil; if ((innerInv = [self.invocationsBySelectors bk_objectForSelector:selector])) { [innerInv invokeWithInvocation:outerInv]; } else if ([self.realDelegate respondsToSelector:selector]) { [outerInv invokeWithTarget:self.realDelegate]; } } #pragma mark - - (BOOL)conformsToProtocol:(Protocol *)aProtocol { return protocol_isEqual(aProtocol, self.protocol) || [super conformsToProtocol:aProtocol]; } - (BOOL)respondsToSelector:(SEL)selector { return [self.invocationsBySelectors bk_objectForSelector:selector] || class_respondsToSelector(object_getClass(self), selector) || [self.realDelegate respondsToSelector:selector]; } - (void)doesNotRecognizeSelector:(SEL)aSelector { [NSException raise:NSInvalidArgumentException format:@"-[%s %@]: unrecognized selector sent to instance %p", object_getClassName(self), NSStringFromSelector(aSelector), (__bridge void *)self]; } #pragma mark - Block Instance Method Implementations - (id)blockImplementationForMethod:(SEL)selector { A2BlockInvocation *invocation = nil; if ((invocation = [self.invocationsBySelectors bk_objectForSelector:selector])) return invocation.block; return NULL; } - (void)implementMethod:(SEL)selector withBlock:(id)block { NSCAssert(selector, @"Attempt to implement or remove NULL selector"); BOOL isClassMethod = self.isClassProxy; if (!block) { [self.invocationsBySelectors bk_removeObjectForSelector:selector]; return; } struct objc_method_description methodDescription = protocol_getMethodDescription(self.protocol, selector, YES, !isClassMethod); if (!methodDescription.name) methodDescription = protocol_getMethodDescription(self.protocol, selector, NO, !isClassMethod); A2BlockInvocation *inv = nil; if (methodDescription.name) { NSMethodSignature *protoSig = [NSMethodSignature signatureWithObjCTypes:methodDescription.types]; inv = [[A2BlockInvocation alloc] initWithBlock:block methodSignature:protoSig]; } else { inv = [[A2BlockInvocation alloc] initWithBlock:block]; } [self.invocationsBySelectors bk_setObject:inv forSelector:selector]; } - (void)removeBlockImplementationForMethod:(SEL)selector __unused { [self implementMethod:selector withBlock:nil]; } #pragma mark - Block Class Method Implementations - (id)blockImplementationForClassMethod:(SEL)selector { return [self.classProxy blockImplementationForMethod:selector]; } - (void)implementClassMethod:(SEL)selector withBlock:(id)block { [self.classProxy implementMethod:selector withBlock:block]; } - (void)removeBlockImplementationForClassMethod:(SEL)selector __unused { [self.classProxy implementMethod:selector withBlock:nil]; } @end #pragma mark - @implementation A2DynamicClassDelegate - (BOOL)isClassProxy { return YES; } - (BOOL)isEqual:(id)object { return [super isEqual:object] || [_proxiedClass isEqual:object]; } - (BOOL)respondsToSelector:(SEL)aSelector { return [self.invocationsBySelectors bk_objectForSelector:aSelector] || [_proxiedClass respondsToSelector:aSelector]; } - (Class)class { return self.proxiedClass; } - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { A2BlockInvocation *invocation = nil; if ((invocation = [self.invocationsBySelectors bk_objectForSelector:aSelector])) return invocation.methodSignature; else if ([_proxiedClass methodSignatureForSelector:aSelector]) return [_proxiedClass methodSignatureForSelector:aSelector]; return [[NSObject class] methodSignatureForSelector:aSelector]; } - (NSString *)description { return [_proxiedClass description]; } - (NSUInteger)hash { return [_proxiedClass hash]; } - (void)forwardInvocation:(NSInvocation *)outerInv { SEL selector = outerInv.selector; A2BlockInvocation *innerInv = nil; if ((innerInv = [self.invocationsBySelectors bk_objectForSelector:selector])) { [innerInv invokeWithInvocation:outerInv]; } else { [outerInv invokeWithTarget:_proxiedClass]; } } #pragma mark - Unavailable Methods - (id)blockImplementationForClassMethod:(SEL)selector { [self doesNotRecognizeSelector:_cmd]; return nil; } - (void)implementClassMethod:(SEL)selector withBlock:(id)block { [self doesNotRecognizeSelector:_cmd]; } - (void)removeBlockImplementationForClassMethod:(SEL)selector { [self doesNotRecognizeSelector:_cmd]; } @end #pragma mark - Helper functions static Protocol *a2_classProtocol(Class _cls, NSString *suffix, NSString *description) { Class cls = _cls; while (cls) { NSString *className = NSStringFromClass(cls); NSString *protocolName = [className stringByAppendingString:suffix]; Protocol *protocol = objc_getProtocol(protocolName.UTF8String); if (protocol) return protocol; cls = class_getSuperclass(cls); } NSCAssert(NO, @"Specify protocol explicitly: could not determine %@ protocol for class %@ (tried <%@>)", description, NSStringFromClass(_cls), [NSStringFromClass(_cls) stringByAppendingString:suffix]); return nil; } Protocol *a2_dataSourceProtocol(Class cls) { return a2_classProtocol(cls, @"DataSource", @"data source"); } Protocol *a2_delegateProtocol(Class cls) { return a2_classProtocol(cls, @"Delegate", @"delegate"); } Protocol *a2_protocolForDelegatingObject(id obj, Protocol *protocol) { NSString *protocolName = NSStringFromProtocol(protocol); if ([protocolName hasSuffix:@"Delegate"]) { Protocol *p = a2_delegateProtocol([obj class]); if (p) return p; } else if ([protocolName hasSuffix:@"DataSource"]) { Protocol *p = a2_dataSourceProtocol([obj class]); if (p) return p; } return protocol; } ================================================ FILE: Pods/BlocksKit/BlocksKit/DynamicDelegate/Foundation/NSCache+BlocksKit.h ================================================ // // NSCache+BlocksKit.h // BlocksKit // #import /** NSCache with block adding of objects This category allows you to conditionally add objects to an instance of NSCache using blocks. Both the normal delegation pattern and a block callback for NSCache's one delegate method are allowed. These methods emulate Rails caching behavior. Created by [Igor Evsukov](https://github.com/evsukov89) and contributed to BlocksKit. */ @interface NSCache (BlocksKit) /** Returns the value associated with a given key. If there is no object for that key, it uses the result of the block, saves that to the cache, and returns it. This mimics the cache behavior of Ruby on Rails. The following code: @products = Rails.cache.fetch('products') do Product.all end becomes: NSMutableArray *products = [cache objectForKey:@"products" withGetter:^id{ return [Product all]; }]; @return The value associated with *key*, or the object returned by the block if no value is associated with *key*. @param key An object identifying the value. @param getterBlock A block used to get an object if there is no value in the cache. */ - (id)bk_objectForKey:(id)key withGetter:(id (^)(void))getterBlock; /** Called when an object is about to be evicted from the cache. This block callback is an analog for the cache:willEviceObject: method of NSCacheDelegate. */ @property (nonatomic, copy, setter = bk_setWillEvictBlock:) void (^bk_willEvictBlock)(NSCache *cache, id obj); @end ================================================ FILE: Pods/BlocksKit/BlocksKit/DynamicDelegate/Foundation/NSCache+BlocksKit.m ================================================ // // NSCache+BlocksKit.m // BlocksKit // #import "A2DynamicDelegate.h" #import "NSCache+BlocksKit.h" #import "NSObject+A2BlockDelegate.h" #pragma mark Custom delegate @interface A2DynamicNSCacheDelegate : A2DynamicDelegate @end @implementation A2DynamicNSCacheDelegate - (void)cache:(NSCache *)cache willEvictObject:(id)obj { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(cache:willEvictObject:)]) [realDelegate cache:cache willEvictObject:obj]; void (^orig)(NSCache *, id) = [self blockImplementationForMethod:_cmd]; if (orig) orig(cache, obj); } @end #pragma mark Category @implementation NSCache (BlocksKit) @dynamic bk_willEvictBlock; + (void)load { @autoreleasepool { [self bk_registerDynamicDelegate]; [self bk_linkDelegateMethods:@{ @"bk_willEvictBlock": @"cache:willEvictObject:" }]; } } #pragma mark Methods - (id)bk_objectForKey:(id)key withGetter:(id (^)(void))block { id object = [self objectForKey:key]; if (object) return object; if (block) { object = block(); [self setObject:object forKey:key]; } return object; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/DynamicDelegate/Foundation/NSURLConnection+BlocksKit.h ================================================ // // NSURLConnection+BlocksKit.h // BlocksKit // #import /** NSURLConnection with both delegate and block callback support. It also adds useful block handlers for tracking upload and download progress. Here is a small example: - (void)downloadImage:(id)sender { self.downloadButton.enabled = NO; self.progressView.progress = 0.0f; NSURL *imageURL = [NSURL URLWithString:@"http://icanhascheezburger.files.wordpress.com/2011/06/funny-pictures-nyan-cat-wannabe1.jpg"]; NSURLRequest *request = [NSURLRequest requestWithURL:imageURL]; NSURLConnection *connection = [NSURLConnection connectionWithRequest:request]; connection.delegate = self; connection.failureBlock = ^(NSURLConnection *connection, NSError *error) { [[UIAlertView alertViewWithTitle:@"Download error" message:[error localizedDescription]] show]; self.downloadButton.enabled = YES; self.progressView.progress = 0.0f; }; connection.successBlock = ^(NSURLConnection *connection, NSURLResponse *response, NSData *responseData) { self.imageView.image = [UIImage imageWithData:responseData]; self.downloadButton.enabled = YES; }; connection.downloadBlock = ^(double progress) { self.progressView.progress = progress; }; [connection start]; } //these methods will be called too! - (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite { NSLog(@"%s",__PRETTY_FUNCTION__); } - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { NSLog(@"%s",__PRETTY_FUNCTION__); } Created by Igor Evsukov as [IEURLConnection](https://github.com/evsukov89/IEURLConnection) and contributed to BlocksKit. */ @interface NSURLConnection (BlocksKit) /** A mutable delegate that implements the NSURLConnectionDelegate protocol. This property allows for both use of block callbacks and delegate methods in an instance of NSURLConnection. It only works on block-backed NSURLConnection instances. */ @property (nonatomic, weak, setter = setDelegate:) id delegate; /** The block fired once the connection recieves a response from the server. This block corresponds to the connection:didReceiveResponse: method of NSURLConnectionDataDelegate. */ @property (nonatomic, copy, setter = bk_setResponseBlock:) void (^bk_responseBlock)(NSURLConnection *connection, NSURLResponse *response); /** The block fired upon the failure of the connection. This block corresponds to the connection:didFailWithError: method of NSURLConnectionDelegate. */ @property (nonatomic, copy, setter = bk_setFailureBlock:) void (^bk_failureBlock)(NSURLConnection *connection, NSError *error); /** The block that upon the successful completion of the connection. This block corresponds to the connectionDidFinishLoading: method of NSURLConnectionDelegate. @warning If the delegate implements connection:didRecieveData:, then this block will *not* include the data recieved by the connection and appending the recieved data to an instance NSMutableData is left up to the user due to the behavior of frameworks that use NSURLConnection. */ @property (nonatomic, copy, setter = bk_setSuccessBlock:) void (^bk_successBlock)(NSURLConnection *connection, NSURLResponse *response, NSData *responseData); /** The block fired every time new data is sent to the server, representing the current percentage of completion. This block corresponds to the connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite: method of NSURLConnectionDelegate. */ @property (nonatomic, copy, setter = bk_setUploadBlock:) void (^bk_uploadBlock)(double percent); /** The block fired every time new data is recieved from the server, representing the current percentage of completion. This block corresponds to the connection:didRecieveData: method of NSURLConnectionDelegate. */ @property (nonatomic, copy, setter = bk_setDownloadBlock:) void (^bk_downloadBlock)(double percent); /** Creates and returns an initialized block-backed URL connection that does not begin to load the data for the URL request. @param request The URL request to load. @return An autoreleased NSURLConnection for the specified URL request. */ + (NSURLConnection *)bk_connectionWithRequest:(NSURLRequest *)request; /** Creates, starts, and returns an asynchronous, block-backed URL connection @return New and running NSURLConnection with the specified properties. @param request The URL request to load. @param success A code block that acts on instances of NSURLResponse and NSData in the event of a successful connection. @param failure A code block that acts on instances of NSURLResponse and NSError in the event of a failed connection. */ + (NSURLConnection *)bk_startConnectionWithRequest:(NSURLRequest *)request successHandler:(void (^)(NSURLConnection *connection, NSURLResponse *response, NSData *responseData))success failureHandler:(void (^)(NSURLConnection *connection, NSError *error))failure; /** Returns an initialized block-backed URL connection. @return Newly initialized NSURLConnection with the specified properties. @param request The URL request to load. */ - (id)bk_initWithRequest:(NSURLRequest *)request NS_REPLACES_RECEIVER; /** Returns an initialized URL connection with the specified completion handler. @return Newly initialized NSURLConnection with the specified properties. @param request The URL request to load. @param block A code block that acts on instances of NSURLResponse and NSData in the event of a successful connection. */ - (id)bk_initWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLConnection *connection, NSURLResponse *response, NSData *responseData))block NS_REPLACES_RECEIVER; /** Causes the connection to begin loading data, if it has not already, with the specified block to be fired on successful completion. @param block A code block that acts on instances of NSURLResponse and NSData in the event of a successful connection. */ - (void)bk_startWithCompletionBlock:(void (^)(NSURLConnection *connection, NSURLResponse *response, NSData *responseData))block; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/DynamicDelegate/Foundation/NSURLConnection+BlocksKit.m ================================================ // // NSURLConnection+BlocksKit.m // BlocksKit // #import #import "A2DynamicDelegate.h" #import "NSObject+A2BlockDelegate.h" #import "NSObject+A2DynamicDelegate.h" #import "NSURLConnection+BlocksKit.h" #pragma mark Private static const void *BKResponseDataKey = &BKResponseDataKey; static const void *BKResponseKey = &BKResponseKey; static const void *BKResponseLengthKey = &BKResponseLengthKey; @interface NSURLConnection (BlocksKitPrivate) @property (nonatomic, retain, setter = bk_setResponseData:) NSMutableData *bk_responseData; @property (nonatomic, retain, setter = bk_setResponse:) NSURLResponse *bk_response; @property (nonatomic, setter = bk_setResponseLength:) NSUInteger bk_responseLength; @end @implementation NSURLConnection (BlocksKitPrivate) - (NSMutableData *)bk_responseData { return objc_getAssociatedObject(self, BKResponseDataKey); } - (void)bk_setResponseData:(NSMutableData *)responseData { objc_setAssociatedObject(self, BKResponseDataKey, responseData, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (NSURLResponse *)bk_response { return objc_getAssociatedObject(self, BKResponseKey); } - (void)bk_setResponse:(NSURLResponse *)response { objc_setAssociatedObject(self, BKResponseKey, response, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (NSUInteger)bk_responseLength { return [objc_getAssociatedObject(self, BKResponseLengthKey) unsignedIntegerValue]; } - (void)bk_setResponseLength:(NSUInteger)responseLength { objc_setAssociatedObject(self, BKResponseLengthKey, @(responseLength), OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @end #pragma mark - BKURLConnectionInformalDelegate - iOS 4.3 & Snow Leopard support @protocol BKURLConnectionInformalDelegate - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response; - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data; - (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite; - (void)connectionDidFinishLoading:(NSURLConnection *)connection; - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error; - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge; - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace; @end @interface A2DynamicBKURLConnectionInformalDelegate : A2DynamicDelegate @end @implementation A2DynamicBKURLConnectionInformalDelegate - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(connection:didReceiveResponse:)]) [realDelegate connection:connection didReceiveResponse:response]; connection.bk_responseLength = 0; [connection.bk_responseData setLength:0]; connection.bk_response = response; void (^block)(NSURLConnection *, NSURLResponse *) = [self blockImplementationForMethod:_cmd]; if (block) block(connection, response); } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { connection.bk_responseLength += data.length; void (^block)(double) = connection.bk_downloadBlock; if (block && connection.bk_response && connection.bk_response.expectedContentLength != NSURLResponseUnknownLength) block((double)connection.bk_responseLength / (double)connection.bk_response.expectedContentLength); id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(connection:didReceiveData:)]) { [realDelegate connection:connection didReceiveData:data]; return; } NSMutableData *responseData = connection.bk_responseData; if (!responseData) { responseData = [NSMutableData data]; connection.bk_responseData = responseData; } [responseData appendData:data]; } - (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:)]) [realDelegate connection:connection didSendBodyData:bytesWritten totalBytesWritten:totalBytesWritten totalBytesExpectedToWrite:totalBytesExpectedToWrite]; void (^block)(double) = connection.bk_uploadBlock; if (block) block((double)totalBytesWritten/(double)totalBytesExpectedToWrite); } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(connectionDidFinishLoading:)]) [realDelegate connectionDidFinishLoading:connection]; if (!connection.bk_responseData.length) connection.bk_responseData = nil; void (^block)(NSURLConnection *, NSURLResponse *, NSData *) = connection.bk_successBlock; if (block) block(connection, connection.bk_response, connection.bk_responseData); } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(connection:didFailWithError:)]) [realDelegate connection:connection didFailWithError:error]; connection.bk_responseLength = 0; [connection.bk_responseData setLength:0]; void (^block)(NSURLConnection *, NSError *) = [self blockImplementationForMethod:_cmd]; if (block) block(connection, error); } - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(connection:didReceiveAuthenticationChallenge:)]) [realDelegate connection:connection didReceiveAuthenticationChallenge:challenge]; } - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(connection:canAuthenticateAgainstProtectionSpace:)]) return [realDelegate connection:connection canAuthenticateAgainstProtectionSpace:protectionSpace]; return NO; } @end #pragma mark - NSURLConnectionDelegate - iOS 5.0 & Lion support @interface A2DynamicNSURLConnectionDelegate : A2DynamicDelegate @end @implementation A2DynamicNSURLConnectionDelegate - (BOOL)conformsToProtocol:(Protocol *)protocol { Protocol *dataDelegateProtocol = objc_getProtocol("NSURLConnectionDataDelegate"); return (protocol_isEqual(protocol, dataDelegateProtocol) || protocol_isEqual(protocol, self.protocol) || [super conformsToProtocol:protocol]); } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(connection:didFailWithError:)]) [realDelegate connection:connection didFailWithError:error]; connection.bk_responseLength = 0; [connection.bk_responseData setLength:0]; void (^block)(NSURLConnection *, NSError *) = [self blockImplementationForMethod:_cmd]; if (block) block(connection, error); } - (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(connectionShouldUseCredentialStorage:)]) return [realDelegate connectionShouldUseCredentialStorage:connection]; return YES; } - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(connection:willSendRequestForAuthenticationChallenge:)]) [realDelegate connection:connection willSendRequestForAuthenticationChallenge:challenge]; } #pragma mark - NSURLConnectionDataDelegate - (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(connection:willSendRequest:redirectResponse:)]) return [realDelegate connection:connection willSendRequest:request redirectResponse:response]; return request; } - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(connection:didReceiveResponse:)]) [realDelegate connection:connection didReceiveResponse:response]; connection.bk_responseLength = 0; if (connection.bk_responseData) [connection.bk_responseData setLength:0]; connection.bk_response = response; void (^block)(NSURLConnection *, NSURLResponse *) = [self blockImplementationForMethod:_cmd]; if (block) block(connection, response); } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { connection.bk_responseLength += data.length; void (^block)(double) = connection.bk_downloadBlock; if (block && connection.bk_response && connection.bk_response.expectedContentLength != NSURLResponseUnknownLength) block((double)connection.bk_responseLength / (double)connection.bk_response.expectedContentLength); id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(connection:didReceiveData:)]) { [realDelegate connection:connection didReceiveData:data]; return; } NSMutableData *responseData = connection.bk_responseData; if (!responseData) { responseData = [NSMutableData data]; connection.bk_responseData = responseData; } [responseData appendData:data]; } - (NSInputStream *)connection:(NSURLConnection *)connection needNewBodyStream:(NSURLRequest *)request { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(connection:needNewBodyStream:)]) return [realDelegate connection:connection needNewBodyStream:request]; return nil; } - (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:)]) [realDelegate connection:connection didSendBodyData:bytesWritten totalBytesWritten:totalBytesWritten totalBytesExpectedToWrite:totalBytesExpectedToWrite]; void (^block)(double) = connection.bk_uploadBlock; if (block) block((double)totalBytesWritten/(double)totalBytesExpectedToWrite); } - (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(connection:willCacheResponse:)]) return [realDelegate connection:connection willCacheResponse:cachedResponse]; return cachedResponse; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(connectionDidFinishLoading:)]) [realDelegate connectionDidFinishLoading:connection]; if (!connection.bk_responseData.length) connection.bk_responseData = nil; void (^block)(NSURLConnection *, NSURLResponse *, NSData *) = connection.bk_successBlock; if (block) block(connection, connection.bk_response, connection.bk_responseData); } #pragma mark - Deprecated iOS 4.x authentication methods - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(connection:didReceiveAuthenticationChallenge:)]) [realDelegate connection:connection didReceiveAuthenticationChallenge:challenge]; } - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(connection:canAuthenticateAgainstProtectionSpace:)]) return [realDelegate connection:connection canAuthenticateAgainstProtectionSpace:protectionSpace]; return NO; } @end #pragma mark - Category static NSString *const kSuccessBlockKey = @"NSURLConnectionDidFinishLoading"; static NSString *const kFailureBlockKey = @"NSURLConnectionDidFailWithError"; static NSString *const kUploadBlockKey = @"NSURLConnectionDidSendData"; static NSString *const kDownloadBlockKey = @"NSURLConnectionDidRecieveData"; @implementation NSURLConnection (BlocksKit) @dynamic delegate, bk_responseBlock, bk_failureBlock; + (void)load { @autoreleasepool { [self bk_registerDynamicDelegate]; [self bk_linkDelegateMethods:@{ @"bk_responseBlock": @"connection:didReceiveResponse:", @"bk_failureBlock": @"connection:didFailWithError:" }]; } } #pragma mark Initializers + (NSURLConnection*)bk_connectionWithRequest:(NSURLRequest *)request { return [[[self class] alloc] bk_initWithRequest:request]; } + (NSURLConnection *)bk_startConnectionWithRequest:(NSURLRequest *)request successHandler:(void (^)(NSURLConnection *, NSURLResponse *, NSData *))success failureHandler:(void (^)(NSURLConnection *, NSError *))failure { Protocol *delegateProtocol = objc_getProtocol("NSURLConnectionDelegate"); if (!delegateProtocol) delegateProtocol = @protocol(BKURLConnectionInformalDelegate); NSURLConnection *ret = [[self class] alloc]; A2DynamicDelegate *dd = [ret bk_dynamicDelegateForProtocol:delegateProtocol]; if (success) dd.handlers[kSuccessBlockKey] = [success copy]; if (failure) [dd implementMethod:@selector(connection:didFailWithError:) withBlock:[failure copy]]; return [ret initWithRequest:request delegate:dd startImmediately:YES]; } - (id)bk_initWithRequest:(NSURLRequest *)request { return (self = [self bk_initWithRequest:request completionHandler:nil]); } - (id)bk_initWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLConnection *, NSURLResponse *, NSData *))block { Protocol *delegateProtocol = objc_getProtocol("NSURLConnectionDelegate"); if (!delegateProtocol) delegateProtocol = @protocol(BKURLConnectionInformalDelegate); A2DynamicDelegate *dd = [self bk_dynamicDelegateForProtocol:delegateProtocol]; if (block) dd.handlers[kSuccessBlockKey] = [block copy]; return (self = [self initWithRequest:request delegate:dd startImmediately:NO]); } - (void)bk_startWithCompletionBlock:(void (^)(NSURLConnection *, NSURLResponse *, NSData *))block { self.bk_successBlock = block; [self start]; } #pragma mark Properties - (void (^)(NSURLConnection *, NSURLResponse *, NSData *))bk_successBlock { return [self.bk_dynamicDelegate handlers][kSuccessBlockKey]; } - (void)bk_setSuccessBlock:(void (^)(NSURLConnection *, NSURLResponse *, NSData *))block { if (block) [self.bk_dynamicDelegate handlers][kSuccessBlockKey] = [block copy]; else [[self.bk_dynamicDelegate handlers] removeObjectForKey:kSuccessBlockKey]; } - (void (^)(double))bk_uploadBlock { return [self.bk_dynamicDelegate handlers][kUploadBlockKey]; } - (void)bk_setUploadBlock:(void (^)(double))block { if (block) [self.bk_dynamicDelegate handlers][kUploadBlockKey] = [block copy]; else [[self.bk_dynamicDelegate handlers] removeObjectForKey:kUploadBlockKey]; } - (void (^)(double))bk_downloadBlock { return [self.bk_dynamicDelegate handlers][kDownloadBlockKey]; } - (void)bk_setDownloadBlock:(void (^)(double))block { if (block) [self.bk_dynamicDelegate handlers][kDownloadBlockKey] = [block copy]; else [[self.bk_dynamicDelegate handlers] removeObjectForKey:kDownloadBlockKey]; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/DynamicDelegate/NSObject+A2BlockDelegate.h ================================================ // // NSObject+A2BlockDelegate.h // BlocksKit // #import /** The A2BlockDelegate category extends features provided by A2DynamicDelegate to create custom block properties in a category on a delegating object and dynamically map them to delegate (`UIAlertViewDelegate`), data source (`UITableViewDataSource`), or other delegated protocol (`NSErrorRecoveryAttempting`) methods. A2BlockDelegate also supports replacing the delegate of a given class with an automatic - though optional - version of these block-based properties, while still allowing for traditional method-based delegate implementations. Simply call one of the methods in the category on a class to add a block property to that class, preferably during a `+load` method in a category. To interplay between classes that support delegation but are extended to have block properties through delegate replacement extended to have block properties, one should implement an `A2Dynamic` subclass of `A2DynamicDelegate`. This behavior is documented in detail in the class documentation for A2DynamicDelegate, and examples exist in BlocksKit. */ @interface NSObject (A2BlockDelegate) /** @name Linking Block Properties */ /** Synthesizes multiple properties and links them to the appropriate selector in the data source protocol. A2DynamicDelegate assumes a protocol name `FooBarDataSource` for instances of class `FooBar`. The method will generate appropriate `setHandler:` and `handler` implementations for each property name and selector name string pair. @param selectorsForPropertyNames A dictionary with property names as keys and selector strings as objects. */ + (void)bk_linkDataSourceMethods:(NSDictionary *)selectorsForPropertyNames; /** Synthesizes multiple properties and links them to the appropriate selector in the delegate protocol. A2DynamicDelegate assumes a protocol name `FooBarDelegate` for instances of class `FooBar`. The method will generate appropriate `setHandler:` and `handler` implementations for each property name and selector name string pair. @param selectorsForPropertyNames A dictionary with property names as keys and selectors strings as objects. */ + (void)bk_linkDelegateMethods:(NSDictionary *)selectorsForPropertyNames; /** Synthesizes multiple properties and links them to the appropriate selector in the given protocol. The method will generate appropriate `setHandler:` and `handler` implementations for each property name and selector name string pair. @param protocol A protocol that declares all of the given selectors. Must not be NULL. @param selectorsForPropertyNames A dictionary with property names as keys and selector strings as objects. */ + (void)bk_linkProtocol:(Protocol *)protocol methods:(NSDictionary *)selectorsForPropertyNames; /** @name Delegate replacement properties */ /** Registers a dynamic data source replacement using the property name `dataSource` and the protocol name `FooBarDataSource` for an instance of `FooBar`. */ + (void)bk_registerDynamicDataSource; /** Registers a dynamic delegate replacement using the property name `delegate` and the protocol name `FooBarDelegate` for an instance of `FooBar`. */ + (void)bk_registerDynamicDelegate; /** Registers a dynamic data source replacement using the given property name and the protocol name `FooBarDataSource` for an instance of `FooBar`. @param dataSourceName The name of the class' data source property. Must not be nil. */ + (void)bk_registerDynamicDataSourceNamed:(NSString *)dataSourceName; /** Registers a dynamic delegate replacement using the given property name and the protocol name `FooBarDelegate` for an instance of `FooBar`. @param delegateName The name of the class' delegate property. Must not be nil. */ + (void)bk_registerDynamicDelegateNamed:(NSString *)delegateName; /** Registers a dynamic protocol implementation replacement using the given property name and the given protocol. @param delegateName The name of the class' delegation protocol property, such as `safeDelegate`. Must not be nil. @param protocol A properly encoded protocol. Must not be NULL. */ + (void)bk_registerDynamicDelegateNamed:(NSString *)delegateName forProtocol:(Protocol *)protocol; /** Creates or gets a dynamic delegate, assuring that it is the delegate. @see bk_dynamicDelegate: @return A dynamic delegate. */ - (id)bk_ensuredDynamicDelegate; /** Creates or gets a dynamic protocol implementation, assuring that it is assigned to the delegate property correspending to that protocol @see bk_dynamicDelegateForProtocol: @return A dynamic delegate. */ - (id)bk_ensuredDynamicDelegateForProtocol:(Protocol *)protocol; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/DynamicDelegate/NSObject+A2BlockDelegate.m ================================================ // // NSObject+A2BlockDelegate.m // BlocksKit // #import #import "NSObject+A2BlockDelegate.h" #import "NSObject+A2DynamicDelegate.h" #pragma mark - Declarations and macros extern Protocol *a2_dataSourceProtocol(Class cls); extern Protocol *a2_delegateProtocol(Class cls); #pragma mark - Functions static BOOL bk_object_isKindOfClass(id obj, Class testClass) { BOOL isKindOfClass = NO; Class cls = object_getClass(obj); while (cls && !isKindOfClass) { isKindOfClass = (cls == testClass); cls = class_getSuperclass(cls); } return isKindOfClass; } static Protocol *a2_protocolForDelegatingObject(id obj, Protocol *protocol) { NSString *protocolName = NSStringFromProtocol(protocol); if ([protocolName hasSuffix:@"Delegate"]) { Protocol *p = a2_delegateProtocol([obj class]); if (p) return p; } else if ([protocolName hasSuffix:@"DataSource"]) { Protocol *p = a2_dataSourceProtocol([obj class]); if (p) return p; } return protocol; } static inline BOOL isValidIMP(IMP impl) { #if defined(__arm64__) if (impl == NULL || impl == _objc_msgForward) return NO; #else if (impl == NULL || impl == _objc_msgForward || impl == (IMP)_objc_msgForward_stret) return NO; #endif return YES; } static BOOL addMethodWithIMP(Class cls, SEL oldSel, SEL newSel, IMP newIMP, const char *types, BOOL aggressive) { if (!class_addMethod(cls, oldSel, newIMP, types)) { return NO; } // We just ended up implementing a method that doesn't exist // (-[NSURLConnection setDelegate:]) or overrode a superclass // version (-[UIImagePickerController setDelegate:]). IMP parentIMP = NULL; Class superclass = class_getSuperclass(cls); while (superclass && !isValidIMP(parentIMP)) { parentIMP = class_getMethodImplementation(superclass, oldSel); if (isValidIMP(parentIMP)) { break; } else { parentIMP = NULL; } superclass = class_getSuperclass(superclass); } if (parentIMP) { if (aggressive) { return class_addMethod(cls, newSel, parentIMP, types); } class_replaceMethod(cls, newSel, newIMP, types); class_replaceMethod(cls, oldSel, parentIMP, types); } return YES; } static BOOL swizzleWithIMP(Class cls, SEL oldSel, SEL newSel, IMP newIMP, const char *types, BOOL aggressive) { Method origMethod = class_getInstanceMethod(cls, oldSel); if (addMethodWithIMP(cls, oldSel, newSel, newIMP, types, aggressive)) { return YES; } // common case, actual swap BOOL ret = class_addMethod(cls, newSel, newIMP, types); Method newMethod = class_getInstanceMethod(cls, newSel); method_exchangeImplementations(origMethod, newMethod); return ret; } static SEL selectorWithPattern(const char *prefix, const char *key, const char *suffix) { size_t prefixLength = prefix ? strlen(prefix) : 0; size_t suffixLength = suffix ? strlen(suffix) : 0; char initial = key[0]; if (prefixLength) initial = (char)toupper(initial); size_t initialLength = 1; const char *rest = key + initialLength; size_t restLength = strlen(rest); char selector[prefixLength + initialLength + restLength + suffixLength + 1]; memcpy(selector, prefix, prefixLength); selector[prefixLength] = initial; memcpy(selector + prefixLength + initialLength, rest, restLength); memcpy(selector + prefixLength + initialLength + restLength, suffix, suffixLength); selector[prefixLength + initialLength + restLength + suffixLength] = '\0'; return sel_registerName(selector); } static SEL getterForProperty(objc_property_t property, const char *name) { if (property) { char *getterName = property_copyAttributeValue(property, "G"); if (getterName) { SEL getter = sel_getUid(getterName); free(getterName); if (getter) return getter; } } const char *propertyName = property ? property_getName(property) : name; return sel_registerName(propertyName); } static SEL setterForProperty(objc_property_t property, const char *name) { if (property) { char *setterName = property_copyAttributeValue(property, "S"); if (setterName) { SEL setter = sel_getUid(setterName); free(setterName); if (setter) return setter; } } const char *propertyName = property ? property_getName(property) : name; return selectorWithPattern("set", propertyName, ":"); } static inline SEL prefixedSelector(SEL original) { return selectorWithPattern("a2_", sel_getName(original), NULL); } #pragma mark - typedef struct { SEL setter; SEL a2_setter; SEL getter; } A2BlockDelegateInfo; static NSUInteger A2BlockDelegateInfoSize(const void *__unused item) { return sizeof(A2BlockDelegateInfo); } static NSString *A2BlockDelegateInfoDescribe(const void *__unused item) { if (!item) { return nil; } const A2BlockDelegateInfo *info = item; return [NSString stringWithFormat:@"(setter: %s, getter: %s)", sel_getName(info->setter), sel_getName(info->getter)]; } static inline A2DynamicDelegate *getDynamicDelegate(NSObject *delegatingObject, Protocol *protocol, const A2BlockDelegateInfo *info, BOOL ensuring) { A2DynamicDelegate *dynamicDelegate = [delegatingObject bk_dynamicDelegateForProtocol:a2_protocolForDelegatingObject(delegatingObject, protocol)]; if (!info || !info->setter || !info->getter) { return dynamicDelegate; } if (!info->a2_setter && !info->setter) { return dynamicDelegate; } id (*getterDispatch)(id, SEL) = (id (*)(id, SEL)) objc_msgSend; id originalDelegate = getterDispatch(delegatingObject, info->getter); if (bk_object_isKindOfClass(originalDelegate, A2DynamicDelegate.class)) { return dynamicDelegate; } void (*setterDispatch)(id, SEL, id) = (void (*)(id, SEL, id)) objc_msgSend; setterDispatch(delegatingObject, info->a2_setter ?: info->setter, dynamicDelegate); return dynamicDelegate; } typedef A2DynamicDelegate *(^A2GetDynamicDelegateBlock)(NSObject *, BOOL); @interface A2DynamicDelegate () @property (nonatomic, weak, readwrite) id realDelegate; @end #pragma mark - @implementation NSObject (A2BlockDelegate) #pragma mark Helpers + (NSMapTable *)bk_delegateInfoByProtocol:(BOOL)createIfNeeded { NSMapTable *delegateInfo = objc_getAssociatedObject(self, _cmd); if (delegateInfo || !createIfNeeded) { return delegateInfo; } NSPointerFunctions *protocols = [NSPointerFunctions pointerFunctionsWithOptions:NSPointerFunctionsOpaqueMemory|NSPointerFunctionsObjectPointerPersonality]; NSPointerFunctions *infoStruct = [NSPointerFunctions pointerFunctionsWithOptions:NSPointerFunctionsMallocMemory|NSPointerFunctionsStructPersonality|NSPointerFunctionsCopyIn]; infoStruct.sizeFunction = A2BlockDelegateInfoSize; infoStruct.descriptionFunction = A2BlockDelegateInfoDescribe; delegateInfo = [[NSMapTable alloc] initWithKeyPointerFunctions:protocols valuePointerFunctions:infoStruct capacity:0]; objc_setAssociatedObject(self, _cmd, delegateInfo, OBJC_ASSOCIATION_RETAIN_NONATOMIC); return delegateInfo; } + (const A2BlockDelegateInfo *)bk_delegateInfoForProtocol:(Protocol *)protocol { A2BlockDelegateInfo *infoAsPtr = NULL; Class cls = self; while ((infoAsPtr == NULL || infoAsPtr->getter == NULL) && cls != nil && cls != NSObject.class) { NSMapTable *map = [cls bk_delegateInfoByProtocol:NO]; infoAsPtr = (__bridge void *)[map objectForKey:protocol]; cls = [cls superclass]; } NSCAssert(infoAsPtr != NULL, @"Class %@ not assigned dynamic delegate for protocol %@", NSStringFromClass(self), NSStringFromProtocol(protocol)); return infoAsPtr; } #pragma mark Linking block properties + (void)bk_linkDataSourceMethods:(NSDictionary *)dictionary { [self bk_linkProtocol:a2_dataSourceProtocol(self) methods:dictionary]; } + (void)bk_linkDelegateMethods:(NSDictionary *)dictionary { [self bk_linkProtocol:a2_delegateProtocol(self) methods:dictionary]; } + (void)bk_linkProtocol:(Protocol *)protocol methods:(NSDictionary *)dictionary { [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *propertyName, NSString *selectorName, BOOL *stop) { const char *name = propertyName.UTF8String; objc_property_t property = class_getProperty(self, name); NSCAssert(property, @"Property \"%@\" does not exist on class %s", propertyName, class_getName(self)); char *dynamic = property_copyAttributeValue(property, "D"); NSCAssert2(dynamic, @"Property \"%@\" on class %s must be backed with \"@dynamic\"", propertyName, class_getName(self)); free(dynamic); char *copy = property_copyAttributeValue(property, "C"); NSCAssert2(copy, @"Property \"%@\" on class %s must be defined with the \"copy\" attribute", propertyName, class_getName(self)); free(copy); SEL selector = NSSelectorFromString(selectorName); SEL getter = getterForProperty(property, name); SEL setter = setterForProperty(property, name); if (class_respondsToSelector(self, setter) || class_respondsToSelector(self, getter)) { return; } const A2BlockDelegateInfo *info = [self bk_delegateInfoForProtocol:protocol]; IMP getterImplementation = imp_implementationWithBlock(^(NSObject *delegatingObject) { A2DynamicDelegate *delegate = getDynamicDelegate(delegatingObject, protocol, info, NO); return [delegate blockImplementationForMethod:selector]; }); if (!class_addMethod(self, getter, getterImplementation, "@@:")) { NSCAssert(NO, @"Could not implement getter for \"%@\" property.", propertyName); } IMP setterImplementation = imp_implementationWithBlock(^(NSObject *delegatingObject, id block) { A2DynamicDelegate *delegate = getDynamicDelegate(delegatingObject, protocol, info, YES); [delegate implementMethod:selector withBlock:block]; }); if (!class_addMethod(self, setter, setterImplementation, "v@:@")) { NSCAssert(NO, @"Could not implement setter for \"%@\" property.", propertyName); } }]; } #pragma mark Dynamic Delegate Replacement + (void)bk_registerDynamicDataSource { [self bk_registerDynamicDelegateNamed:@"dataSource" forProtocol:a2_dataSourceProtocol(self)]; } + (void)bk_registerDynamicDelegate { [self bk_registerDynamicDelegateNamed:@"delegate" forProtocol:a2_delegateProtocol(self)]; } + (void)bk_registerDynamicDataSourceNamed:(NSString *)dataSourceName { [self bk_registerDynamicDelegateNamed:dataSourceName forProtocol:a2_dataSourceProtocol(self)]; } + (void)bk_registerDynamicDelegateNamed:(NSString *)delegateName { [self bk_registerDynamicDelegateNamed:delegateName forProtocol:a2_delegateProtocol(self)]; } + (void)bk_registerDynamicDelegateNamed:(NSString *)delegateName forProtocol:(Protocol *)protocol { NSMapTable *propertyMap = [self bk_delegateInfoByProtocol:YES]; A2BlockDelegateInfo *infoAsPtr = (__bridge void *)[propertyMap objectForKey:protocol]; if (infoAsPtr != NULL) { return; } const char *name = delegateName.UTF8String; objc_property_t property = class_getProperty(self, name); SEL setter = setterForProperty(property, name); SEL a2_setter = prefixedSelector(setter); SEL getter = getterForProperty(property, name); A2BlockDelegateInfo info = { setter, a2_setter, getter }; [propertyMap setObject:(__bridge id)&info forKey:protocol]; infoAsPtr = (__bridge void *)[propertyMap objectForKey:protocol]; IMP setterImplementation = imp_implementationWithBlock(^(NSObject *delegatingObject, id delegate) { A2DynamicDelegate *dynamicDelegate = getDynamicDelegate(delegatingObject, protocol, infoAsPtr, YES); if ([delegate isEqual:dynamicDelegate]) { delegate = nil; } dynamicDelegate.realDelegate = delegate; }); if (!swizzleWithIMP(self, setter, a2_setter, setterImplementation, "v@:@", YES)) { bzero(infoAsPtr, sizeof(A2BlockDelegateInfo)); return; } if (![self instancesRespondToSelector:getter]) { IMP getterImplementation = imp_implementationWithBlock(^(NSObject *delegatingObject) { return [delegatingObject bk_dynamicDelegateForProtocol:a2_protocolForDelegatingObject(delegatingObject, protocol)]; }); addMethodWithIMP(self, getter, NULL, getterImplementation, "@@:", NO); } } - (id)bk_ensuredDynamicDelegate { Protocol *protocol = a2_delegateProtocol(self.class); return [self bk_ensuredDynamicDelegateForProtocol:protocol]; } - (id)bk_ensuredDynamicDelegateForProtocol:(Protocol *)protocol { const A2BlockDelegateInfo *info = [self.class bk_delegateInfoForProtocol:protocol]; return getDynamicDelegate(self, protocol, info, YES); } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/DynamicDelegate/NSObject+A2DynamicDelegate.h ================================================ // // NSObject+A2DynamicDelegate.h // BlocksKit // #import #import /** The A2DynamicDelegate category to NSObject provides the primary interface by which dynamic delegates are generated for a given object. */ @interface NSObject (A2DynamicDelegate) /** Creates or gets a dynamic data source for the reciever. A2DynamicDelegate assumes a protocol name `FooBarDataSource` for instances of class `FooBar`. The object is given a strong attachment to the reciever, and is automatically deallocated when the reciever is released. If the user implements a `A2DynamicFooBarDataSource` subclass of A2DynamicDelegate, its implementation of any method will be used over the block. If the block needs to be used, it can be called from within the custom implementation using blockImplementationForMethod:. @see blockImplementationForMethod: @return A dynamic data source. */ - (id)bk_dynamicDataSource; /** Creates or gets a dynamic delegate for the reciever. A2DynamicDelegate assumes a protocol name `FooBarDelegate` for instances of class `FooBar`. The object is given a strong attachment to the reciever, and is automatically deallocated when the reciever is released. If the user implements a `A2DynamicFooBarDelegate` subclass of A2DynamicDelegate, its implementation of any method will be used over the block. If the block needs to be used, it can be called from within the custom implementation using blockImplementationForMethod:. @see blockImplementationForMethod: @return A dynamic delegate. */ - (id)bk_dynamicDelegate; /** Creates or gets a dynamic protocol implementation for the reciever. The designated initializer. The object is given a strong attachment to the reciever, and is automatically deallocated when the reciever is released. If the user implements a subclass of A2DynamicDelegate prepended with `A2Dynamic`, such as `A2DynamicFooProvider`, its implementation of any method will be used over the block. If the block needs to be used, it can be called from within the custom implementation using blockImplementationForMethod:. @param protocol A custom protocol. @return A dynamic protocol implementation. @see blockImplementationForMethod: */ - (id)bk_dynamicDelegateForProtocol:(Protocol *)protocol; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/DynamicDelegate/NSObject+A2DynamicDelegate.m ================================================ // // NSObject+A2DynamicDelegate.m // BlocksKit // #import #import "NSObject+A2DynamicDelegate.h" extern Protocol *a2_dataSourceProtocol(Class cls); extern Protocol *a2_delegateProtocol(Class cls); static Class a2_dynamicDelegateClass(Class cls, NSString *suffix) { while (cls) { NSString *className = [NSString stringWithFormat:@"A2Dynamic%@%@", NSStringFromClass(cls), suffix]; Class ddClass = NSClassFromString(className); if (ddClass) return ddClass; cls = class_getSuperclass(cls); } return [A2DynamicDelegate class]; } static dispatch_queue_t a2_backgroundQueue(void) { static dispatch_once_t onceToken; static dispatch_queue_t backgroundQueue = nil; dispatch_once(&onceToken, ^{ backgroundQueue = dispatch_queue_create("BlocksKit.DynamicDelegate.Queue", DISPATCH_QUEUE_SERIAL); }); return backgroundQueue; } @implementation NSObject (A2DynamicDelegate) - (id)bk_dynamicDataSource { Protocol *protocol = a2_dataSourceProtocol([self class]); Class class = a2_dynamicDelegateClass([self class], @"DataSource"); return [self bk_dynamicDelegateWithClass:class forProtocol:protocol]; } - (id)bk_dynamicDelegate { Protocol *protocol = a2_delegateProtocol([self class]); Class class = a2_dynamicDelegateClass([self class], @"Delegate"); return [self bk_dynamicDelegateWithClass:class forProtocol:protocol]; } - (id)bk_dynamicDelegateForProtocol:(Protocol *)protocol { Class class = [A2DynamicDelegate class]; NSString *protocolName = NSStringFromProtocol(protocol); if ([protocolName hasSuffix:@"Delegate"]) { class = a2_dynamicDelegateClass([self class], @"Delegate"); } else if ([protocolName hasSuffix:@"DataSource"]) { class = a2_dynamicDelegateClass([self class], @"DataSource"); } return [self bk_dynamicDelegateWithClass:class forProtocol:protocol]; } - (id)bk_dynamicDelegateWithClass:(Class)cls forProtocol:(Protocol *)protocol { /** * Storing the dynamic delegate as an associated object of the delegating * object not only allows us to later retrieve the delegate, but it also * creates a strong relationship to the delegate. Since delegates are weak * references on the part of the delegating object, a dynamic delegate * would be deallocated immediately after its declaring scope ends. * Therefore, this strong relationship is required to ensure that the * delegate's lifetime is at least as long as that of the delegating object. **/ __block A2DynamicDelegate *dynamicDelegate; dispatch_sync(a2_backgroundQueue(), ^{ dynamicDelegate = objc_getAssociatedObject(self, (__bridge const void *)protocol); if (!dynamicDelegate) { dynamicDelegate = [[cls alloc] initWithProtocol:protocol]; objc_setAssociatedObject(self, (__bridge const void *)protocol, dynamicDelegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } }); return dynamicDelegate; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/MessageUI/MFMailComposeViewController+BlocksKit.h ================================================ // // MFMailComposeViewController+BlocksKit.h // BlocksKit // #import /** MFMailComposeViewController with block callbacks. If you provide a completion handler to an instance of MFMailComposeViewController but do not implement a delegate callback for mailComposeController:didFinishWithResult:error:, the mail compose view controller will automatically be dismissed if it was launched modally. Created by [Igor Evsukov](https://github.com/evsukov89) and contributed to BlocksKit. @warning MFMailComposeViewController is only available on a platform with MessageUI. */ @interface MFMailComposeViewController (BlocksKit) /** The block fired on the dismissal of the mail composition interface. This block callback is an analog for the mailComposeController:didFinishWithResult:error:method of MFMailComposeViewControllerDelegate. */ @property (nonatomic, copy, setter = bk_setCompletionBlock:) void (^bk_completionBlock)(MFMailComposeViewController *controller, MFMailComposeResult result, NSError *error); @end ================================================ FILE: Pods/BlocksKit/BlocksKit/MessageUI/MFMailComposeViewController+BlocksKit.m ================================================ // // MFMailComposeViewController+BlocksKit.m // BlocksKit // #import "A2DynamicDelegate.h" #import "MFMailComposeViewController+BlocksKit.h" #import "NSObject+A2BlockDelegate.h" #pragma mark Custom delegate @interface A2DynamicMFMailComposeViewControllerDelegate : A2DynamicDelegate @end @implementation A2DynamicMFMailComposeViewControllerDelegate - (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error { id realDelegate = self.realDelegate; BOOL shouldDismiss = (realDelegate && [realDelegate respondsToSelector:@selector(mailComposeController:didFinishWithResult:error:)]); if (shouldDismiss) [realDelegate mailComposeController:controller didFinishWithResult:result error:error]; void (^block)(MFMailComposeViewController *, MFMailComposeResult, NSError *) = [self blockImplementationForMethod:_cmd]; if (shouldDismiss) { if (block) block(controller, result, error); } else { #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000 __weak typeof(controller) weakController = controller; [controller dismissViewControllerAnimated:YES completion:^{ typeof(&*weakController) strongController = weakController; if (block) block(strongController, result, error); }]; #else #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000 if ([controller respondsToSelector:@selector(dismissViewControllerAnimated:completion:)]) { __weak typeof(controller) weakController = controller; [controller dismissViewControllerAnimated:YES completion:^{ typeof(&*weakController) strongController = weakController; if (block) block(strongController, result, error); }]; } else { #endif [controller dismissModalViewControllerAnimated:YES]; if (block) block(controller, result, error); #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000 } #endif #endif } } @end #pragma mark Category @implementation MFMailComposeViewController (BlocksKit) @dynamic bk_completionBlock; + (void)load { @autoreleasepool { [self bk_registerDynamicDelegateNamed:@"mailComposeDelegate"]; [self bk_linkDelegateMethods:@{ @"bk_completionBlock": @"mailComposeController:didFinishWithResult:error:" }]; } } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/MessageUI/MFMessageComposeViewController+BlocksKit.h ================================================ // // MFMessageComposeViewController+BlocksKit.h // BlocksKit // #import /** MFMessageComposeViewController with block callback in addition to delegation. If you provide a completion handler to an instance of MFMessageComposeViewController but do not implement a delegate callback for messageComposeViewController:didFinishWithResult:error:, the message compose view controller will automatically be dismissed if it was launched modally. Created by [Igor Evsukov](https://github.com/evsukov89) and contributed to BlocksKit. @warning MFMessageComposeViewController is only available on a platform with MessageUI. */ @interface MFMessageComposeViewController (BlocksKit) /** The block fired on the dismissal of the SMS composition interface. This block callback is an analog for the messageComposeViewController:didFinishWithResult: method of MFMessageComposeViewControllerDelegate. */ @property (nonatomic, copy, setter = bk_setCompletionBlock:) void (^bk_completionBlock)(MFMessageComposeViewController *controller, MessageComposeResult result); @end ================================================ FILE: Pods/BlocksKit/BlocksKit/MessageUI/MFMessageComposeViewController+BlocksKit.m ================================================ // // MFMessageComposeViewController+BlocksKit.m // BlocksKit // #import "A2DynamicDelegate.h" #import "MFMessageComposeViewController+BlocksKit.h" #import "NSObject+A2BlockDelegate.h" #pragma mark Custom delegate @interface A2DynamicMFMessageComposeViewControllerDelegate : A2DynamicDelegate @end @implementation A2DynamicMFMessageComposeViewControllerDelegate - (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result { id realDelegate = self.realDelegate; BOOL shouldDismiss = (realDelegate && [realDelegate respondsToSelector:@selector(messageComposeViewController:didFinishWithResult:)]); if (shouldDismiss) [realDelegate messageComposeViewController:controller didFinishWithResult:result]; void (^block)(MFMessageComposeViewController *, MessageComposeResult) = [self blockImplementationForMethod:_cmd]; if (shouldDismiss) { if (block) block(controller, result); } else { #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000 __weak typeof(controller) weakController = controller; [controller dismissViewControllerAnimated:YES completion:^{ typeof(&*weakController) strongController = weakController; if (block) block(strongController, result); }]; #else #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000 if ([controller respondsToSelector:@selector(dismissViewControllerAnimated:completion:)]) { __weak typeof(controller) weakController = controller; [controller dismissViewControllerAnimated:YES completion:^{ typeof(&*weakController) strongController = weakController; if (block) block(strongController, result); }]; } else { #endif [controller dismissModalViewControllerAnimated:YES]; if (block) block(controller, result); #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000 } #endif #endif } } @end #pragma mark - Category @implementation MFMessageComposeViewController (BlocksKit) @dynamic bk_completionBlock; + (void)load { @autoreleasepool { [self bk_registerDynamicDelegateNamed:@"messageComposeDelegate"]; [self bk_linkDelegateMethods:@{ @"bk_completionBlock": @"messageComposeViewController:didFinishWithResult:" }]; } } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UIActionSheet+BlocksKit.h ================================================ // // UIActionSheet+BlocksKit.h // BlocksKit // #import /** UIActionSheet without delegates! This set of extensions and convenience classes allows for an instance of UIActionSheet without the implementation of a delegate. Any time you instantiate a UIActionSheet using the methods here, you must add buttons using addButtonWithTitle:handler: to make sure nothing breaks. A typical invocation might go like this: UIActionSheet *testSheet = [UIActionSheet actionSheetWithTitle:@"Please select one."]; [testSheet addButtonWithTitle:@"Zip" handler:^{ NSLog(@"Zip!"); }]; [testSheet addButtonWithTitle:@"Zap" handler:^{ NSLog(@"Zap!"); }]; [testSheet addButtonWithTitle:@"Zop" handler:^{ NSLog(@"Zop!"); }]; [testSheet setDestructiveButtonWithTitle:@"No!" handler:^{ NSLog(@"Fine!"); }]; [testSheet setCancelButtonWithTitle:nil handler:^{ NSLog(@"Never mind, then!"); }]; [testSheet showInView:self.view]; Includes code by the following: - [Landon Fuller](http://landonf.bikemonkey.org), "Using Blocks". - [Peter Steinberger](https://github.com/steipete) - [Zach Waldowski](https://github.com/zwaldowski) @warning UIActionSheet is only available on a platform with UIKit. */ @interface UIActionSheet (BlocksKit) ///----------------------------------- /// @name Creating action sheets ///----------------------------------- /** Creates and returns a new action sheet with only a title and cancel button. @param title The header of the action sheet. @return A newly created action sheet. */ + (id)bk_actionSheetWithTitle:(NSString *)title; /** Returns a configured action sheet with only a title and cancel button. @param title The header of the action sheet. @return An instantiated actionSheet. */ - (id)bk_initWithTitle:(NSString *)title NS_REPLACES_RECEIVER; ///----------------------------------- /// @name Adding buttons ///----------------------------------- /** Add a new button with an associated code block. @param title The text of the button. @param block A block of code. */ - (NSInteger)bk_addButtonWithTitle:(NSString *)title handler:(void (^)(void))block; /** Set the destructive (red) button with an associated code block. @warning Because buttons cannot be removed from an action sheet, be aware that the effects of calling this method are cumulative. Previously added destructive buttons will become normal buttons. @param title The text of the button. @param block A block of code. */ - (NSInteger)bk_setDestructiveButtonWithTitle:(NSString *)title handler:(void (^)(void))block; /** Set the title and trigger of the cancel button. `block` can be set to `nil`, but this is generally useless as the cancel button is configured already to do nothing. iPhone users will have the button shown regardless; if the title is set to `nil`, it will automatically be localized. @param title The text of the button. @param block A block of code. */ - (NSInteger)bk_setCancelButtonWithTitle:(NSString *)title handler:(void (^)(void))block; ///----------------------------------- /// @name Altering actions ///----------------------------------- /** Sets the block that is to be fired when a button is pressed. @param block A code block, or nil to set no response. @param index The index of a button already added to the action sheet. */ - (void)bk_setHandler:(void (^)(void))block forButtonAtIndex:(NSInteger)index; /** The block that is to be fired when a button is pressed. @param index The index of a button already added to the action sheet. @return A code block, or nil if no block is assigned. */ - (void (^)(void))bk_handlerForButtonAtIndex:(NSInteger)index; /** The block to be fired when the action sheet is dismissed with the cancel button and/or action. This property performs the same action as setCancelButtonWithTitle:handler: but with `title` set to nil. Contrary to setCancelButtonWithTitle:handler:, you can set this property multiple times and multiple cancel buttons will not be generated. */ @property (nonatomic, copy, setter = bk_setCancelBlock:) void (^bk_cancelBlock)(void); /** The block to be fired before the action sheet will show. */ @property (nonatomic, copy, setter = bk_setWillShowBlock:) void (^bk_willShowBlock)(UIActionSheet *actionSheet); /** The block to be fired when the action sheet shows. */ @property (nonatomic, copy, setter = bk_setDidShowBlock:) void (^bk_didShowBlock)(UIActionSheet *actionSheet); /** The block to be fired before the action sheet will dismiss. */ @property (nonatomic, copy, setter = bk_setWillDismissBlock:) void (^bk_willDismissBlock)(UIActionSheet *actionSheet, NSInteger buttonIndex); /** The block to be fired after the action sheet dismisses. */ @property (nonatomic, copy, setter = bk_setDidDismissBlock:) void (^bk_didDismissBlock)(UIActionSheet *actionSheet, NSInteger buttonIndex); @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UIActionSheet+BlocksKit.m ================================================ // // UIActionSheet+BlocksKit.m // BlocksKit // #import "NSObject+A2BlockDelegate.h" #import "NSObject+A2DynamicDelegate.h" #import "UIActionSheet+BlocksKit.h" #pragma mark Custom delegate @interface A2DynamicUIActionSheetDelegate : A2DynamicDelegate @end @implementation A2DynamicUIActionSheetDelegate - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(actionSheet:clickedButtonAtIndex:)]) [realDelegate actionSheet:actionSheet clickedButtonAtIndex:buttonIndex]; void (^block)(void) = self.handlers[@(buttonIndex)]; if (block) block(); } - (void)willPresentActionSheet:(UIActionSheet *)actionSheet { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(willPresentActionSheet:)]) [realDelegate willPresentActionSheet:actionSheet]; void (^block)(UIActionSheet *) = [self blockImplementationForMethod:_cmd]; if (block) block(actionSheet); } - (void)didPresentActionSheet:(UIActionSheet *)actionSheet { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(didPresentActionSheet:)]) [realDelegate didPresentActionSheet:actionSheet]; void (^block)(UIActionSheet *) = [self blockImplementationForMethod:_cmd]; if (block) block(actionSheet); } - (void)actionSheet:(UIActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(actionSheet:willDismissWithButtonIndex:)]) [realDelegate actionSheet:actionSheet willDismissWithButtonIndex:buttonIndex]; void (^block)(UIActionSheet *, NSInteger) = [self blockImplementationForMethod:_cmd]; if (block) block(actionSheet, buttonIndex); } - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(actionSheet:didDismissWithButtonIndex:)]) [realDelegate actionSheet:actionSheet didDismissWithButtonIndex:buttonIndex]; void (^block)(UIActionSheet *, NSInteger) = [self blockImplementationForMethod:_cmd]; if (block) block(actionSheet, buttonIndex); } - (void)actionSheetCancel:(UIActionSheet *)actionSheet { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(actionSheetCancel:)]) [realDelegate actionSheetCancel:actionSheet]; void (^block)(void) = actionSheet.bk_cancelBlock; if (block) block(); } @end #pragma mark - Category @implementation UIActionSheet (BlocksKit) @dynamic bk_willShowBlock, bk_didShowBlock, bk_willDismissBlock, bk_didDismissBlock; + (void)load { @autoreleasepool { [self bk_registerDynamicDelegate]; [self bk_linkDelegateMethods:@{ @"bk_willShowBlock": @"willPresentActionSheet:", @"bk_didShowBlock": @"didPresentActionSheet:", @"bk_willDismissBlock": @"actionSheet:willDismissWithButtonIndex:", @"bk_didDismissBlock": @"actionSheet:didDismissWithButtonIndex:" }]; } } #pragma mark Initializers + (id)bk_actionSheetWithTitle:(NSString *)title { return [[[self class] alloc] bk_initWithTitle:title]; } - (id)bk_initWithTitle:(NSString *)title { self = [self initWithTitle:title delegate:self.bk_dynamicDelegate cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil]; if (!self) { return nil; } self.delegate = self.bk_dynamicDelegate; return self; } #pragma mark Actions - (NSInteger)bk_addButtonWithTitle:(NSString *)title handler:(void (^)(void))block { NSAssert(title.length, @"A button without a title cannot be added to an action sheet."); NSInteger index = [self addButtonWithTitle:title]; [self bk_setHandler:block forButtonAtIndex:index]; return index; } - (NSInteger)bk_setDestructiveButtonWithTitle:(NSString *)title handler:(void (^)(void))block { NSInteger index = [self bk_addButtonWithTitle:title handler:block]; self.destructiveButtonIndex = index; return index; } - (NSInteger)bk_setCancelButtonWithTitle:(NSString *)title handler:(void (^)(void))block { NSInteger cancelButtonIndex = self.cancelButtonIndex; if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) && !title.length) title = NSLocalizedString(@"Cancel", nil); if (title.length) cancelButtonIndex = [self addButtonWithTitle:title]; [self bk_setHandler:block forButtonAtIndex:cancelButtonIndex]; self.cancelButtonIndex = cancelButtonIndex; return cancelButtonIndex; } #pragma mark Properties - (void)bk_setHandler:(void (^)(void))block forButtonAtIndex:(NSInteger)index { A2DynamicUIActionSheetDelegate *delegate = self.bk_ensuredDynamicDelegate; if (block) { delegate.handlers[@(index)] = [block copy]; } else { [delegate.handlers removeObjectForKey:@(index)]; } } - (void (^)(void))bk_handlerForButtonAtIndex:(NSInteger)index { return [self.bk_dynamicDelegate handlers][@(index)]; } - (void (^)(void))bk_cancelBlock { return [self bk_handlerForButtonAtIndex:self.cancelButtonIndex]; } - (void)bk_setCancelBlock:(void (^)(void))block { [self bk_setHandler:block forButtonAtIndex:self.cancelButtonIndex]; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UIAlertView+BlocksKit.h ================================================ // // UIAlertView+BlocksKit.h // BlocksKit // #import /** UIAlertView without delegates! This set of extensions and convenience classes allows for an instance of UIAlertView without the implementation of a delegate. Any time you instantiate a UIAlertView using the methods here, you must add buttons using addButtonWithTitle:handler:otherwise nothing will happen. A typical invocation will go like this: UIAlertView *testView = [UIAlertView alertViewWithTitle:@"Application Alert" message:@"This app will explode in 42 seconds."]; [testView setCancelButtonWithTitle:@"Oh No!" handler:^{ NSLog(@"Boom!"); }]; [testView show]; A more traditional, and more useful, modal dialog looks like so: UIAlertView *testView = [UIAlertView alertViewWithTitle:@"Very important!" message:@"Do you like chocolate?"]; [testView addButtonWithTitle:@"Yes" handler:^{ NSLog(@"Yay!"); }]; [testView addButtonWithTitle:@"No" handler:^{ NSLog(@"We hate you."); }]; [testView show]; Includes code by the following: - [Landon Fuller](http://landonf.bikemonkey.org), "Using Blocks". - [Peter Steinberger](https://github.com/steipete) - [Zach Waldowski](https://github.com/zwaldowski) @warning UIAlertView is only available on a platform with UIKit. */ @interface UIAlertView (BlocksKit) ///----------------------------------- /// @name Creating alert views ///----------------------------------- /** Creates and shows a new alert view with only a title, message, and cancel button. @param title The title of the alert view. @param message The message content of the alert. @param cancelButtonTitle The title of the cancel button. If both cancelButtonTitle and otherButtonTitles are empty or nil, defaults to a @param otherButtonTitles Titles of additional buttons to add to the receiver. @param block A block of code to be fired on the dismissal of the alert view. @return The UIAlertView. */ + (UIAlertView*)bk_showAlertViewWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSArray *)otherButtonTitles handler:(void (^)(UIAlertView *alertView, NSInteger buttonIndex))block; /** Creates and returns a new alert view with only a title and cancel button. @param title The title of the alert view. @return A newly created alert view. */ + (id)bk_alertViewWithTitle:(NSString *)title; /** Creates and returns a new alert view with only a title, message, and cancel button. @param title The title of the alert view. @param message The message content of the alert. @return A newly created alert view. */ + (id)bk_alertViewWithTitle:(NSString *)title message:(NSString *)message; /** Returns a configured alert view with only a title, message, and cancel button. @param title The title of the alert view. @param message The message content of the alert. @return An instantiated alert view. */ - (id)bk_initWithTitle:(NSString *)title message:(NSString *)message NS_REPLACES_RECEIVER; ///----------------------------------- /// @name Adding buttons ///----------------------------------- /** Add a new button with an associated code block. @param title The text of the button. @param block A block of code. */ - (NSInteger)bk_addButtonWithTitle:(NSString *)title handler:(void (^)(void))block; /** Set the title and trigger of the cancel button. @param title The text of the button. @param block A block of code. */ - (NSInteger)bk_setCancelButtonWithTitle:(NSString *)title handler:(void (^)(void))block; ///----------------------------------- /// @name Altering actions ///----------------------------------- /** Sets the block that is to be fired when a button is pressed. @param block A code block, or nil to set no response. @param index The index of a button already added to the action sheet. */ - (void)bk_setHandler:(void (^)(void))block forButtonAtIndex:(NSInteger)index; /** The block that is to be fired when a button is pressed. @param index The index of the button already added to the alert view. @return A code block, or nil if no block yet assigned. */ - (void (^)(void))bk_handlerForButtonAtIndex:(NSInteger)index; /** The block to be fired when the action sheet is dismissed with the cancel button. Contrary to setCancelButtonWithTitle:handler:, you can set this property multiple times but multiple cancel buttons will not be generated. */ @property (nonatomic, copy, setter = bk_setCancelBlock:) void (^bk_cancelBlock)(void); /** The block to be fired before the alert view will show. */ @property (nonatomic, copy, setter = bk_setWillShowBlock:) void (^bk_willShowBlock)(UIAlertView *alertView); /** The block to be fired when the alert view shows. */ @property (nonatomic, copy, setter = bk_setDidShowBlock:) void (^bk_didShowBlock)(UIAlertView *alertView); /** The block to be fired before the alert view will dismiss. */ @property (nonatomic, copy, setter = bk_setWillDismissBlock:) void (^bk_willDismissBlock)(UIAlertView *alertView, NSInteger buttonIndex); /** The block to be fired after the alert view dismisses. */ @property (nonatomic, copy, setter = bk_setDidDismissBlock:) void (^bk_didDismissBlock)(UIAlertView *alertView, NSInteger buttonIndex); /** The block to be fired to determine whether the first non-cancel should be enabled */ @property (nonatomic, copy, setter = bk_SetShouldEnableFirstOtherButtonBlock:) BOOL (^bk_shouldEnableFirstOtherButtonBlock)(UIAlertView *alertView) NS_AVAILABLE_IOS(5_0); @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UIAlertView+BlocksKit.m ================================================ // // UIAlertView+BlocksKit.m // BlocksKit // #import "A2DynamicDelegate.h" #import "NSObject+A2BlockDelegate.h" #import "NSObject+A2DynamicDelegate.h" #import "UIAlertView+BlocksKit.h" #pragma mark Delegate @interface A2DynamicUIAlertViewDelegate : A2DynamicDelegate @end @implementation A2DynamicUIAlertViewDelegate - (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView { BOOL should = YES; id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(alertViewShouldEnableFirstOtherButton:)]) should &= [realDelegate alertViewShouldEnableFirstOtherButton:alertView]; BOOL (^block)(UIAlertView *) = [self blockImplementationForMethod:_cmd]; if (block) should &= block(alertView); return should; } - (void)alertViewCancel:(UIAlertView *)alertView { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(alertViewCancel:)]) [realDelegate alertViewCancel:alertView]; id key = @(alertView.cancelButtonIndex); void (^cancelBlock)(void) = (self.handlers)[key]; if (cancelBlock) cancelBlock(); } - (void)willPresentAlertView:(UIAlertView *)alertView { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(willPresentAlertView:)]) [realDelegate willPresentAlertView:alertView]; void (^block)(UIAlertView *) = [self blockImplementationForMethod:_cmd]; if (block) block(alertView); } - (void)didPresentAlertView:(UIAlertView *)alertView { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(didPresentAlertView:)]) [realDelegate didPresentAlertView:alertView]; void (^block)(UIAlertView *) = [self blockImplementationForMethod:_cmd]; if (block) block(alertView); } - (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(alertView:willDismissWithButtonIndex:)]) [realDelegate alertView:alertView willDismissWithButtonIndex:buttonIndex]; void (^block)(UIAlertView *, NSInteger) = [self blockImplementationForMethod:_cmd]; if (block) block(alertView, buttonIndex); } - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(alertView:didDismissWithButtonIndex:)]) [realDelegate alertView:alertView didDismissWithButtonIndex:buttonIndex]; void (^block)(UIAlertView *, NSInteger) = [self blockImplementationForMethod:_cmd]; if (block) block(alertView, buttonIndex); } - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(alertView:clickedButtonAtIndex:)]) [realDelegate alertView:alertView clickedButtonAtIndex:buttonIndex]; void (^block)(UIAlertView *, NSInteger) = [self blockImplementationForMethod:_cmd]; if (block) block(alertView, buttonIndex); id key = @(buttonIndex); void (^buttonBlock)(void) = (self.handlers)[key]; if (buttonBlock) buttonBlock(); } @end #pragma mark - Category @implementation UIAlertView (BlocksKit) @dynamic bk_willShowBlock, bk_didShowBlock, bk_willDismissBlock, bk_didDismissBlock, bk_shouldEnableFirstOtherButtonBlock; + (void)load { @autoreleasepool { [self bk_registerDynamicDelegate]; [self bk_linkDelegateMethods:@{ @"bk_willShowBlock": @"willPresentAlertView:", @"bk_didShowBlock": @"didPresentAlertView:", @"bk_willDismissBlock": @"alertView:willDismissWithButtonIndex:", @"bk_didDismissBlock": @"alertView:didDismissWithButtonIndex:", @"bk_shouldEnableFirstOtherButtonBlock": @"alertViewShouldEnableFirstOtherButton:" }]; } } #pragma mark Convenience + (UIAlertView*)bk_showAlertViewWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSArray *)otherButtonTitles handler:(void (^)(UIAlertView *alertView, NSInteger buttonIndex))block { // If no buttons were specified, cancel button becomes "Dismiss" if (!cancelButtonTitle.length && !otherButtonTitles.count) cancelButtonTitle = NSLocalizedString(@"Dismiss", nil); UIAlertView *alertView = [[[self class] alloc] initWithTitle:title message:message delegate:self.bk_dynamicDelegate cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil]; // Set other buttons [otherButtonTitles enumerateObjectsUsingBlock:^(NSString *button, NSUInteger idx, BOOL *stop) { [alertView addButtonWithTitle:button]; }]; // Set `didDismissBlock` if (block) alertView.bk_didDismissBlock = block; // Show alert view [alertView show]; return alertView; } #pragma mark Initializers + (id)bk_alertViewWithTitle:(NSString *)title { return [self bk_alertViewWithTitle:title message:nil]; } + (id)bk_alertViewWithTitle:(NSString *)title message:(NSString *)message { return [[[self class] alloc] bk_initWithTitle:title message:message]; } - (id)bk_initWithTitle:(NSString *)title message:(NSString *)message { self = [self initWithTitle:title message:message delegate:nil cancelButtonTitle:nil otherButtonTitles:nil]; if (!self) return nil; self.delegate = self.bk_dynamicDelegate; return self; } #pragma Actions - (NSInteger)bk_addButtonWithTitle:(NSString *)title handler:(void (^)(void))block { NSAssert(title.length, @"A button without a title cannot be added to the alert view."); NSInteger index = [self addButtonWithTitle:title]; [self bk_setHandler:block forButtonAtIndex:index]; return index; } - (NSInteger)bk_setCancelButtonWithTitle:(NSString *)title handler:(void (^)(void))block { if (!title.length) title = NSLocalizedString(@"Cancel", nil); NSInteger cancelButtonIndex = [self addButtonWithTitle:title]; self.cancelButtonIndex = cancelButtonIndex; [self bk_setHandler:block forButtonAtIndex:cancelButtonIndex]; return cancelButtonIndex; } #pragma mark Properties - (void)bk_setHandler:(void (^)(void))block forButtonAtIndex:(NSInteger)index { id key = @(index); if (block) [self.bk_dynamicDelegate handlers][key] = [block copy]; else [[self.bk_dynamicDelegate handlers] removeObjectForKey:key]; } - (void (^)(void))bk_handlerForButtonAtIndex:(NSInteger)index { return [self.bk_dynamicDelegate handlers][@(index)]; } - (void (^)(void))bk_cancelBlock { return [self bk_handlerForButtonAtIndex:self.cancelButtonIndex]; } - (void)bk_setCancelBlock:(void (^)(void))block { if (block && self.cancelButtonIndex == -1) { [self bk_setCancelButtonWithTitle:nil handler:block]; return; } [self bk_setHandler:block forButtonAtIndex:self.cancelButtonIndex]; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UIBarButtonItem+BlocksKit.h ================================================ // // UIBarButtonItem+BlocksKit.h // BlocksKit // #import /** Block event initialization for UIBarButtonItem. This set of extensions has near-drop-in replacements for the standard set of UIBarButton item initializations, using a block handler instead of a target/selector. Includes code by the following: - [Kevin O'Neill](https://github.com/kevinoneill) - [Zach Waldowski](https://github.com/zwaldowski) @warning UIBarButtonItem is only available on a platform with UIKit. */ @interface UIBarButtonItem (BlocksKit) /** Creates and returns a configured item containing the specified system item. @return Newly initialized item with the specified properties. @param systemItem The system item to use as the item representation. One of the constants defined in UIBarButtonSystemItem. @param action The block that gets fired on the button press. */ - (id)bk_initWithBarButtonSystemItem:(UIBarButtonSystemItem)systemItem handler:(void (^)(id sender))action NS_REPLACES_RECEIVER; /** Creates and returns a configured item using the specified image and style. @return Newly initialized item with the specified properties. @param image The item’s image. If nil an image is not displayed. If this image is too large to fit on the bar, it is scaled to fit The size of a toolbar and navigation bar image is 20 x 20 points. @param style The style of the item. One of the constants defined in UIBarButtonItemStyle. @param action The block that gets fired on the button press. */ - (id)bk_initWithImage:(UIImage *)image style:(UIBarButtonItemStyle)style handler:(void (^)(id sender))action NS_REPLACES_RECEIVER; /** Creates and returns a configured item using the specified image and style. @return Newly initialized item with the specified properties. @param image The item’s image. If nil an image is not displayed. @param landscapeImagePhone The image to be used for the item in landscape bars in the UIUserInterfaceIdiomPhone idiom. @param style The style of the item. One of the constants defined in UIBarButtonItemStyle. @param action The block that gets fired on the button press. */ - (id)bk_initWithImage:(UIImage *)image landscapeImagePhone:(UIImage *)landscapeImagePhone style:(UIBarButtonItemStyle)style handler:(void (^)(id sender))action NS_REPLACES_RECEIVER NS_AVAILABLE_IOS(5_0); /** Creates and returns a configured item using the specified text and style. @return Newly initialized item with the specified properties. @param title The text displayed on the button item. @param style The style of the item. One of the constants defined in UIBarButtonItemStyle. @param action The block that gets fired on the button press. */ - (id)bk_initWithTitle:(NSString *)title style:(UIBarButtonItemStyle)style handler:(void (^)(id sender))action NS_REPLACES_RECEIVER; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UIBarButtonItem+BlocksKit.m ================================================ // // UIBarButtonItem+BlocksKit.m // BlocksKit // #import #import "UIBarButtonItem+BlocksKit.h" static const void *BKBarButtonItemBlockKey = &BKBarButtonItemBlockKey; @interface UIBarButtonItem (BlocksKitPrivate) - (void)bk_handleAction:(UIBarButtonItem *)sender; @end @implementation UIBarButtonItem (BlocksKit) - (id)bk_initWithBarButtonSystemItem:(UIBarButtonSystemItem)systemItem handler:(void (^)(id sender))action { self = [self initWithBarButtonSystemItem:systemItem target:self action:@selector(bk_handleAction:)]; if (!self) return nil; objc_setAssociatedObject(self, BKBarButtonItemBlockKey, action, OBJC_ASSOCIATION_COPY_NONATOMIC); return self; } - (id)bk_initWithImage:(UIImage *)image style:(UIBarButtonItemStyle)style handler:(void (^)(id sender))action { self = [self initWithImage:image style:style target:self action:@selector(bk_handleAction:)]; if (!self) return nil; objc_setAssociatedObject(self, BKBarButtonItemBlockKey, action, OBJC_ASSOCIATION_COPY_NONATOMIC); return self; } - (id)bk_initWithImage:(UIImage *)image landscapeImagePhone:(UIImage *)landscapeImagePhone style:(UIBarButtonItemStyle)style handler:(void (^)(id sender))action { self = [self initWithImage:image landscapeImagePhone:landscapeImagePhone style:style target:self action:@selector(bk_handleAction:)]; if (!self) return nil; objc_setAssociatedObject(self, BKBarButtonItemBlockKey, action, OBJC_ASSOCIATION_COPY_NONATOMIC); return self; } - (id)bk_initWithTitle:(NSString *)title style:(UIBarButtonItemStyle)style handler:(void (^)(id sender))action { self = [self initWithTitle:title style:style target:self action:@selector(bk_handleAction:)]; if (!self) return nil; objc_setAssociatedObject(self, BKBarButtonItemBlockKey, action, OBJC_ASSOCIATION_COPY_NONATOMIC); return self; } - (void)bk_handleAction:(UIBarButtonItem *)sender { void (^block)(id) = objc_getAssociatedObject(self, BKBarButtonItemBlockKey); if (block) block(self); } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UIControl+BlocksKit.h ================================================ // // UIControl+BlocksKit.h // BlocksKit // #import /** Block control event handling for UIControl. Includes code by the following: - [Kevin O'Neill](https://github.com/kevinoneill) - [Zach Waldowski](https://github.com/zwaldowski) @warning UIControl is only available on a platform with UIKit. */ @interface UIControl (BlocksKit) ///----------------------------------- /// @name Block event handling ///----------------------------------- /** Adds a block for a particular event to an internal dispatch table. @param handler A block representing an action message, with an argument for the sender. @param controlEvents A bitmask specifying the control events for which the action message is sent. @see removeEventHandlersForControlEvents: */ - (void)bk_addEventHandler:(void (^)(id sender))handler forControlEvents:(UIControlEvents)controlEvents; /** Removes all blocks for a particular event combination. @param controlEvents A bitmask specifying the control events for which the block will be removed. @see addEventHandler:forControlEvents: */ - (void)bk_removeEventHandlersForControlEvents:(UIControlEvents)controlEvents; /** Checks to see if the control has any blocks for a particular event combination. @param controlEvents A bitmask specifying the control events for which to check for blocks. @see addEventHandler:forControlEvents: @return Returns YES if there are blocks for these control events, NO otherwise. */ - (BOOL)bk_hasEventHandlersForControlEvents:(UIControlEvents)controlEvents; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UIControl+BlocksKit.m ================================================ // // UIControl+BlocksKit.m // BlocksKit // #import #import "UIControl+BlocksKit.h" static const void *BKControlHandlersKey = &BKControlHandlersKey; #pragma mark Private @interface BKControlWrapper : NSObject - (id)initWithHandler:(void (^)(id sender))handler forControlEvents:(UIControlEvents)controlEvents; @property (nonatomic) UIControlEvents controlEvents; @property (nonatomic, copy) void (^handler)(id sender); @end @implementation BKControlWrapper - (id)initWithHandler:(void (^)(id sender))handler forControlEvents:(UIControlEvents)controlEvents { self = [super init]; if (!self) return nil; self.handler = handler; self.controlEvents = controlEvents; return self; } - (id)copyWithZone:(NSZone *)zone { return [[BKControlWrapper alloc] initWithHandler:self.handler forControlEvents:self.controlEvents]; } - (void)invoke:(id)sender { self.handler(sender); } @end #pragma mark Category @implementation UIControl (BlocksKit) - (void)bk_addEventHandler:(void (^)(id sender))handler forControlEvents:(UIControlEvents)controlEvents { NSParameterAssert(handler); NSMutableDictionary *events = objc_getAssociatedObject(self, BKControlHandlersKey); if (!events) { events = [NSMutableDictionary dictionary]; objc_setAssociatedObject(self, BKControlHandlersKey, events, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } NSNumber *key = @(controlEvents); NSMutableSet *handlers = events[key]; if (!handlers) { handlers = [NSMutableSet set]; events[key] = handlers; } BKControlWrapper *target = [[BKControlWrapper alloc] initWithHandler:handler forControlEvents:controlEvents]; [handlers addObject:target]; [self addTarget:target action:@selector(invoke:) forControlEvents:controlEvents]; } - (void)bk_removeEventHandlersForControlEvents:(UIControlEvents)controlEvents { NSMutableDictionary *events = objc_getAssociatedObject(self, BKControlHandlersKey); if (!events) { events = [NSMutableDictionary dictionary]; objc_setAssociatedObject(self, BKControlHandlersKey, events, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } NSNumber *key = @(controlEvents); NSSet *handlers = events[key]; if (!handlers) return; [handlers enumerateObjectsUsingBlock:^(id sender, BOOL *stop) { [self removeTarget:sender action:NULL forControlEvents:controlEvents]; }]; [events removeObjectForKey:key]; } - (BOOL)bk_hasEventHandlersForControlEvents:(UIControlEvents)controlEvents { NSMutableDictionary *events = objc_getAssociatedObject(self, BKControlHandlersKey); if (!events) { events = [NSMutableDictionary dictionary]; objc_setAssociatedObject(self, BKControlHandlersKey, events, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } NSNumber *key = @(controlEvents); NSSet *handlers = events[key]; if (!handlers) return NO; return !!handlers.count; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UIGestureRecognizer+BlocksKit.h ================================================ // // UIGestureRecognizer+BlocksKit.h // BlocksKit // #import /** Block functionality for UIGestureRecognizer. Use of the delay property is pretty straightforward, although cancellation might be a little harder to swallow. An example follows: UITapGestureRecognizer *singleTap = [UITapGestureRecognizer recognizerWithHandler:^(id sender) { NSLog(@"Single tap."); } delay:0.18]; [self addGestureRecognizer:singleTap]; UITapGestureRecognizer *doubleTap = [UITapGestureRecognizer recognizerWithHandler:^(id sender) { [singleTap cancel]; NSLog(@"Double tap."); }]; doubleTap.numberOfTapsRequired = 2; [self addGestureRecognizer:doubleTap]; Believe it or not, the above code is fully memory-safe and efficient. Eagle-eyed coders will notice that this setup emulates UIGestureRecognizer's requireGestureRecognizerToFail:, and, yes, it totally apes it. Not only is this setup much faster on the user's end of things, it is more flexible and allows for much more complicated setups. Includes code by the following: - [Kevin O'Neill](https://github.com/kevinoneill) - [Zach Waldowski](https://github.com/zwaldowski) @warning UIGestureRecognizer is only available on a platform with UIKit. @warning It is not recommended to use the Apple-supplied locationInView and state methods on a *delayed* block-backed gesture recognizer, as these properties are likely to have been cleared by the time by the block fires. It is instead recommended to use the arguments provided to the block. */ @interface UIGestureRecognizer (BlocksKit) /** An autoreleased gesture recognizer that will, on firing, call the given block asynchronously after a number of seconds. @return An autoreleased instance of a concrete UIGestureRecognizer subclass, or `nil`. @param block The block which handles an executed gesture. @param delay A number of seconds after which the block will fire. */ + (id)bk_recognizerWithHandler:(void (^)(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location))block delay:(NSTimeInterval)delay; /** Initializes an allocated gesture recognizer that will call the given block after a given delay. An alternative to the designated initializer. @return An initialized instance of a concrete UIGestureRecognizer subclass or `nil`. @param block The block which handles an executed gesture. @param delay A number of seconds after which the block will fire. */ - (id)bk_initWithHandler:(void (^)(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location))block delay:(NSTimeInterval)delay NS_REPLACES_RECEIVER; /** An autoreleased gesture recognizer that will call the given block. For convenience and compatibility reasons, this method is indentical to using recognizerWithHandler:delay: with a delay of 0.0. @return An initialized and autoreleased instance of a concrete UIGestureRecognizer subclass, or `nil`. @param block The block which handles an executed gesture. */ + (id)bk_recognizerWithHandler:(void (^)(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location))block; /** Initializes an allocated gesture recognizer that will call the given block. This method is indentical to calling initWithHandler:delay: with a delay of 0.0. @return An initialized instance of a concrete UIGestureRecognizer subclass or `nil`. @param block The block which handles an executed gesture. */ - (id)bk_initWithHandler:(void (^)(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location))block NS_REPLACES_RECEIVER; /** Allows the block that will be fired by the gesture recognizer to be modified after the fact. */ @property (nonatomic, copy, setter = bk_setHandler:) void (^bk_handler)(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location); /** Allows the length of the delay after which the gesture recognizer will be fired to modify. */ @property (nonatomic, setter = bk_setHandlerDelay:) NSTimeInterval bk_handlerDelay; /** If the recognizer happens to be fired, calling this method will stop it from firing, but only if a delay is set. @warning This method is not for arbitrarily canceling the firing of a recognizer, but will only function for a block handler *after the recognizer has already been fired*. Be sure to make your delay times accomodate this likelihood. */ - (void)bk_cancel; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UIGestureRecognizer+BlocksKit.m ================================================ // // UIGestureRecognizer+BlocksKit.m // BlocksKit // #import #import "UIGestureRecognizer+BlocksKit.h" static const void *BKGestureRecognizerBlockKey = &BKGestureRecognizerBlockKey; static const void *BKGestureRecognizerDelayKey = &BKGestureRecognizerDelayKey; static const void *BKGestureRecognizerShouldHandleActionKey = &BKGestureRecognizerShouldHandleActionKey; @interface UIGestureRecognizer (BlocksKitInternal) @property (nonatomic, setter = bk_setShouldHandleAction:) BOOL bk_shouldHandleAction; - (void)bk_handleAction:(UIGestureRecognizer *)recognizer; @end @implementation UIGestureRecognizer (BlocksKit) + (id)bk_recognizerWithHandler:(void (^)(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location))block delay:(NSTimeInterval)delay { return [[[self class] alloc] bk_initWithHandler:block delay:delay]; } - (id)bk_initWithHandler:(void (^)(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location))block delay:(NSTimeInterval)delay { self = [self initWithTarget:self action:@selector(bk_handleAction:)]; if (!self) return nil; self.bk_handler = block; self.bk_handlerDelay = delay; return self; } + (id)bk_recognizerWithHandler:(void (^)(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location))block { return [self bk_recognizerWithHandler:block delay:0.0]; } - (id)bk_initWithHandler:(void (^)(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location))block { return (self = [self bk_initWithHandler:block delay:0.0]); } - (void)bk_handleAction:(UIGestureRecognizer *)recognizer { void (^handler)(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location) = recognizer.bk_handler; if (!handler) return; NSTimeInterval delay = self.bk_handlerDelay; CGPoint location = [self locationInView:self.view]; void (^block)(void) = ^{ if (!self.bk_shouldHandleAction) return; handler(self, self.state, location); }; self.bk_shouldHandleAction = YES; if (!delay) { block(); return; } dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)); dispatch_after(popTime, dispatch_get_main_queue(), block); } - (void)bk_setHandler:(void (^)(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location))handler { objc_setAssociatedObject(self, BKGestureRecognizerBlockKey, handler, OBJC_ASSOCIATION_COPY_NONATOMIC); } - (void (^)(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location))bk_handler { return objc_getAssociatedObject(self, BKGestureRecognizerBlockKey); } - (void)bk_setHandlerDelay:(NSTimeInterval)delay { NSNumber *delayValue = delay ? @(delay) : nil; objc_setAssociatedObject(self, BKGestureRecognizerDelayKey, delayValue, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (NSTimeInterval)bk_handlerDelay { return [objc_getAssociatedObject(self, BKGestureRecognizerDelayKey) doubleValue]; } - (void)bk_setShouldHandleAction:(BOOL)flag { objc_setAssociatedObject(self, BKGestureRecognizerShouldHandleActionKey, @(flag), OBJC_ASSOCIATION_COPY_NONATOMIC); } - (BOOL)bk_shouldHandleAction { return [objc_getAssociatedObject(self, BKGestureRecognizerShouldHandleActionKey) boolValue]; } - (void)bk_cancel { self.bk_shouldHandleAction = NO; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UIImagePickerController+BlocksKit.h ================================================ // // UIImagePickerController+BlocksKit.h // BlocksKit // // Contributed by Yas Kuraishi. // #import /** UIImagePickerController with block callback. Created by [Yas Kuraishi](https://github.com/YasKuraishi) and contributed to BlocksKit. @warning UIImagePickerController is only available on a platform with UIKit. */ @interface UIImagePickerController (BlocksKit) /** * The block that fires after the receiver finished picking up an image */ @property (nonatomic, copy) void(^bk_didFinishPickingMediaBlock)(UIImagePickerController *, NSDictionary *); /** * The block that fires after the user cancels out of picker */ @property (nonatomic, copy) void(^bk_didCancelBlock)(UIImagePickerController *); @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UIImagePickerController+BlocksKit.m ================================================ // // UIImagePickerController+BlocksKit.m // BlocksKit // #import "A2DynamicDelegate.h" #import "NSObject+A2BlockDelegate.h" #import "UIImagePickerController+BlocksKit.h" #pragma mark Custom delegate @interface A2DynamicUIImagePickerControllerDelegate : A2DynamicDelegate @end @implementation A2DynamicUIImagePickerControllerDelegate - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(imagePickerController:didFinishPickingMediaWithInfo:)]) [realDelegate imagePickerController:picker didFinishPickingMediaWithInfo:info]; void (^block)(UIImagePickerController *, NSDictionary *) = [self blockImplementationForMethod:_cmd]; if (block) block(picker, info); } - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(imagePickerControllerDidCancel:)]) [realDelegate imagePickerControllerDidCancel:picker]; void (^block)(UIImagePickerController *) = [self blockImplementationForMethod:_cmd]; if (block) block(picker); } @end #pragma mark Category @implementation UIImagePickerController (BlocksKit) @dynamic bk_didFinishPickingMediaBlock; @dynamic bk_didCancelBlock; + (void)load { @autoreleasepool { [self bk_registerDynamicDelegate]; [self bk_linkDelegateMethods:@{ @"bk_didFinishPickingMediaBlock": @"imagePickerController:didFinishPickingMediaWithInfo:", @"bk_didCancelBlock": @"imagePickerControllerDidCancel:" }]; } } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UIPopoverController+BlocksKit.h ================================================ // // UIPopoverController+BlocksKit.h // BlocksKit // #import /** Block functionality for UIPopoverController. Created by [Alexsander Akers](https://github.com/a2) and contributed to BlocksKit. @warning UIPopovercontroller is only available on a platform with UIKit. */ @interface UIPopoverController (BlocksKit) /** The block to be called when the popover controller will dismiss the popover. Return NO to prevent the dismissal of the view. */ @property (nonatomic, copy, setter = bk_setShouldDismissBlock:) BOOL (^bk_shouldDismissBlock)(UIPopoverController *popoverController); /** The block to be called when the user has taken action to dismiss the popover. This is not called when -dismissPopoverAnimated: is called directly. */ @property (nonatomic, copy, setter = bk_setDidDismissBlock:) void (^bk_didDismissBlock)(UIPopoverController *popoverController); @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UIPopoverController+BlocksKit.m ================================================ // // UIPopoverController+BlocksKit.m // BlocksKit // #import "A2DynamicDelegate.h" #import "NSObject+A2BlockDelegate.h" #import "UIPopoverController+BlocksKit.h" #pragma mark - Delegate @interface A2DynamicUIPopoverControllerDelegate : A2DynamicDelegate @end @implementation A2DynamicUIPopoverControllerDelegate - (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController { BOOL should = YES; id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(popoverControllerShouldDismissPopover:)]) should &= [realDelegate popoverControllerShouldDismissPopover:popoverController]; BOOL (^block)(UIPopoverController *) = [self blockImplementationForMethod:_cmd]; if (block) should &= block(popoverController); return should; } - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(popoverControllerDidDismissPopover:)]) [realDelegate popoverControllerDidDismissPopover:popoverController]; void (^block)(UIPopoverController *) = [self blockImplementationForMethod:_cmd]; if (block) block(popoverController); } @end #pragma mark - Category @implementation UIPopoverController (BlocksKit) @dynamic bk_didDismissBlock, bk_shouldDismissBlock; + (void)load { @autoreleasepool { [self bk_registerDynamicDelegate]; [self bk_linkDelegateMethods:@{ @"bk_didDismissBlock": @"popoverControllerDidDismissPopover:", @"bk_shouldDismissBlock": @"popoverControllerShouldDismissPopover:" }]; } } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UITextField+BlocksKit.h ================================================ // // UITextField+BlocksKit.h // BlocksKit // // Contributed by Samuel E. Giddins. // #import #import "BlocksKit.h" /** Block callbacks for UITextField. @warning UITextField is only available on a platform with UIKit. Created by [Samuel E. Giddins](https://github.com/segiddins) and contributed to BlocksKit. */ @interface UITextField (BlocksKit) /** * The block that fires before the receiver begins editing * * The return value indicates whether the receiver should begin editing */ @property (nonatomic, copy) BOOL(^bk_shouldBeginEditingBlock)(UITextField *); /** * The block that fires after the receiver begins editing */ @property (nonatomic, copy) void(^bk_didBeginEditingBlock)(UITextField *); /** * The block that fires before the receiver ends editing * * The return value indicates whether the receiver should end editing */ @property (nonatomic, copy) BOOL(^bk_shouldEndEditingBlock)(UITextField *); /** * The block that fires after the receiver ends editing */ @property (nonatomic, copy) void(^bk_didEndEditingBlock)(UITextField *); /** * The block that fires when the receiver's text will change * * The return value indicates whether the receiver should replace the characters in the given range with the replacement string */ @property (nonatomic, copy) BOOL(^bk_shouldChangeCharactersInRangeWithReplacementStringBlock)(UITextField *, NSRange, NSString *); /** * The block that fires when the receiver's clear button is pressed * * The return value indicates whether the receiver should clear its contents */ @property (nonatomic, copy) BOOL(^bk_shouldClearBlock)(UITextField *); /** * The block that fires when the keyboard's return button is pressed and the receiver is the first responder * * The return value indicates whether the receiver should return */ @property (nonatomic, copy) BOOL(^bk_shouldReturnBlock)(UITextField *); @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UITextField+BlocksKit.m ================================================ // // UITextField+BlocksKit.m // BlocksKit // #import "UITextField+BlocksKit.h" #import "A2DynamicDelegate.h" #import "NSObject+A2BlockDelegate.h" #pragma mark Delegate @interface A2DynamicUITextFieldDelegate : A2DynamicDelegate @end @implementation A2DynamicUITextFieldDelegate - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { BOOL ret = YES; id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(textFieldShouldBeginEditing:)]) ret = [realDelegate textFieldShouldBeginEditing:textField]; BOOL (^block)(UITextField *) = [self blockImplementationForMethod:_cmd]; if (block) ret &= block(textField); return ret; } - (void)textFieldDidBeginEditing:(UITextField *)textField { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(textFieldDidBeginEditing:)]) [realDelegate textFieldDidBeginEditing:textField]; void (^block)(UITextField *) = [self blockImplementationForMethod:_cmd]; if (block) block(textField); } - (BOOL)textFieldShouldEndEditing:(UITextField *)textField { BOOL ret = YES; id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(textFieldShouldEndEditing:)]) ret = [realDelegate textFieldShouldEndEditing:textField]; BOOL (^block)(UITextField *) = [self blockImplementationForMethod:_cmd]; if (block) ret &= block(textField); return ret; } - (void)textFieldDidEndEditing:(UITextField *)textField { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(textFieldDidEndEditing:)]) [realDelegate textFieldDidEndEditing:textField]; void (^block)(UITextField *) = [self blockImplementationForMethod:_cmd]; if (block) block(textField); } - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { BOOL ret = YES; id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(textField:shouldChangeCharactersInRange:replacementString:)]) ret = [realDelegate textField:textField shouldChangeCharactersInRange:range replacementString:string]; BOOL (^block)(UITextField *, NSRange, NSString *) = [self blockImplementationForMethod:_cmd]; if (block) ret &= block(textField, range, string); return ret; } - (BOOL)textFieldShouldClear:(UITextField *)textField { BOOL ret = YES; id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(textFieldShouldClear:)]) ret = [realDelegate textFieldShouldClear:textField]; BOOL (^block)(UITextField *) = [self blockImplementationForMethod:_cmd]; if (block) ret &= block(textField); return ret; } - (BOOL)textFieldShouldReturn:(UITextField *)textField { BOOL ret = YES; id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(textFieldShouldReturn:)]) ret = [realDelegate textFieldShouldReturn:textField]; BOOL (^block)(UITextField *) = [self blockImplementationForMethod:_cmd]; if (block) ret &= block(textField); return ret; } @end #pragma mark - Category @implementation UITextField (BlocksKit) @dynamic bk_shouldBeginEditingBlock, bk_didBeginEditingBlock, bk_shouldEndEditingBlock, bk_didEndEditingBlock, bk_shouldChangeCharactersInRangeWithReplacementStringBlock, bk_shouldClearBlock, bk_shouldReturnBlock; + (void)load { [self bk_registerDynamicDelegate]; [self bk_linkDelegateMethods: @{ @"bk_shouldBeginEditingBlock": @"textFieldShouldBeginEditing:", @"bk_didBeginEditingBlock": @"textFieldDidBeginEditing:", @"bk_shouldEndEditingBlock": @"textFieldShouldEndEditing:", @"bk_didEndEditingBlock" : @"textFieldDidEndEditing:", @"bk_shouldChangeCharactersInRangeWithReplacementStringBlock" : @"textField:shouldChangeCharactersInRange:replacementString:", @"bk_shouldClearBlock" : @"textFieldShouldClear:", @"bk_shouldReturnBlock" : @"textFieldShouldReturn:", }]; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UIView+BlocksKit.h ================================================ // // UIView+BlocksKit.h // BlocksKit // #import /** Convenience on-touch methods for UIView. Includes code by the following: - Kevin O'Neill. . 2011. BSD. - Jake Marsh. . 2011. - Zach Waldowski. . 2011. @warning UIView is only available on a platform with UIKit. */ @interface UIView (BlocksKit) /** Abstract creation of a block-backed UITapGestureRecognizer. This method allows for the recognition of any arbitrary number of fingers tapping any number of times on a view. An instance of UITapGesture recognizer is allocated for the block and added to the recieving view. @warning This method has an _additive_ effect. Do not call it multiple times to set-up or tear-down. The view will discard the gesture recognizer on release. @param numberOfTouches The number of fingers tapping that will trigger the block. @param numberOfTaps The number of taps required to trigger the block. @param block The handler for the UITapGestureRecognizer @see whenTapped: @see whenDoubleTapped: */ - (void)bk_whenTouches:(NSUInteger)numberOfTouches tapped:(NSUInteger)numberOfTaps handler:(void (^)(void))block; /** Adds a recognizer for one finger tapping once. @warning This method has an _additive_ effect. Do not call it multiple times to set-up or tear-down. The view will discard the gesture recognizer on release. @param block The handler for the tap recognizer @see whenDoubleTapped: @see whenTouches:tapped:handler: */ - (void)bk_whenTapped:(void (^)(void))block; /** Adds a recognizer for one finger tapping twice. @warning This method has an _additive_ effect. Do not call it multiple times to set-up or tear-down. The view will discard the gesture recognizer on release. @param block The handler for the tap recognizer @see whenTapped: @see whenTouches:tapped:handler: */ - (void)bk_whenDoubleTapped:(void (^)(void))block; /** A convenience wrapper that non-recursively loops through the subviews of a view. @param block A code block that interacts with a UIView sender. */ - (void)bk_eachSubview:(void (^)(UIView *subview))block; @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UIView+BlocksKit.m ================================================ // // UIView+BlocksKit.m // BlocksKit // #import "UIGestureRecognizer+BlocksKit.h" #import "UIView+BlocksKit.h" @implementation UIView (BlocksKit) - (void)bk_whenTouches:(NSUInteger)numberOfTouches tapped:(NSUInteger)numberOfTaps handler:(void (^)(void))block { if (!block) return; UITapGestureRecognizer *gesture = [UITapGestureRecognizer bk_recognizerWithHandler:^(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location) { if (state == UIGestureRecognizerStateRecognized) block(); }]; gesture.numberOfTouchesRequired = numberOfTouches; gesture.numberOfTapsRequired = numberOfTaps; [self.gestureRecognizers enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { if (![obj isKindOfClass:[UITapGestureRecognizer class]]) return; UITapGestureRecognizer *tap = obj; BOOL rightTouches = (tap.numberOfTouchesRequired == numberOfTouches); BOOL rightTaps = (tap.numberOfTapsRequired == numberOfTaps); if (rightTouches && rightTaps) { [gesture requireGestureRecognizerToFail:tap]; } }]; [self addGestureRecognizer:gesture]; } - (void)bk_whenTapped:(void (^)(void))block { [self bk_whenTouches:1 tapped:1 handler:block]; } - (void)bk_whenDoubleTapped:(void (^)(void))block { [self bk_whenTouches:2 tapped:1 handler:block]; } - (void)bk_eachSubview:(void (^)(UIView *subview))block { NSParameterAssert(block != nil); [self.subviews enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop) { block(subview); }]; } @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UIWebView+BlocksKit.h ================================================ // // UIWebView+BlocksKit.h // BlocksKit // #import /** Block callbacks for UIWebView. @warning UIWebView is only available on a platform with UIKit. */ @interface UIWebView (BlocksKit) /** The block to be decide whether a URL will be loaded. @warning If the delegate implements webView:shouldStartLoadWithRequest:navigationType:, the return values of both the delegate method and the block will be considered. */ @property (nonatomic, copy, setter = bk_setShouldStartLoadBlock:) BOOL (^bk_shouldStartLoadBlock)(UIWebView *webView, NSURLRequest *request, UIWebViewNavigationType navigationType); /** The block that is fired when the web view starts loading. */ @property (nonatomic, copy, setter = bk_setDidStartLoadBlock:) void (^bk_didStartLoadBlock)(UIWebView *webView); /** The block that is fired when the web view finishes loading. */ @property (nonatomic, copy, setter = bk_setDidFinishLoadBlock:) void (^bk_didFinishLoadBlock)(UIWebView *webView); /** The block that is fired when the web view stops loading due to an error. */ @property (nonatomic, copy, setter = bk_setDidFinishWithErrorBlock:) void (^bk_didFinishWithErrorBlock)(UIWebView *webView, NSError *error); @end ================================================ FILE: Pods/BlocksKit/BlocksKit/UIKit/UIWebView+BlocksKit.m ================================================ // // UIWebView+BlocksKit.m // BlocksKit // #import "A2DynamicDelegate.h" #import "NSObject+A2BlockDelegate.h" #import "UIWebView+BlocksKit.h" #pragma mark Custom delegate @interface A2DynamicUIWebViewDelegate : A2DynamicDelegate @end @implementation A2DynamicUIWebViewDelegate - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { BOOL ret = YES; id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) ret = [realDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]; BOOL (^block)(UIWebView *, NSURLRequest *, UIWebViewNavigationType) = [self blockImplementationForMethod:_cmd]; if (block) ret &= block(webView, request, navigationType); return ret; } - (void)webViewDidStartLoad:(UIWebView *)webView { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(webViewDidStartLoad:)]) [realDelegate webViewDidStartLoad:webView]; void (^block)(UIWebView *) = [self blockImplementationForMethod:_cmd]; if (block) block(webView); } - (void)webViewDidFinishLoad:(UIWebView *)webView { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(webViewDidFinishLoad:)]) [realDelegate webViewDidFinishLoad:webView]; void (^block)(UIWebView *) = [self blockImplementationForMethod:_cmd]; if (block) block(webView); } - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { id realDelegate = self.realDelegate; if (realDelegate && [realDelegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) [realDelegate webView:webView didFailLoadWithError:error]; void (^block)(UIWebView *, NSError *) = [self blockImplementationForMethod:_cmd]; if (block) block(webView, error); } @end #pragma mark Category @implementation UIWebView (BlocksKit) @dynamic bk_shouldStartLoadBlock, bk_didStartLoadBlock, bk_didFinishLoadBlock, bk_didFinishWithErrorBlock; + (void)load { @autoreleasepool { [self bk_registerDynamicDelegate]; [self bk_linkDelegateMethods:@{ @"bk_shouldStartLoadBlock": @"webView:shouldStartLoadWithRequest:navigationType:", @"bk_didStartLoadBlock": @"webViewDidStartLoad:", @"bk_didFinishLoadBlock": @"webViewDidFinishLoad:", @"bk_didFinishWithErrorBlock": @"webView:didFailLoadWithError:" }]; } } @end ================================================ FILE: Pods/BlocksKit/LICENSE ================================================ // // LICENSE // BlocksKit // Copyright (c) 2011-2014 Zachary Waldowski, Alexsander Akers, and the BlocksKit Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Pods/BlocksKit/README.md ================================================ [BlocksKit](https://zwaldowski.github.io/BlocksKit) =================================================== Blocks in C and Objective-C are downright magical. They make coding easier and potentially quicker, not to mention faster on the front end with multithreading and Grand Central Dispatch. BlocksKit hopes to facilitate this kind of programming by removing some of the annoying - and, in some cases, impeding - limits on coding with blocks. BlocksKit is a framework for OS X Mountain Lion and newer and a static library for iOS 6 and newer. BlocksKit was created by [Zachary Waldowski](https://github.com/zwaldowski) and [Alexsander Akers](https://github.com/a2) and is maintained by Zachary Waldowski. Installation ============ BlocksKit can be added to a project using [CocoaPods](https://github.com/cocoapods/cocoapods). One may also use targets included in the project. ### Library * Download a release of BlocksKit. * Run "Archive" in XCode. * By default the static library will be compiled to `~/Library/Developer/Xcode/DerivedData`. * Move libBlocksKit.a and Headers to your project's folder, preferably a subfolder like "Vendor". * In "Build Phases", Drag libBlocksKit.a into your target's "Link Binary With Libraries" build phase. * In the build settings of your target or project, change "Other Linker Flags" to `-ObjC`. Make sure your app is linked with CoreGraphics, Foundation, MessageUI, and UIKit. * Change (or add) to "Header Search Paths" the relative path to BlocksKit's headers, like `$(SRCROOT)/Vendor/Headers`. * Insert `#import ` in your project's prefix header. ### Framework See the included `Configurations/MacBundleFramework.xcconfig` for more information. Documentation ============= An Xcode-compatible documentation set is available [from CocoaDocs](http://cocoadocs.org/docsets/BlocksKit/). License ======= BlocksKit is maintained under the MIT license. **The project itself is free for use in any and all projects.** You can use BlocksKit in any project, public or private, with or without attribution - though we prefer attribution! It helps us. Unsure about your rights? [Read more.](http://opensource.org/licenses/MIT) Individual credits for included code exist in the header files and documentation. We thank them for their contributions to the open source community. ================================================ FILE: Pods/Local Podspecs/NBSwipePageView.podspec.json ================================================ { "name": "NBSwipePageView", "version": "0.1", "license": "zlib", "summary": "NBSwipePageView is an Objective-C library for easily creating table-based forms on iOS. It is ideal for settings pages or user data entry tasks.", "homepage": "https://github.com/xuzhe/NBSwipePageView.git", "authors": "Nick Lockwood", "source": { "git": "https://github.com/xuzhe/NBSwipePageView.git", "tag": "0.1" }, "source_files": "NBSwipePageView/*.{h,m}", "requires_arc": true, "platforms": { "ios": "5.0" } } ================================================ FILE: Pods/NBSwipePageView/NBSwipePageView/NBSwipePageView.h ================================================ // // NBSwipePageView.h // NBSwipePageView // // Created by 徐 哲 on 4/25/12. // Copyright (c) 2012 ラクラクテクノロジーズ株式会社 XUZHE.COM. All rights reserved. // #import #import "NBSwipePageViewSheet.h" typedef enum { NBSwipePageViewPageAnimationFade, NBSwipePageViewPageAnimationRight, // slide in from right (or out to right) NBSwipePageViewPageAnimationLeft, NBSwipePageViewPageAnimationTop, NBSwipePageViewPageAnimationBottom, NBSwipePageViewPageAnimationNone, // NBSwipePageViewPageAnimationMiddle, // attempts to keep cell centered in the space it will/did occupy NBSwipePageViewPageAnimationAutomatic = 100 // chooses an appropriate animation style for you } NBSwipePageViewPageAnimation; typedef enum { NBSwipePageViewModePageSize = 0, NBSwipePageViewModeFullSize = 1, } NBSwipePageViewMode; @protocol NBSwipePageViewDelegate; @protocol NBSwipePageViewDataSource; @interface NBSwipePageView : UIView @property (unsafe_unretained, nonatomic) IBOutlet id delegate; @property (unsafe_unretained, nonatomic) IBOutlet id dataSource; @property (readonly, nonatomic) NSUInteger currentPageIndex; @property (readonly, nonatomic) BOOL isAnimating; @property (readonly, nonatomic) UIScrollView *scrollView; @property (assign, nonatomic) CGSize scaleScrollView; @property (assign, nonatomic) NBSwipePageViewMode pageViewMode; @property (assign, nonatomic) BOOL allowsSelection; @property (assign, nonatomic) BOOL disableScrollInFullSizeMode; @property (strong, nonatomic) UIView *pageHeaderView; @property (strong, nonatomic) UIView *pageTailView; @property (strong, nonatomic) UIView *backgroundView; @property (strong, nonatomic) UIView *pageTitleView; @property (strong, nonatomic) void (^visibleViewEffectBlock)(id obj, NSUInteger idx, BOOL *stop); @property (readonly, nonatomic) NSArray *visiblePages; // UIScrollViews's property @property (assign, nonatomic) BOOL delaysContentTouches; @property (assign, nonatomic) UIEdgeInsets contentInset; @property (assign, nonatomic) CGPoint contentOffset; @property (assign, nonatomic) CGSize contentSize; @property (assign, nonatomic) BOOL pagingEnabled; @property (assign, nonatomic) BOOL scrollEnabled; @property (readonly, assign, nonatomic) BOOL dragging; @property (readonly, assign, nonatomic) BOOL tracking; @property (readonly, assign, nonatomic) BOOL decelerating; // Reload all pages. Always call this method after Data Source is changed. - (NBSwipePageViewSheet *)dequeueReusableCellWithIdentifier:(NSString *)reuseIdentifier; - (void)reloadData; - (void)scrollToPageAtIndex:(NSUInteger)index animated:(BOOL)animated; - (NBSwipePageViewSheet *)swipePageViewSheetAtIndex:(NSUInteger)index; - (void)setPageViewMode:(NBSwipePageViewMode)pageViewMode animated:(BOOL)animated; - (BOOL)selectPageAtIndex:(NSUInteger)index animated:(BOOL)animated scrollToMiddle:(BOOL)scrollToMiddle; - (BOOL)deselectPageAtIndex:(NSUInteger)index animated:(BOOL)animated; // Pulished methods for fast offset and index convert - (NSUInteger)pageIndexOfCurrentOffset; - (CGPoint)contentOffsetOfIndex:(NSUInteger)index; // TODO: Edit the page view - (void)beginUpdates; - (void)endUpdates; - (void)insertPagesAtIndexes:(NSIndexSet *)indexes withPageAnimation:(NBSwipePageViewPageAnimation)animated; - (void)deletePagesAtIndexes:(NSIndexSet *)indexes withPageAnimation:(NBSwipePageViewPageAnimation)animated; - (void)movePageAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex; @end @protocol NBSwipePageViewDelegate @optional // This delegate will be called after the user stoped the scroll. // The index should always equal to currentPage index. // The animated is YES if the page is scrolled by user or by scrollToPageAtIndex:animated:YES. - (void)swipePageView:(NBSwipePageView *)swipePageView didScrollToPageAtIndex:(NSUInteger)index animated:(BOOL)animated; // This delegate will be called when the user starts to scroll. // The index is depend on the direction of user's swipe. If user is trying to swipe to the left page of the first page // or the right page of the last page, the index will be equal to currentPage index. // The animated is YES if the page is scrolled by user or by scrollToPageAtIndex:animated:YES. - (void)swipePageView:(NBSwipePageView *)swipePageView willScrollToPageAtIndex:(NSUInteger)index animated:(BOOL)animated; // This delegate will be called after the user scrolled back to the page which just started the scroll. - (void)swipePageView:(NBSwipePageView *)swipePageView didCancelScrollFromPageAtIndex:(NSUInteger)index; - (CGFloat)scaleOfSmallViewModeForSwipePageView:(NBSwipePageView *)swipePageView; // default is 60% - (NSUInteger)swipePageView:(NBSwipePageView *)swipePageView willSelectPageAtIndex:(NSUInteger)index; - (void)swipePageView:(NBSwipePageView *)swipePageView didSelectPageAtIndex:(NSUInteger)index; - (NSUInteger)swipePageView:(NBSwipePageView *)swipePageView willDeselectPageAtIndex:(NSUInteger)index; - (void)swipePageView:(NBSwipePageView *)swipePageView didDeselectPageAtIndex:(NSUInteger)index; // TODO: Action Menu Support - (BOOL)swipePageView:(NBSwipePageView *)swipePageView shouldShowMenuForPageAtIndex:(NSUInteger)index; - (BOOL)swipePageView:(NBSwipePageView *)swipePageView canPerformAction:(SEL)action forPageAtIndex:(NSUInteger)index withSender:(id)sender; - (void)swipePageView:(NBSwipePageView *)swipePageView performAction:(SEL)action forPageAtIndex:(NSUInteger)index withSender:(id)sender; // TODO: Editing Page View Support - (void)swipePageView:(NBSwipePageView *)swipePageView willBeginEditingPageAtIndex:(NSUInteger)index; - (void)swipePageView:(NBSwipePageView *)swipePageView didEndEditingPageAtIndex:(NSUInteger)index; - (void)swipePageView:(NBSwipePageView *)swipePageView editingStyleForPageAtIndex:(NSUInteger)index; @end @protocol NBSwipePageViewDataSource @required // You should use this data source to tell me how many pages in the swipe page view. - (NSUInteger)numberOfPagesInSwipePageView:(NBSwipePageView *)swipePageView; // Give me a sheet for the page at index. - (NBSwipePageViewSheet *)swipePageView:(NBSwipePageView *)swipePageView sheetForPageAtIndex:(NSUInteger)index; @optional // TODO: Editing page views - (BOOL)swipePageView:(NBSwipePageView *)swipePageView canEditPageAtIndex:(NSUInteger)index; - (void)swipePageView:(NBSwipePageView *)swipePageView commitEditingStyle:(NBSwipePageViewSheetEditingStyle)editingStyle forPagetAtIndex:(NSUInteger)index; // TODO: Reording page views - (BOOL)swipePageView:(NBSwipePageView *)swipePageView canMovePageAtIndex:(NSUInteger)index; - (void)swipePageView:(NBSwipePageView *)swipePageView movePageAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex; @end ================================================ FILE: Pods/NBSwipePageView/NBSwipePageView/NBSwipePageView.m ================================================ // // NBSwipePageView.m // NBSwipePageView // // Created by 徐 哲 on 4/25/12. // Copyright (c) 2012 ラクラクテクノロジーズ株式会社 XUZHE.COM. All rights reserved. // #import "NBSwipePageView.h" #define kMaxVisiblePageLength 3 @interface NBSwipePageTouchView : UIView @property (unsafe_unretained, nonatomic) UIView *touchHandlerView; @end @implementation NBSwipePageTouchView - (void)initCodes { self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.backgroundColor = [UIColor clearColor]; } - (id)init { self = [super init]; if (self) { [self initCodes]; } return self; } - (id)initWithCoder:(NSCoder *)coder { self = [super initWithCoder:coder]; if (self) { [self initCodes]; } return self; } - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self initCodes]; } return self; } - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { if (_touchHandlerView && [self pointInside:point withEvent:event]) { UIView *test = [_touchHandlerView hitTest:[self convertPoint:point toView:_touchHandlerView] withEvent:event]; return test == nil ? _touchHandlerView : test; } return nil; } @end // ======================= NBSwipePageView ======================= @interface NBSwipePageView (PrivateMethod) @end @implementation NBSwipePageView { NBSwipePageTouchView *_touchView; NBSwipePageViewSheet *_currentPage; NSMutableArray *_visiblePages; NSMutableDictionary *_reusablePages; NSUInteger _cachedNumberOfPages; NSRange _visibleRange; BOOL _isPendingScrolledPageUpdateNotification; CGFloat _cachedScaleRate; NSUInteger _selectedPageIndex; } #pragma mark - Init Codes - (void)initCodes { // init settings _currentPageIndex = NSNotFound; _selectedPageIndex = NSNotFound; _allowsSelection = NO; _disableScrollInFullSizeMode = NO; // defult is do NOT disable scroll in full size mode _isPendingScrolledPageUpdateNotification = NO; _scaleScrollView = CGSizeMake(1.0f, 1.0f); // init views _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; _scrollView.delegate = self; _scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; _scrollView.backgroundColor = [UIColor clearColor]; _scrollView.pagingEnabled = YES; _scrollView.decelerationRate = UIScrollViewDecelerationRateNormal; _scrollView.clipsToBounds = NO; _scrollView.delaysContentTouches = YES; _scrollView.showsVerticalScrollIndicator = NO; _scrollView.showsHorizontalScrollIndicator = NO; _scrollView.alwaysBounceHorizontal = YES; _scrollView.canCancelContentTouches = YES; [self addSubview:_scrollView]; [self setPageViewMode:NBSwipePageViewModePageSize]; // default mode is page size // set tap gesture recognizer for page selection UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureHandler:)]; [_scrollView addGestureRecognizer:tapRecognizer]; tapRecognizer.delegate = self; UILongPressGestureRecognizer *longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureHandler:)]; [_scrollView addGestureRecognizer:longPressRecognizer]; longPressRecognizer.delegate = self; // init caches _cachedNumberOfPages = 0; _visiblePages = [NSMutableArray arrayWithCapacity:4]; _reusablePages = [NSMutableDictionary dictionary]; _visibleRange.location = 0; _visibleRange.length = 0; } - (id)init { self = [super init]; if (self) { [self initCodes]; } return self; } - (id)initWithCoder:(NSCoder *)coder { self = [super initWithCoder:coder]; if (self) { [self initCodes]; } return self; } - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self initCodes]; } return self; } //- (void)dealloc { // NSLog(@"Just for release check."); //} - (void)setFrame:(CGRect)frame { [super setFrame:frame]; [self updateContentSize]; [self relayoutVisiblePages]; } #pragma mark - Delegate Sender - (void)delegateDidScrollToPageAtIndex:(NSUInteger)index animated:(BOOL)animated { if (_delegate && [_delegate respondsToSelector:@selector(swipePageView:didScrollToPageAtIndex:animated:)]) { [_delegate swipePageView:self didScrollToPageAtIndex:index animated:animated]; } } - (void)delegateWillScrollToPageAtIndex:(NSUInteger)index animated:(BOOL)animated { if (_delegate && [_delegate respondsToSelector:@selector(swipePageView:willScrollToPageAtIndex:animated:)]) { [_delegate swipePageView:self willScrollToPageAtIndex:index animated:animated]; } } - (void)delegateDidCancelScrollFromPageAtIndex:(NSUInteger)index { if (_delegate && [_delegate respondsToSelector:@selector(swipePageView:didCancelScrollFromPageAtIndex:)]) { [_delegate swipePageView:self didCancelScrollFromPageAtIndex:index]; } } - (CGFloat)delegateScaleOfSmallViewMode { if (_delegate && [_delegate respondsToSelector:@selector(scaleOfSmallViewModeForSwipePageView:)]) { return [_delegate scaleOfSmallViewModeForSwipePageView:self]; } return 0.6; // default is 60% } - (NSUInteger)delegateWillSelectPageAtIndex:(NSUInteger)index { if (_delegate && [_delegate respondsToSelector:@selector(swipePageView:willSelectPageAtIndex:)]) { return [_delegate swipePageView:self willSelectPageAtIndex:index]; } return index; } - (void)delegateDidSelectPageAtIndex:(NSUInteger)index { if (_delegate && [_delegate respondsToSelector:@selector(swipePageView:didSelectPageAtIndex:)]) { [_delegate swipePageView:self didSelectPageAtIndex:index]; } } - (NSUInteger)delegateWillDeselectPageAtIndex:(NSUInteger)index { if (_delegate && [_delegate respondsToSelector:@selector(swipePageView:willDeselectPageAtIndex:)]) { [_delegate swipePageView:self willDeselectPageAtIndex:index]; } return index; } - (void)delegateDidDeselectPageAtIndex:(NSUInteger)index { if (_delegate && [_delegate respondsToSelector:@selector(swipePageView:didDeselectPageAtIndex:)]) { [_delegate swipePageView:self didDeselectPageAtIndex:index]; } } // TODO: Action Menu Support - (BOOL)delegateShouldShowMenuForPageAtIndex:(NSUInteger)index { if (_delegate && [_delegate respondsToSelector:@selector(swipePageView:shouldShowMenuForPageAtIndex:)]) { return [_delegate swipePageView:self shouldShowMenuForPageAtIndex:index]; } return NO; } - (BOOL)delegateCanPerformAction:(SEL)action forPageAtIndex:(NSUInteger)index withSender:(id)sender { if (_delegate && [_delegate respondsToSelector:@selector(swipePageView:canPerformAction:forPageAtIndex:withSender:)]) { return [_delegate swipePageView:self canPerformAction:action forPageAtIndex:index withSender:sender]; } return NO; } - (void)delegatePerformAction:(SEL)action forPageAtIndex:(NSUInteger)index withSender:(id)sender { if (_delegate && [_delegate respondsToSelector:@selector(swipePageView:performAction:forPageAtIndex:withSender:)]) { [_delegate swipePageView:self performAction:action forPageAtIndex:index withSender:sender]; } } // TODO: Editing Page View Support - (void)delegateWillBeginEditingPageAtIndex:(NSUInteger)index { if (_delegate && [_delegate respondsToSelector:@selector(swipePageView:willBeginEditingPageAtIndex:)]) { [_delegate swipePageView:self willBeginEditingPageAtIndex:index]; } } - (void)delegateDidEndEditingPageAtIndex:(NSUInteger)index { if (_delegate && [_delegate respondsToSelector:@selector(swipePageView:didEndEditingPageAtIndex:)]) { [_delegate swipePageView:self didEndEditingPageAtIndex:index]; } } - (void)delegateEditingStyleForPageAtIndex:(NSUInteger)index { if (_delegate && [_delegate respondsToSelector:@selector(swipePageView:editingStyleForPageAtIndex:)]) { [_delegate swipePageView:self editingStyleForPageAtIndex:index]; } } #pragma mark - Datasource Sender // Required Datasource - (NSUInteger)dataSourceLoadNumberOfPages { NSUInteger pages = [_dataSource numberOfPagesInSwipePageView:self]; if (_cachedNumberOfPages == pages) { return pages; } _cachedNumberOfPages = pages; [self updateContentSize]; return pages; } - (NBSwipePageViewSheet *)dataSourceSheetForPageAtIndex:(NSUInteger)index { NBSwipePageViewSheet *sheet = [_dataSource swipePageView:self sheetForPageAtIndex:index]; NSAssert(sheet != nil, @"The sheet for page at index: %d must not be nil", index); return sheet; } // Option Datasource // TODO: Editing page views - (BOOL)dataSourceCanEditPageAtIndex:(NSUInteger)index { if (_dataSource && [_dataSource respondsToSelector:@selector(swipePageView:canEditPageAtIndex:)]) { return [_dataSource swipePageView:self canEditPageAtIndex:index]; } return NO; } - (void)dataSourceCommitEditingStyle:(NBSwipePageViewSheetEditingStyle)editingStyle forPagetAtIndex:(NSUInteger)index { if (_dataSource && [_dataSource respondsToSelector:@selector(swipePageView:commitEditingStyle:forPagetAtIndex:)]) { [_dataSource swipePageView:self commitEditingStyle:editingStyle forPagetAtIndex:index]; } } // TODO: Reording page views - (BOOL)dataSourceCanMovePageAtIndex:(NSUInteger)index { if (_dataSource && [_dataSource respondsToSelector:@selector(swipePageView:canMovePageAtIndex:)]) { return [_dataSource swipePageView:self canMovePageAtIndex:index]; } return NO; } - (void)dataSourceMovePageAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex { if (_dataSource && [_dataSource respondsToSelector:@selector(swipePageView:movePageAtIndex:toIndex:)]) { [_dataSource swipePageView:self movePageAtIndex:fromIndex toIndex:toIndex]; } } #pragma mark - Private Logic Methods - (void)updateContentSize { _scrollView.contentSize = CGSizeMake((CGFloat)_cachedNumberOfPages * _scrollView.bounds.size.width, _scrollView.bounds.size.height); if (_pageTailView) { CGRect frame = _pageTailView.frame; frame.origin.x = _scrollView.contentSize.width + self.bounds.size.width - CGRectGetMaxX(_scrollView.frame); _pageTailView.frame = frame; } if (_pageHeaderView) { CGRect frame = _pageHeaderView.frame; frame.origin.x = -frame.size.width - CGRectGetMinX(_scrollView.frame); _pageHeaderView.frame = frame; } } - (void)resizeScrollView { CGRect frame = _scrollView.frame; CGFloat width = self.bounds.size.width * _scaleScrollView.width; width += (self.bounds.size.width - width) * 0.25f; frame.size.width = ceilf(width); frame.size.height = ceilf(self.bounds.size.height * _scaleScrollView.height); frame.origin.x = floorf((self.bounds.size.width - frame.size.width) * 0.5); frame.origin.y = floorf((self.bounds.size.height - frame.size.height) * 0.5); _scrollView.frame = frame; [self updateContentSize]; [self relayoutVisiblePages]; } - (void)setFrameForPage:(NBSwipePageViewSheet *)page atIndex:(NSInteger)index { page.transform = CGAffineTransformMakeScale(_cachedScaleRate, _cachedScaleRate); CGFloat contentOffset = (CGFloat)index * _scrollView.frame.size.width; CGFloat margin = floorf((_scrollView.frame.size.width - page.frame.size.width) * 0.5f); CGRect frame = page.frame; frame.origin.x = floorf(contentOffset + margin); page.frame = frame; page.margin = margin; } - (void)relayoutVisiblePages { for (NSUInteger i = 0; i < [_visiblePages count]; i++) { NBSwipePageViewSheet *sheet = _visiblePages[i]; NSUInteger index = _visibleRange.location + i; if (index >= _cachedNumberOfPages) { continue; } [self setFrameForPage:sheet atIndex:index]; } } - (void)shiftPage:(UIView*)page withOffset:(CGFloat)offset { CGRect frame = page.frame; frame.origin.x += offset; page.frame = frame; } - (NBSwipePageViewSheet *)loadPageAtIndex:(NSInteger)index insertIntoVisibleIndex:(NSInteger)visibleIndex { NBSwipePageViewSheet *visiblePage = [self dataSourceSheetForPageAtIndex:index]; // add the page to the visible pages array [_visiblePages insertObject:visiblePage atIndex:visibleIndex]; return visiblePage; } - (CGPoint)contentOffsetOfIndex:(NSUInteger)index { return CGPointMake(_scrollView.bounds.size.width * (CGFloat)index, 0.0f); } - (NSUInteger)pageIndexOfCurrentOffset { CGFloat pageWidth = _scrollView.bounds.size.width; return floor((_scrollView.contentOffset.x - pageWidth * 0.5f) / pageWidth) + 1.0f; } - (void)preparePage:(NBSwipePageViewSheet *)page forMode:(NBSwipePageViewMode)mode { // When a page is presented in NBSwipePageViewMode mode, it is scaled up and is moved to a different superview. // As it captures the full screen, it may be cropped to fit inside its new superview's frame. // So when moving it back to NBSwipePageViewMode, we restore the page's proportions to prepare it to Deck mode. if (mode == NBSwipePageViewModePageSize && CGAffineTransformEqualToTransform(page.transform, CGAffineTransformIdentity)) { // TODO: // page.frame = page.identityFrame; } } // add a page to the scroll view at a given index. No adjustments are made to existing pages offsets. - (void)addPageToScrollView:(NBSwipePageViewSheet *)page atIndex:(NSInteger)index { // inserting a page into the scroll view is in HGPageScrollViewModeDeck by definition (the scroll is the "deck") [self preparePage:page forMode:NBSwipePageViewModePageSize]; // configure the page frame [self setFrameForPage:page atIndex:index]; // add the page to the scroller [_scrollView insertSubview:page atIndex:0]; } - (void)addToReusablePages:(NBSwipePageViewSheet *)page { NSMutableSet *set = _reusablePages[page.reuseIdentifier]; if (set) { // if already have one reusable page, do not add another one. if ([set count] == 0) { [set addObject:page]; } } else { set = [NSMutableSet setWithObject:page]; _reusablePages[page.reuseIdentifier] = set; } } // Update Visible Pages - (void)updateVisiblePages:(BOOL)force { NSRange lastVisibleRange = _visibleRange; [self updateVisibleRange:[self pageIndexOfCurrentOffset]]; if (NSEqualRanges(lastVisibleRange, _visibleRange) && !force) { return; } BOOL initVisiblePages = ([_visiblePages count] == 0); if (!initVisiblePages) { NSUInteger maxRange = NSMaxRange(lastVisibleRange); for (NSUInteger i = maxRange - 1; i < maxRange && i >= lastVisibleRange.location; i--) { if (!NSLocationInRange(i, _visibleRange)) { NSUInteger ii = i - lastVisibleRange.location; NBSwipePageViewSheet *page = _visiblePages[ii]; [page removeFromSuperview]; [self addToReusablePages:page]; [_visiblePages removeObjectAtIndex:ii]; } } } for (NSUInteger i = _visibleRange.location; i < NSMaxRange(_visibleRange); i++) { if (initVisiblePages || !NSLocationInRange(i, lastVisibleRange)) { NBSwipePageViewSheet *page = [self loadPageAtIndex:i insertIntoVisibleIndex:i - _visibleRange.location]; // add the page to the scroll view (to make it actually visible) [self addPageToScrollView:page atIndex:i]; } } } - (void)updateScrolledPageIndex:(NSUInteger)index animated:(BOOL)animated { NBSwipePageViewSheet *page = [self swipePageViewSheetAtIndex:index]; if (page) { // notify delegate [self delegateWillScrollToPageAtIndex:index animated:animated]; // TODO: // set the page selector (page control) _currentPageIndex = index; // set selected page _currentPage = page; // NSLog(@"selectedPage: 0x%x (index %d)", page, index ); if (_scrollView.dragging || _scrollView.decelerating) { _isPendingScrolledPageUpdateNotification = YES; } else { _isPendingScrolledPageUpdateNotification = NO; [self delegateDidScrollToPageAtIndex:_currentPageIndex animated:animated]; } } } - (NSUInteger)indexForVisiblePage:(NBSwipePageViewSheet *)page { NSUInteger index = [_visiblePages indexOfObject:page]; if (index != NSNotFound) { return _visibleRange.location + index; } return NSNotFound; } #pragma mark - Set Views - (void)setBackgroundView:(UIView *)backgroundView { if ([backgroundView isEqual:_backgroundView]) { return; } if (_backgroundView) { [_backgroundView removeFromSuperview]; } _backgroundView = backgroundView; if (backgroundView) { backgroundView.frame = self.bounds; backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; // should always autoresize background view [self insertSubview:backgroundView atIndex:0]; } } - (void)setPageHeaderView:(UIView *)pageHeaderView { if ([pageHeaderView isEqual:_pageHeaderView]) { return; } if (_pageHeaderView) { [_pageHeaderView removeFromSuperview]; } _pageHeaderView = pageHeaderView; if (pageHeaderView) { [_scrollView addSubview:pageHeaderView]; } } - (void)setPageTailView:(UIView *)pageTailView { if ([pageTailView isEqual:_pageTailView]) { return; } if (_pageTailView) { [_pageTailView removeFromSuperview]; } _pageTailView = pageTailView; if (pageTailView) { [_scrollView addSubview:pageTailView]; } } - (void)setPageTitleView:(UIView *)pageTitleView { if ([pageTitleView isEqual:_pageTitleView]) { return; } if (_pageTitleView) { [_pageTitleView removeFromSuperview]; } _pageTitleView = pageTitleView; if (pageTitleView) { [self addSubview:pageTitleView]; } } #pragma mark - Set Propertys - (void)setPageViewMode:(NBSwipePageViewMode)pageViewMode { [self setPageViewMode:pageViewMode animated:NO]; } #pragma mark - Public Methods - (NBSwipePageViewSheet *)dequeueReusableCellWithIdentifier:(NSString *)reuseIdentifier { NSMutableSet *reusableSet = _reusablePages[reuseIdentifier]; NBSwipePageViewSheet *reusableSheet = [reusableSet anyObject]; if (reusableSheet) { [reusableSheet prepareForReuse]; [reusableSet removeObject:reusableSheet]; return reusableSheet; } return nil; } - (void)updateVisibleRange:(NSUInteger)currentIndex { if (currentIndex >= NSNotFound || currentIndex == 0) { _currentPageIndex = 0; _visibleRange.location = 0; _visibleRange.length = MIN(kMaxVisiblePageLength - 1, _cachedNumberOfPages); } else if (currentIndex >= _cachedNumberOfPages) { _currentPageIndex = _cachedNumberOfPages - 1; _visibleRange.location = MIN(_currentPageIndex - 1, _cachedNumberOfPages - 1); _visibleRange.length = MIN(kMaxVisiblePageLength - 1, _cachedNumberOfPages); } else { _visibleRange.location = currentIndex - 1; _visibleRange.length = MIN(MIN(kMaxVisiblePageLength, _cachedNumberOfPages), _cachedNumberOfPages - _visibleRange.location); } } - (void)setScaleScrollView:(CGSize)scaleScrollView { if (!CGSizeEqualToSize(scaleScrollView, _scaleScrollView)) { _scaleScrollView = scaleScrollView; [self resizeScrollView]; } } - (void)reloadData { [_reusablePages removeAllObjects]; [_visiblePages removeAllObjects]; [[_scrollView subviews] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { *stop = NO; if ([obj isEqual:_pageTailView] || [obj isEqual:_pageHeaderView]) { return ; } [obj removeFromSuperview]; }]; if (_pageViewMode == NBSwipePageViewModePageSize) { _cachedScaleRate = [self delegateScaleOfSmallViewMode]; } else { _cachedScaleRate = 1.0f; } [self resizeScrollView]; [self dataSourceLoadNumberOfPages]; _selectedPageIndex = NSNotFound; if (_cachedNumberOfPages == 0 || _cachedNumberOfPages >= NSNotFound) { _currentPage = nil; _currentPageIndex = NSNotFound; return; } // this will load any additional views which become visible [self updateVisiblePages:YES]; _currentPage = [self swipePageViewSheetAtIndex:_currentPageIndex]; // reloading the data implicitely resets the viewMode to UIPageScrollViewModeDeck. // here we restore the view mode in case this is not the first time reloadData is called (i.e. if there if a _selectedPage). // if (_selectedPage && _viewMode==HGPageScrollViewModePage) { // _viewMode = HGPageScrollViewModeDeck; // [self setViewMode:HGPageScrollViewModePage animated:NO]; // } if (_pageViewMode == NBSwipePageViewModePageSize && _visibleViewEffectBlock) { [_visiblePages enumerateObjectsUsingBlock:_visibleViewEffectBlock]; } } - (void)scrollToPageAtIndex:(NSUInteger)index animated:(BOOL)animated { _isAnimating = animated; [_scrollView setContentOffset:[self contentOffsetOfIndex:index] animated:animated]; if (!animated) { // do not call this method when animated, // because it will be called in UIScrollViewDelegate. [self updateScrolledPageIndex:index animated:animated]; } } - (NBSwipePageViewSheet *)swipePageViewSheetAtIndex:(NSUInteger)index { if (index >= _cachedNumberOfPages) { // Out of bounds return nil; } if (NSLocationInRange(index, _visibleRange)) { return _visiblePages[index - _visibleRange.location]; } return [self dataSourceSheetForPageAtIndex:index]; } - (void)setPageViewMode:(NBSwipePageViewMode)pageViewMode animated:(BOOL)animated { _pageViewMode = pageViewMode; if (pageViewMode == NBSwipePageViewModeFullSize) { if (_touchView) { [_touchView removeFromSuperview]; _touchView = nil; } } else { if (!_touchView) { _touchView = [[NBSwipePageTouchView alloc] initWithFrame:self.bounds]; _touchView.touchHandlerView = _scrollView; _touchView.autoresizingMask = _scrollView.autoresizingMask; [self addSubview:_touchView]; } } // TODO: add animated support } - (BOOL)selectPageAtIndex:(NSUInteger)index animated:(BOOL)animated scrollToMiddle:(BOOL)scrollToMiddle { if (![self deselectPageAtIndex:_selectedPageIndex animated:animated]) { return NO; } NSUInteger shouldSelectIndex = [self delegateWillSelectPageAtIndex:index]; if (shouldSelectIndex >= NSNotFound) { return NO; } else if (shouldSelectIndex != _currentPageIndex && scrollToMiddle) { [self delegateDidSelectPageAtIndex:shouldSelectIndex]; // should be called before currentIndex changed by scrollToPageAtIndex: [self scrollToPageAtIndex:shouldSelectIndex animated:animated]; } else { [self delegateDidSelectPageAtIndex:shouldSelectIndex]; } _selectedPageIndex = shouldSelectIndex; return YES; } - (BOOL)deselectPageAtIndex:(NSUInteger)index animated:(BOOL)animated { if (index >= NSNotFound) { return YES; } NSUInteger shouldDeselectIndex = [self delegateWillDeselectPageAtIndex:_selectedPageIndex]; if (shouldDeselectIndex >= NSNotFound) { return NO; } [self delegateDidDeselectPageAtIndex:_selectedPageIndex]; _selectedPageIndex = NSNotFound; return YES; } // TODO: Edit the page view - (void)beginUpdates { } - (void)endUpdates { } - (void)insertPagesAtIndexes:(NSIndexSet *)indexes withPageAnimation:(NBSwipePageViewPageAnimation)animated { } - (void)deletePagesAtIndexes:(NSIndexSet *)indexes withPageAnimation:(NBSwipePageViewPageAnimation)animated { } - (void)movePageAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex { } #pragma mark - UIScrollViewDelegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView { [self updateVisiblePages:NO]; if (_pageViewMode == NBSwipePageViewModePageSize && _visibleViewEffectBlock) { [_visiblePages enumerateObjectsUsingBlock:_visibleViewEffectBlock]; } if (_delegate && [_delegate respondsToSelector:@selector(scrollViewDidScroll:)]) { [_delegate scrollViewDidScroll:scrollView]; } } - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { _isAnimating = NO; [self updateScrolledPageIndex:[self pageIndexOfCurrentOffset] animated:YES]; if (_delegate && [_delegate respondsToSelector:@selector(scrollViewDidEndScrollingAnimation:)]) { [_delegate scrollViewDidEndScrollingAnimation:scrollView]; } } - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { if (!decelerate) { [self updateScrolledPageIndex:[self pageIndexOfCurrentOffset] animated:NO]; if (_isPendingScrolledPageUpdateNotification) { _isPendingScrolledPageUpdateNotification = NO; [self delegateDidScrollToPageAtIndex:_currentPageIndex animated:NO]; } } if (_delegate && [_delegate respondsToSelector:@selector(scrollViewDidEndDragging:willDecelerate:)]) { [_delegate scrollViewDidEndDragging:scrollView willDecelerate:decelerate]; } } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { [self updateScrolledPageIndex:[self pageIndexOfCurrentOffset] animated:YES]; if (_isPendingScrolledPageUpdateNotification) { _isPendingScrolledPageUpdateNotification = NO; [self delegateDidScrollToPageAtIndex:_currentPageIndex animated:YES]; } if (_delegate && [_delegate respondsToSelector:@selector(scrollViewDidEndDecelerating:)]) { [_delegate scrollViewDidEndDecelerating:scrollView]; } } - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView { if (_delegate && [_delegate respondsToSelector:@selector(scrollViewWillBeginDecelerating:)]) { [_delegate scrollViewWillBeginDecelerating:scrollView]; } } - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { if (_delegate && [_delegate respondsToSelector:@selector(scrollViewWillBeginDragging:)]) { [_delegate scrollViewWillBeginDragging:scrollView]; } } - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { if (_delegate && [_delegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) { [_delegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset]; } } #pragma make - Get or Set some propeties of UIScrollView - (CGPoint)contentOffset { return _scrollView.contentOffset; } - (CGSize)contentSize { return _scrollView.contentSize; } - (BOOL)dragging { return _scrollView.dragging; } - (BOOL)tracking { return _scrollView.tracking; } - (BOOL)decelerating { return _scrollView.decelerating; } - (UIEdgeInsets)contentInset { return _scrollView.contentInset; } - (BOOL)pagingEnabled { return _scrollView.pagingEnabled; } - (BOOL)scrollEnabled { return _scrollView.scrollEnabled; } - (BOOL)delaysContentTouches { return _scrollView.delaysContentTouches; } - (void)setContentInset:(UIEdgeInsets)contentInset { _scrollView.contentInset = contentInset; } - (void)setContentOffset:(CGPoint)contentOffset { _scrollView.contentOffset = contentOffset; } - (void)setContentSize:(CGSize)contentSize { _scrollView.contentSize = contentSize; } - (void)setPagingEnabled:(BOOL)pagingEnabled { _scrollView.pagingEnabled = pagingEnabled; } - (void)setScrollEnabled:(BOOL)scrollEnabled { _scrollView.scrollEnabled = scrollEnabled; } - (void)setDelaysContentTouches:(BOOL)delaysContentTouches { _scrollView.delaysContentTouches = delaysContentTouches; } - (NSArray *)visiblePages { return [NSArray arrayWithArray:_visiblePages]; } #pragma mark - #pragma mark Handling Touches - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { if (_pageViewMode == NBSwipePageViewModePageSize && !_scrollView.decelerating && !_scrollView.dragging && !_isAnimating) { return YES; } return NO; } - (void)tapGestureHandler:(UITapGestureRecognizer *)recognizer { if (_currentPageIndex >= NSNotFound) { return; } if (recognizer.state == UIGestureRecognizerStateBegan) { [self deselectPageAtIndex:_selectedPageIndex animated:YES]; } else if (recognizer.state == UIGestureRecognizerStateRecognized) { for (NBSwipePageViewSheet *page in _visiblePages) { if ([page pointInside:[recognizer locationInView:page] withEvent:nil]) { [self selectPageAtIndex:[self indexForVisiblePage:page] animated:YES scrollToMiddle:YES]; return; } } } } @end ================================================ FILE: Pods/NBSwipePageView/NBSwipePageView/NBSwipePageViewSheet.h ================================================ // // NBSwipePageSheetView.h // NBSwipePageView // // Created by 徐 哲 on 4/25/12. // Copyright (c) 2012 ラクラクテクノロジーズ株式会社 XUZHE.COM. All rights reserved. // #import typedef enum { NBSwipePageViewSheetEditingStyleNone, NBSwipePageViewSheetEditingStyleDelete, NBSwipePageViewSheetEditingStyleInsert } NBSwipePageViewSheetEditingStyle; @interface NBSwipePageViewSheet : UIView @property (readonly, strong, nonatomic) UIView *contentView; @property (readonly, strong, nonatomic) NSString *reuseIdentifier; @property (strong, nonatomic) UIView *backgroundView; @property (assign, nonatomic) CGFloat margin; - (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier; - (void)prepareForReuse; @end ================================================ FILE: Pods/NBSwipePageView/NBSwipePageView/NBSwipePageViewSheet.m ================================================ // // NBSwipePageSheetView.m // NBSwipePageView // // Created by 徐 哲 on 4/25/12. // Copyright (c) 2012 ラクラクテクノロジーズ株式会社 XUZHE.COM. All rights reserved. // #import "NBSwipePageViewSheet.h" @implementation NBSwipePageViewSheet @synthesize contentView = _contentView; @synthesize reuseIdentifier = _reuseIdentifier; @synthesize backgroundView = _backgroundView; @synthesize margin = _margin; - (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithFrame:frame]; if (self) { self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; _reuseIdentifier = reuseIdentifier; _contentView = [[UIView alloc] initWithFrame:self.bounds]; _contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; _contentView.backgroundColor = [UIColor clearColor]; // set default color to clear color [self addSubview:_contentView]; } return self; } - (void)setBackgroundView:(UIView *)backgroundView { if (_backgroundView) { [_backgroundView removeFromSuperview]; } _backgroundView = backgroundView; if (_backgroundView) { [self insertSubview:_backgroundView atIndex:0]; } } /* // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code } */ - (void)prepareForReuse { _margin = 0.0f; self.transform = CGAffineTransformIdentity; } @end ================================================ FILE: Pods/NBSwipePageView/README.md ================================================ # About NBSwipePageView This is the same page view using in [iWeekly](http://itunes.apple.com/cn/app/iweekly-zhou-mo-hua-bao/id453405026) for the photo gallery view. There are a lot of _TODOs_ in the project, since it's not finished yet. Although the basic functions are OK to use, things like re-order, add or delete pages with animation, etc still need more work. Before I have time to finishe the project, I am not going to give any example to show how to use the project. But as you can see, the project is very similar to UITableView, so if you do understand how to use UITableView, I don't think it's going to be too hard in using the project. =============== ================================================ FILE: Pods/Pods.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 01149FA585A714569093657B85C1A350 /* NSSet+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 77DE1165EA844BC34C8346F58A8F0A5A /* NSSet+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 03592DBD830EF65C1AE796A0697F46E1 /* NSMutableSet+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = B6823A4FF3E238DF1137CACBF4C46821 /* NSMutableSet+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0692E35064349B6FA8C1EFD50B7B1F45 /* A2DynamicDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = BBAFE8B59E5658A456D1604C4787586A /* A2DynamicDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0A288C4D0ED296320F86966D45E8D5E9 /* A2DynamicDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D8BBC3B21EF93C94C0503F37C7C203B /* A2DynamicDelegate.m */; }; 0B1447334EF3FCD08E783F72251FC1EB /* NBSwipePageViewSheet.m in Sources */ = {isa = PBXBuildFile; fileRef = D68729D6462BB5D59BABD3601B0FDAB1 /* NBSwipePageViewSheet.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; 0F0550B889810895B32BCA065DD6CFC4 /* NSObject+BKAssociatedObjects.h in Headers */ = {isa = PBXBuildFile; fileRef = 46EFDC605BDEB95E1A9B82AEF274BD22 /* NSObject+BKAssociatedObjects.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0F4EF1312B94E272652DA22CCDF8E52D /* NBSwipePageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 5668070ABC17B99F0C429987153668DD /* NBSwipePageView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 12F7B27FB2422AC6413E77B7F98812C4 /* UIWebView+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 41D6CCC50142DC73264F3B2564675B4D /* UIWebView+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 149B9A4BDC7FB1FEDE01059764F1D584 /* NSMutableIndexSet+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 614B88C7540695BA460B2D36A1B05409 /* NSMutableIndexSet+BlocksKit.m */; }; 14BAF7AE2D75E18559739D71CFF10C84 /* NSMutableOrderedSet+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C5B6808ACA80A0065D2603DE05E203C /* NSMutableOrderedSet+BlocksKit.m */; }; 1BE7CD118C7601DDD1629547E938ED5E /* NSMutableArray+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 43F3926287AD7C1C9985FAB1B0D59DB8 /* NSMutableArray+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1FACCDACF70A7AF5AAED0F35D9AC0642 /* BKMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC4BA1E19DC4B493F408D635ABBF62B /* BKMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; 213BDA0BFDC7FA8B00CD8395940400E2 /* NSOrderedSet+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = C5D6B3E5DEC02F3C9DE27DD8628A08DC /* NSOrderedSet+BlocksKit.m */; }; 28A0BEDF1DB5E178DEAF1D03F718557B /* NSArray+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = EEFAAEE862815EC5E9B4F1DCBA6F17FE /* NSArray+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2CE50403797DDF662DAE1DBDEF30A901 /* UIGestureRecognizer+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 740B1526DF32677371C7A2DF105FAE4C /* UIGestureRecognizer+BlocksKit.m */; }; 3221D2FE805E7A2E298CB3B9CC4E6AF0 /* A2BlockInvocation.m in Sources */ = {isa = PBXBuildFile; fileRef = DB66189290187545EEDE2D7F1AE90FB7 /* A2BlockInvocation.m */; }; 33C43B6C020C6A9CC4EE5C22650C550E /* MFMessageComposeViewController+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 634D4C0636DCCAFFBD36469460668E7E /* MFMessageComposeViewController+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 37A05672C67666332CF82130E9A461C2 /* MFMailComposeViewController+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C50D73F1B981F3B038DF62C2F60A37C /* MFMailComposeViewController+BlocksKit.m */; }; 3CF5DE3EC202C9678B0120CB3CC93FE3 /* NSIndexSet+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 9FA4B445912F0749A52EE63D4E05B6D8 /* NSIndexSet+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3DF2307D736F5A334CC5392A06B142C0 /* NSMutableIndexSet+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 1252D073D9C58FC751C660D1703BEB3E /* NSMutableIndexSet+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 423CD981F80732AA6C075F7F633CFBBD /* NSURLConnection+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CBCCDF78C46DB5F52421D85CFB809EF /* NSURLConnection+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 455F71D95890455473B3AF068D2003D1 /* UIPopoverController+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E033364536F067BF46B9EC6E167D278 /* UIPopoverController+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 484776F8B4CF9A89AA18C6874E246DF6 /* NSObject+A2BlockDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F00475220127F6FF8443D9DB465FC35 /* NSObject+A2BlockDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5467BA80FE76E5928DBC92FCA8F319DD /* UIAlertView+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 33D000060EBEA0877D9D3D4D8C13A946 /* UIAlertView+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 58F4C1C349633CE28F242E5FC8518636 /* NSTimer+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = E7722EACAD43F5A9B234A80B32CB11C8 /* NSTimer+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 61898DE2259DB9ECC1F23C538FCE7BBB /* UIImagePickerController+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = FC58DFFAE0793B2B3045B4732E2CD03E /* UIImagePickerController+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6A242E93B8569A42628B0F8B369273CA /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22506F41FE03B0B7B4ECC1B0E4929BE1 /* MessageUI.framework */; }; 6DCBF5A3569BA772FBAB3379A00464D2 /* UIBarButtonItem+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AEB0CB1AE9B06F4C7C8CC1B15C6B7B1 /* UIBarButtonItem+BlocksKit.m */; }; 6F2746610AB8BBFA162997F6AED950F7 /* NSTimer+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DDB454F9D30684567C7FF47639F70CB /* NSTimer+BlocksKit.m */; }; 6F6DD1FA269EB37E6CC9722C59AFBA5B /* NSArray+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 10DF349A029A74E7E70830C83EEFF691 /* NSArray+BlocksKit.m */; }; 6FE51449ABAA54EF33F44CE810BAD905 /* UITextField+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 7988F167AF2CB0EF3EDDE88B91F9FD6A /* UITextField+BlocksKit.m */; }; 73B9779AEDACEB09223A4474DCE9F330 /* NBSwipePageView-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 34A1A8EBB6B2BE8DD6FEEF00D06054E4 /* NBSwipePageView-dummy.m */; }; 77515111C9AFE11AB1287761150614F5 /* UITextField+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 881990B0A7EDA7C9A0FFFA8211B4F700 /* UITextField+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 79588DF8F673302C22F3C81278A0B98E /* NSObject+A2BlockDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C50D0F868E786D1E086980E0BC9F1AC /* NSObject+A2BlockDelegate.m */; }; 7D2D914EEDBCFF0F225F680F75D5694E /* NSObject+BKAssociatedObjects.m in Sources */ = {isa = PBXBuildFile; fileRef = C01BD2B1CC9309D65230900534DF7C40 /* NSObject+BKAssociatedObjects.m */; }; 7E8DF508233A1A7A663933939A6D5FE8 /* MFMessageComposeViewController+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 11F45121D62B3EEBDB4A186317A573F5 /* MFMessageComposeViewController+BlocksKit.m */; }; 80D7B80A26162132A65EE9167AEAE94F /* UIControl+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 695220B18921774E4B9C4485DFE2ECEB /* UIControl+BlocksKit.m */; }; 8517BE33C254EE906D831579DD8C72B3 /* A2BlockInvocation.h in Headers */ = {isa = PBXBuildFile; fileRef = E2B042EB2E64EB498398AA91AA1EC6B7 /* A2BlockInvocation.h */; settings = {ATTRIBUTES = (Public, ); }; }; 992944F68F8CC38008B2C611A0107FDE /* UIView+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 6333B315B5444FC7ADE1236E2FD2BACF /* UIView+BlocksKit.m */; }; 9C639C4D43608486642208566DF05AF5 /* NSObject+BKBlockObservation.m in Sources */ = {isa = PBXBuildFile; fileRef = BE2997B16159B7B5802CEB7CCA4F21BA /* NSObject+BKBlockObservation.m */; }; 9F9CFBD464085524F455C4D19211E69E /* NSMutableDictionary+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = C10BF9320F1F503BFC80200239C3D561 /* NSMutableDictionary+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9FADA4523CE1BFD6E588D400285BAC0E /* NSURLConnection+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 199655B8F3ACCD00C27AECE62B405726 /* NSURLConnection+BlocksKit.m */; }; A026405E495CA2EFF557A70D1515A689 /* NSOrderedSet+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 785F482D4C83DF5936253BF9509A20E9 /* NSOrderedSet+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; A02CE14E5350ABACF361F7EB4696AA42 /* NBSwipePageViewSheet.h in Headers */ = {isa = PBXBuildFile; fileRef = 32142D64333FD6C119110D9B0E9EB867 /* NBSwipePageViewSheet.h */; settings = {ATTRIBUTES = (Public, ); }; }; A1968C04873813D7CEB076FDFCBC479C /* UIControl+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 9FB5DA3DA29B7F25193DE7E4F59EB59F /* UIControl+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; A229FCF9FEBBF16977B33AB2FEF23830 /* UIBarButtonItem+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 364BD1494421E8B900DB4DA2A40A600F /* UIBarButtonItem+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; A2FC6CF3F13C4799D04AC89ADD403AED /* NSMutableSet+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = A77A230DD6AF310C41E9C858AAE6F935 /* NSMutableSet+BlocksKit.m */; }; A5CA4DD465154E16BF094796B56E7E52 /* NSMutableDictionary+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 309914CD0767C7A8A1C8506412C735E0 /* NSMutableDictionary+BlocksKit.m */; }; A5DBFF76EDEC1BCDA0351DCE8407ACA9 /* NSDictionary+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 85724216A6B67A7836F8691210733738 /* NSDictionary+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; B0B0BE27896A5E10D51303AB299BA5FF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04E16E7749E7745FBA9CD27032FD363F /* Foundation.framework */; }; B25F8085B440D68735024862A5F6AD9F /* UIGestureRecognizer+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 484C959134D86C5B50B0B97A88AAE812 /* UIGestureRecognizer+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; B6947A884743188A3E6C81EA172D4DCE /* NSInvocation+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 311AC030AF157B5858A0858B3867F546 /* NSInvocation+BlocksKit.m */; }; B74B90AB5E2F98B82040E5B791B1E513 /* NSMutableArray+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D85C27D9CC6618BD9D712896EE1FE19 /* NSMutableArray+BlocksKit.m */; }; BE2BE12ECE566C14238DD7845DEDD84B /* BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 4893F44277A4C37383B3D17C95B83FCD /* BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; C237814AF824CAE9A479AD0F4DB151AA /* NSCache+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 637FD4034E4411441D61D4D6183AE090 /* NSCache+BlocksKit.m */; }; C2874BD5AC24AB6CF628418E5C251A22 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04E16E7749E7745FBA9CD27032FD363F /* Foundation.framework */; }; C2BFF405BE0AEE5C66C90E6FD8B10415 /* BlocksKit+UIKit.h in Headers */ = {isa = PBXBuildFile; fileRef = B528444B31C485419EDB3ED4A45C4C0E /* BlocksKit+UIKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; C7C6F46E66572803459747BD9121EB20 /* UIActionSheet+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = F0E6B57E0BE3118912DF7A17CEAFBC55 /* UIActionSheet+BlocksKit.m */; }; C7E0B31A7916AABF23A79CB06E1F5272 /* NSObject+BKBlockObservation.h in Headers */ = {isa = PBXBuildFile; fileRef = 97A6FD59B94F19837F47228762F60765 /* NSObject+BKBlockObservation.h */; settings = {ATTRIBUTES = (Public, ); }; }; C9B6328F023FF633ABA6879D50FC90DE /* NSInvocation+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A58BA0A4C3DFDB1C8868C9C470884B0 /* NSInvocation+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; CB21742066F67241062931F6F568D071 /* UIImagePickerController+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = BA03FA5E90293A8A242661B033CE510B /* UIImagePickerController+BlocksKit.m */; }; CC7E36A547AEE6456442AF7F5C60E2F9 /* NSMutableOrderedSet+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = C789E1C7C1C97EC081F026883D17433D /* NSMutableOrderedSet+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; D53F7D2E487057DC8EDA59A6DD54FF7A /* NSSet+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CAD913AE197086CEEE294B9F5502653 /* NSSet+BlocksKit.m */; }; D6017E171F626B176414E066B800C1AF /* NSObject+BKBlockExecution.m in Sources */ = {isa = PBXBuildFile; fileRef = 33BC212BC63A8F33CB9874D61425C2A6 /* NSObject+BKBlockExecution.m */; }; D7AFF4F4AA1900F1FDD8CCC28367CD1C /* BlocksKit+MessageUI.h in Headers */ = {isa = PBXBuildFile; fileRef = 21F951F391EDAD89F86B953947D86B2F /* BlocksKit+MessageUI.h */; settings = {ATTRIBUTES = (Public, ); }; }; D9D88ED515332296D0EE0C7129EDAAA0 /* NSCache+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = C9E4F4971BCDCF11039D997201D02D1D /* NSCache+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; DB21A546C83305719CD699E00E36AA3F /* BlocksKit-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 13383F03F54652A8599B82F086D0331C /* BlocksKit-dummy.m */; }; DD97B6AC8570C045E8327C7E8118E0A4 /* NBSwipePageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5821F4D4451349CFC8D88517CA3DF30C /* NBSwipePageView.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; E09FAE444FA9AAC6F1F0295F5092A2FC /* UIWebView+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 79ADF0B4DB0DE9BCBB8A4498A6DDA10D /* UIWebView+BlocksKit.m */; }; E0C060F23AA82483327B74CCD9B72676 /* Pods-testPasterImage-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = DAB4C3670351DE9A3F9CFABDB83B1EA8 /* Pods-testPasterImage-dummy.m */; }; E32DDF26286A2F7F77F8B90754373696 /* UIActionSheet+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 0440BC37D29AEF8B3F714A656300E905 /* UIActionSheet+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; EC783E9B9EA9DDFC778E4AA0D5065097 /* NSObject+A2DynamicDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 143CCC414A02F0DD2FCC137AF1BC9187 /* NSObject+A2DynamicDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; EE57724381B2462C7604C9DB685E5A0F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04E16E7749E7745FBA9CD27032FD363F /* Foundation.framework */; }; EF87B1AB7825C0B9244F364CEAC1EF31 /* MFMailComposeViewController+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = B46E021A91570EABA92EE2A75C32BE12 /* MFMailComposeViewController+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; F09A8E1234A6B7D95122D5DAEA3870FF /* NSObject+A2DynamicDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 937C6B15BB3B289271417E4A31D2CC56 /* NSObject+A2DynamicDelegate.m */; }; F222764F0ED41EF907EE5D439DA182A1 /* UIAlertView+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 9910D6958916F2D04CC043A0E4984AFD /* UIAlertView+BlocksKit.m */; }; F3040EE21525146A4AABD68CFF758D23 /* NSDictionary+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = B22BB841E22A6C72E1D7FBF093387257 /* NSDictionary+BlocksKit.m */; }; F5C8F609901D5C71DC95528248D1D0F3 /* UIPopoverController+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 407D6DC4ACE2CC84080DB3E3C8CA73A5 /* UIPopoverController+BlocksKit.m */; }; F60CAF477B4F4573C02F675C42DFFD2D /* UIView+BlocksKit.h in Headers */ = {isa = PBXBuildFile; fileRef = F3E890DE7A3601C854CC8D25DDAED06D /* UIView+BlocksKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; F6516207095BAB4A00C52187CFAD097B /* NSObject+BKBlockExecution.h in Headers */ = {isa = PBXBuildFile; fileRef = B510783B568A6D55FCAAFE7A8BBB35EC /* NSObject+BKBlockExecution.h */; settings = {ATTRIBUTES = (Public, ); }; }; F67325523D6DDBF4AF0C19A02ED3FDBD /* NSIndexSet+BlocksKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EF4CE8CFA59BBEAF766F3A03296E09C /* NSIndexSet+BlocksKit.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 371ED08071AFFDADE018659914EF5E2E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; remoteGlobalIDString = DA1A7295DF2A99609DA0EEBF5E83233D; remoteInfo = BlocksKit; }; CA315BBEDAB8A2B4955C90AD54907F2F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; remoteGlobalIDString = 9C6466D79F40B07C4D15FDE68159545C; remoteInfo = NBSwipePageView; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 012283CDA7885A24CB83F6722C2C21AB /* Pods-testPasterImage-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-testPasterImage-acknowledgements.plist"; sourceTree = ""; }; 0440BC37D29AEF8B3F714A656300E905 /* UIActionSheet+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIActionSheet+BlocksKit.h"; path = "BlocksKit/UIKit/UIActionSheet+BlocksKit.h"; sourceTree = ""; }; 04E16E7749E7745FBA9CD27032FD363F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 0F00475220127F6FF8443D9DB465FC35 /* NSObject+A2BlockDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+A2BlockDelegate.h"; path = "BlocksKit/DynamicDelegate/NSObject+A2BlockDelegate.h"; sourceTree = ""; }; 0FC4BA1E19DC4B493F408D635ABBF62B /* BKMacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = BKMacros.h; path = BlocksKit/Core/BKMacros.h; sourceTree = ""; }; 10DF349A029A74E7E70830C83EEFF691 /* NSArray+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSArray+BlocksKit.m"; path = "BlocksKit/Core/NSArray+BlocksKit.m"; sourceTree = ""; }; 1169513FD91CD57AB8AC5BB9E020DDB3 /* NBSwipePageView.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = NBSwipePageView.xcconfig; sourceTree = ""; }; 11F45121D62B3EEBDB4A186317A573F5 /* MFMessageComposeViewController+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "MFMessageComposeViewController+BlocksKit.m"; path = "BlocksKit/MessageUI/MFMessageComposeViewController+BlocksKit.m"; sourceTree = ""; }; 1252D073D9C58FC751C660D1703BEB3E /* NSMutableIndexSet+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSMutableIndexSet+BlocksKit.h"; path = "BlocksKit/Core/NSMutableIndexSet+BlocksKit.h"; sourceTree = ""; }; 13383F03F54652A8599B82F086D0331C /* BlocksKit-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "BlocksKit-dummy.m"; sourceTree = ""; }; 143CCC414A02F0DD2FCC137AF1BC9187 /* NSObject+A2DynamicDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+A2DynamicDelegate.h"; path = "BlocksKit/DynamicDelegate/NSObject+A2DynamicDelegate.h"; sourceTree = ""; }; 199655B8F3ACCD00C27AECE62B405726 /* NSURLConnection+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSURLConnection+BlocksKit.m"; path = "BlocksKit/DynamicDelegate/Foundation/NSURLConnection+BlocksKit.m"; sourceTree = ""; }; 21F951F391EDAD89F86B953947D86B2F /* BlocksKit+MessageUI.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "BlocksKit+MessageUI.h"; path = "BlocksKit/BlocksKit+MessageUI.h"; sourceTree = ""; }; 22506F41FE03B0B7B4ECC1B0E4929BE1 /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/System/Library/Frameworks/MessageUI.framework; sourceTree = DEVELOPER_DIR; }; 29C868A366BA357EA2ECCFFE176E0BBF /* Pods-testPasterImage.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-testPasterImage.release.xcconfig"; sourceTree = ""; }; 2AEB0CB1AE9B06F4C7C8CC1B15C6B7B1 /* UIBarButtonItem+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIBarButtonItem+BlocksKit.m"; path = "BlocksKit/UIKit/UIBarButtonItem+BlocksKit.m"; sourceTree = ""; }; 2C50D0F868E786D1E086980E0BC9F1AC /* NSObject+A2BlockDelegate.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+A2BlockDelegate.m"; path = "BlocksKit/DynamicDelegate/NSObject+A2BlockDelegate.m"; sourceTree = ""; }; 2DDB454F9D30684567C7FF47639F70CB /* NSTimer+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSTimer+BlocksKit.m"; path = "BlocksKit/Core/NSTimer+BlocksKit.m"; sourceTree = ""; }; 2EF4CE8CFA59BBEAF766F3A03296E09C /* NSIndexSet+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSIndexSet+BlocksKit.m"; path = "BlocksKit/Core/NSIndexSet+BlocksKit.m"; sourceTree = ""; }; 309914CD0767C7A8A1C8506412C735E0 /* NSMutableDictionary+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSMutableDictionary+BlocksKit.m"; path = "BlocksKit/Core/NSMutableDictionary+BlocksKit.m"; sourceTree = ""; }; 311AC030AF157B5858A0858B3867F546 /* NSInvocation+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSInvocation+BlocksKit.m"; path = "BlocksKit/Core/NSInvocation+BlocksKit.m"; sourceTree = ""; }; 32142D64333FD6C119110D9B0E9EB867 /* NBSwipePageViewSheet.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = NBSwipePageViewSheet.h; path = NBSwipePageView/NBSwipePageViewSheet.h; sourceTree = ""; }; 33BC212BC63A8F33CB9874D61425C2A6 /* NSObject+BKBlockExecution.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+BKBlockExecution.m"; path = "BlocksKit/Core/NSObject+BKBlockExecution.m"; sourceTree = ""; }; 33D000060EBEA0877D9D3D4D8C13A946 /* UIAlertView+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIAlertView+BlocksKit.h"; path = "BlocksKit/UIKit/UIAlertView+BlocksKit.h"; sourceTree = ""; }; 34A1A8EBB6B2BE8DD6FEEF00D06054E4 /* NBSwipePageView-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "NBSwipePageView-dummy.m"; sourceTree = ""; }; 364BD1494421E8B900DB4DA2A40A600F /* UIBarButtonItem+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIBarButtonItem+BlocksKit.h"; path = "BlocksKit/UIKit/UIBarButtonItem+BlocksKit.h"; sourceTree = ""; }; 3A58BA0A4C3DFDB1C8868C9C470884B0 /* NSInvocation+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSInvocation+BlocksKit.h"; path = "BlocksKit/Core/NSInvocation+BlocksKit.h"; sourceTree = ""; }; 3C50D73F1B981F3B038DF62C2F60A37C /* MFMailComposeViewController+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "MFMailComposeViewController+BlocksKit.m"; path = "BlocksKit/MessageUI/MFMailComposeViewController+BlocksKit.m"; sourceTree = ""; }; 407D6DC4ACE2CC84080DB3E3C8CA73A5 /* UIPopoverController+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIPopoverController+BlocksKit.m"; path = "BlocksKit/UIKit/UIPopoverController+BlocksKit.m"; sourceTree = ""; }; 41D6CCC50142DC73264F3B2564675B4D /* UIWebView+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIWebView+BlocksKit.h"; path = "BlocksKit/UIKit/UIWebView+BlocksKit.h"; sourceTree = ""; }; 43F3926287AD7C1C9985FAB1B0D59DB8 /* NSMutableArray+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSMutableArray+BlocksKit.h"; path = "BlocksKit/Core/NSMutableArray+BlocksKit.h"; sourceTree = ""; }; 46EFDC605BDEB95E1A9B82AEF274BD22 /* NSObject+BKAssociatedObjects.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+BKAssociatedObjects.h"; path = "BlocksKit/Core/NSObject+BKAssociatedObjects.h"; sourceTree = ""; }; 484C959134D86C5B50B0B97A88AAE812 /* UIGestureRecognizer+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIGestureRecognizer+BlocksKit.h"; path = "BlocksKit/UIKit/UIGestureRecognizer+BlocksKit.h"; sourceTree = ""; }; 4893F44277A4C37383B3D17C95B83FCD /* BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = BlocksKit.h; path = BlocksKit/BlocksKit.h; sourceTree = ""; }; 5668070ABC17B99F0C429987153668DD /* NBSwipePageView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = NBSwipePageView.h; path = NBSwipePageView/NBSwipePageView.h; sourceTree = ""; }; 5821F4D4451349CFC8D88517CA3DF30C /* NBSwipePageView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = NBSwipePageView.m; path = NBSwipePageView/NBSwipePageView.m; sourceTree = ""; }; 5C5B6808ACA80A0065D2603DE05E203C /* NSMutableOrderedSet+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSMutableOrderedSet+BlocksKit.m"; path = "BlocksKit/Core/NSMutableOrderedSet+BlocksKit.m"; sourceTree = ""; }; 5D85C27D9CC6618BD9D712896EE1FE19 /* NSMutableArray+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSMutableArray+BlocksKit.m"; path = "BlocksKit/Core/NSMutableArray+BlocksKit.m"; sourceTree = ""; }; 5D8BBC3B21EF93C94C0503F37C7C203B /* A2DynamicDelegate.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = A2DynamicDelegate.m; path = BlocksKit/DynamicDelegate/A2DynamicDelegate.m; sourceTree = ""; }; 5E033364536F067BF46B9EC6E167D278 /* UIPopoverController+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIPopoverController+BlocksKit.h"; path = "BlocksKit/UIKit/UIPopoverController+BlocksKit.h"; sourceTree = ""; }; 614B88C7540695BA460B2D36A1B05409 /* NSMutableIndexSet+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSMutableIndexSet+BlocksKit.m"; path = "BlocksKit/Core/NSMutableIndexSet+BlocksKit.m"; sourceTree = ""; }; 6333B315B5444FC7ADE1236E2FD2BACF /* UIView+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+BlocksKit.m"; path = "BlocksKit/UIKit/UIView+BlocksKit.m"; sourceTree = ""; }; 634D4C0636DCCAFFBD36469460668E7E /* MFMessageComposeViewController+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MFMessageComposeViewController+BlocksKit.h"; path = "BlocksKit/MessageUI/MFMessageComposeViewController+BlocksKit.h"; sourceTree = ""; }; 637FD4034E4411441D61D4D6183AE090 /* NSCache+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSCache+BlocksKit.m"; path = "BlocksKit/DynamicDelegate/Foundation/NSCache+BlocksKit.m"; sourceTree = ""; }; 695220B18921774E4B9C4485DFE2ECEB /* UIControl+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIControl+BlocksKit.m"; path = "BlocksKit/UIKit/UIControl+BlocksKit.m"; sourceTree = ""; }; 6CBCCDF78C46DB5F52421D85CFB809EF /* NSURLConnection+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSURLConnection+BlocksKit.h"; path = "BlocksKit/DynamicDelegate/Foundation/NSURLConnection+BlocksKit.h"; sourceTree = ""; }; 740B1526DF32677371C7A2DF105FAE4C /* UIGestureRecognizer+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIGestureRecognizer+BlocksKit.m"; path = "BlocksKit/UIKit/UIGestureRecognizer+BlocksKit.m"; sourceTree = ""; }; 745574CB3EE981C509D1E2696FFE092F /* libNBSwipePageView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libNBSwipePageView.a; sourceTree = BUILT_PRODUCTS_DIR; }; 77DE1165EA844BC34C8346F58A8F0A5A /* NSSet+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSSet+BlocksKit.h"; path = "BlocksKit/Core/NSSet+BlocksKit.h"; sourceTree = ""; }; 785F482D4C83DF5936253BF9509A20E9 /* NSOrderedSet+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSOrderedSet+BlocksKit.h"; path = "BlocksKit/Core/NSOrderedSet+BlocksKit.h"; sourceTree = ""; }; 7988F167AF2CB0EF3EDDE88B91F9FD6A /* UITextField+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UITextField+BlocksKit.m"; path = "BlocksKit/UIKit/UITextField+BlocksKit.m"; sourceTree = ""; }; 79ADF0B4DB0DE9BCBB8A4498A6DDA10D /* UIWebView+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIWebView+BlocksKit.m"; path = "BlocksKit/UIKit/UIWebView+BlocksKit.m"; sourceTree = ""; }; 85724216A6B67A7836F8691210733738 /* NSDictionary+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+BlocksKit.h"; path = "BlocksKit/Core/NSDictionary+BlocksKit.h"; sourceTree = ""; }; 881990B0A7EDA7C9A0FFFA8211B4F700 /* UITextField+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UITextField+BlocksKit.h"; path = "BlocksKit/UIKit/UITextField+BlocksKit.h"; sourceTree = ""; }; 8CAD913AE197086CEEE294B9F5502653 /* NSSet+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSSet+BlocksKit.m"; path = "BlocksKit/Core/NSSet+BlocksKit.m"; sourceTree = ""; }; 937C6B15BB3B289271417E4A31D2CC56 /* NSObject+A2DynamicDelegate.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+A2DynamicDelegate.m"; path = "BlocksKit/DynamicDelegate/NSObject+A2DynamicDelegate.m"; sourceTree = ""; }; 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 940DBD94A05688547906B48F4FBF5CAF /* Pods-testPasterImage-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-testPasterImage-resources.sh"; sourceTree = ""; }; 97A6FD59B94F19837F47228762F60765 /* NSObject+BKBlockObservation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+BKBlockObservation.h"; path = "BlocksKit/Core/NSObject+BKBlockObservation.h"; sourceTree = ""; }; 9910D6958916F2D04CC043A0E4984AFD /* UIAlertView+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIAlertView+BlocksKit.m"; path = "BlocksKit/UIKit/UIAlertView+BlocksKit.m"; sourceTree = ""; }; 9FA4B445912F0749A52EE63D4E05B6D8 /* NSIndexSet+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSIndexSet+BlocksKit.h"; path = "BlocksKit/Core/NSIndexSet+BlocksKit.h"; sourceTree = ""; }; 9FB5DA3DA29B7F25193DE7E4F59EB59F /* UIControl+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIControl+BlocksKit.h"; path = "BlocksKit/UIKit/UIControl+BlocksKit.h"; sourceTree = ""; }; A08A8DB765006DD2C2B3B2C680FCF822 /* BlocksKit.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = BlocksKit.xcconfig; sourceTree = ""; }; A20A06929A4BC668B1088FBFA4C78044 /* BlocksKit-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "BlocksKit-prefix.pch"; sourceTree = ""; }; A77A230DD6AF310C41E9C858AAE6F935 /* NSMutableSet+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSMutableSet+BlocksKit.m"; path = "BlocksKit/Core/NSMutableSet+BlocksKit.m"; sourceTree = ""; }; A855DC09868C0AF098946E945FF59AE8 /* libBlocksKit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libBlocksKit.a; sourceTree = BUILT_PRODUCTS_DIR; }; B22BB841E22A6C72E1D7FBF093387257 /* NSDictionary+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+BlocksKit.m"; path = "BlocksKit/Core/NSDictionary+BlocksKit.m"; sourceTree = ""; }; B46E021A91570EABA92EE2A75C32BE12 /* MFMailComposeViewController+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MFMailComposeViewController+BlocksKit.h"; path = "BlocksKit/MessageUI/MFMailComposeViewController+BlocksKit.h"; sourceTree = ""; }; B510783B568A6D55FCAAFE7A8BBB35EC /* NSObject+BKBlockExecution.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+BKBlockExecution.h"; path = "BlocksKit/Core/NSObject+BKBlockExecution.h"; sourceTree = ""; }; B528444B31C485419EDB3ED4A45C4C0E /* BlocksKit+UIKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "BlocksKit+UIKit.h"; path = "BlocksKit/BlocksKit+UIKit.h"; sourceTree = ""; }; B6823A4FF3E238DF1137CACBF4C46821 /* NSMutableSet+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSMutableSet+BlocksKit.h"; path = "BlocksKit/Core/NSMutableSet+BlocksKit.h"; sourceTree = ""; }; BA03FA5E90293A8A242661B033CE510B /* UIImagePickerController+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImagePickerController+BlocksKit.m"; path = "BlocksKit/UIKit/UIImagePickerController+BlocksKit.m"; sourceTree = ""; }; BBAFE8B59E5658A456D1604C4787586A /* A2DynamicDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = A2DynamicDelegate.h; path = BlocksKit/DynamicDelegate/A2DynamicDelegate.h; sourceTree = ""; }; BE2997B16159B7B5802CEB7CCA4F21BA /* NSObject+BKBlockObservation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+BKBlockObservation.m"; path = "BlocksKit/Core/NSObject+BKBlockObservation.m"; sourceTree = ""; }; C01BD2B1CC9309D65230900534DF7C40 /* NSObject+BKAssociatedObjects.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+BKAssociatedObjects.m"; path = "BlocksKit/Core/NSObject+BKAssociatedObjects.m"; sourceTree = ""; }; C10BF9320F1F503BFC80200239C3D561 /* NSMutableDictionary+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSMutableDictionary+BlocksKit.h"; path = "BlocksKit/Core/NSMutableDictionary+BlocksKit.h"; sourceTree = ""; }; C4AF27C25935F8F90BBC88CD0DAA19C3 /* Pods-testPasterImage-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-testPasterImage-acknowledgements.markdown"; sourceTree = ""; }; C5D6B3E5DEC02F3C9DE27DD8628A08DC /* NSOrderedSet+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSOrderedSet+BlocksKit.m"; path = "BlocksKit/Core/NSOrderedSet+BlocksKit.m"; sourceTree = ""; }; C71C3F131A855C7CD9143B43D775A182 /* Pods-testPasterImage.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-testPasterImage.debug.xcconfig"; sourceTree = ""; }; C789E1C7C1C97EC081F026883D17433D /* NSMutableOrderedSet+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSMutableOrderedSet+BlocksKit.h"; path = "BlocksKit/Core/NSMutableOrderedSet+BlocksKit.h"; sourceTree = ""; }; C9E4F4971BCDCF11039D997201D02D1D /* NSCache+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSCache+BlocksKit.h"; path = "BlocksKit/DynamicDelegate/Foundation/NSCache+BlocksKit.h"; sourceTree = ""; }; D574531AE45C3322A21EEB8628986242 /* Pods-testPasterImage-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-testPasterImage-frameworks.sh"; sourceTree = ""; }; D68729D6462BB5D59BABD3601B0FDAB1 /* NBSwipePageViewSheet.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = NBSwipePageViewSheet.m; path = NBSwipePageView/NBSwipePageViewSheet.m; sourceTree = ""; }; DAB4C3670351DE9A3F9CFABDB83B1EA8 /* Pods-testPasterImage-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-testPasterImage-dummy.m"; sourceTree = ""; }; DB66189290187545EEDE2D7F1AE90FB7 /* A2BlockInvocation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = A2BlockInvocation.m; path = BlocksKit/DynamicDelegate/A2BlockInvocation.m; sourceTree = ""; }; E2B042EB2E64EB498398AA91AA1EC6B7 /* A2BlockInvocation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = A2BlockInvocation.h; path = BlocksKit/DynamicDelegate/A2BlockInvocation.h; sourceTree = ""; }; E4F9ABD6A796F565BA3FE9C92C648F98 /* NBSwipePageView-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "NBSwipePageView-prefix.pch"; sourceTree = ""; }; E7722EACAD43F5A9B234A80B32CB11C8 /* NSTimer+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSTimer+BlocksKit.h"; path = "BlocksKit/Core/NSTimer+BlocksKit.h"; sourceTree = ""; }; E7F011EB4C9F94875BC0C31D693729FE /* libPods-testPasterImage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-testPasterImage.a"; sourceTree = BUILT_PRODUCTS_DIR; }; EEFAAEE862815EC5E9B4F1DCBA6F17FE /* NSArray+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+BlocksKit.h"; path = "BlocksKit/Core/NSArray+BlocksKit.h"; sourceTree = ""; }; F0E6B57E0BE3118912DF7A17CEAFBC55 /* UIActionSheet+BlocksKit.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIActionSheet+BlocksKit.m"; path = "BlocksKit/UIKit/UIActionSheet+BlocksKit.m"; sourceTree = ""; }; F3E890DE7A3601C854CC8D25DDAED06D /* UIView+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+BlocksKit.h"; path = "BlocksKit/UIKit/UIView+BlocksKit.h"; sourceTree = ""; }; FC58DFFAE0793B2B3045B4732E2CD03E /* UIImagePickerController+BlocksKit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImagePickerController+BlocksKit.h"; path = "BlocksKit/UIKit/UIImagePickerController+BlocksKit.h"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 87D63FC8B5A5501852974C5E1F3328A6 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( C2874BD5AC24AB6CF628418E5C251A22 /* Foundation.framework in Frameworks */, 6A242E93B8569A42628B0F8B369273CA /* MessageUI.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 8B550906D4EEAFEF38AACE8AD606D2D9 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( B0B0BE27896A5E10D51303AB299BA5FF /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; F4195BEBE6C06638A02A058FF98AB60E /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( EE57724381B2462C7604C9DB685E5A0F /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 093D43DE6B698080B8BB8193E7BF0D35 /* BlocksKit */ = { isa = PBXGroup; children = ( A61995544C61F7AE8945ACCFAD4CC9B0 /* Core */, 4A56F381179B4028D52F5C10EACF9B04 /* DynamicDelegate */, CC333F97E94301B7BED7C872F3A6BB41 /* MessageUI */, EA235F8A517EEBF391EF796EECC81405 /* Support Files */, 5CC37690864A96B8082CF9D4A626D531 /* UIKit */, ); path = BlocksKit; sourceTree = ""; }; 0AF8CF74B0922138036D97199BCF293D /* iOS */ = { isa = PBXGroup; children = ( 04E16E7749E7745FBA9CD27032FD363F /* Foundation.framework */, 22506F41FE03B0B7B4ECC1B0E4929BE1 /* MessageUI.framework */, ); name = iOS; sourceTree = ""; }; 1129A49CEBFD30BE6B62FA28D7F4059E /* NBSwipePageView */ = { isa = PBXGroup; children = ( 5668070ABC17B99F0C429987153668DD /* NBSwipePageView.h */, 5821F4D4451349CFC8D88517CA3DF30C /* NBSwipePageView.m */, 32142D64333FD6C119110D9B0E9EB867 /* NBSwipePageViewSheet.h */, D68729D6462BB5D59BABD3601B0FDAB1 /* NBSwipePageViewSheet.m */, E4270B0AD4C62C0E70D034DF108FC1BB /* Support Files */, ); path = NBSwipePageView; sourceTree = ""; }; 433CD3331B6C3787F473C941B61FC68F /* Frameworks */ = { isa = PBXGroup; children = ( 0AF8CF74B0922138036D97199BCF293D /* iOS */, ); name = Frameworks; sourceTree = ""; }; 4A56F381179B4028D52F5C10EACF9B04 /* DynamicDelegate */ = { isa = PBXGroup; children = ( E2B042EB2E64EB498398AA91AA1EC6B7 /* A2BlockInvocation.h */, DB66189290187545EEDE2D7F1AE90FB7 /* A2BlockInvocation.m */, BBAFE8B59E5658A456D1604C4787586A /* A2DynamicDelegate.h */, 5D8BBC3B21EF93C94C0503F37C7C203B /* A2DynamicDelegate.m */, C9E4F4971BCDCF11039D997201D02D1D /* NSCache+BlocksKit.h */, 637FD4034E4411441D61D4D6183AE090 /* NSCache+BlocksKit.m */, 0F00475220127F6FF8443D9DB465FC35 /* NSObject+A2BlockDelegate.h */, 2C50D0F868E786D1E086980E0BC9F1AC /* NSObject+A2BlockDelegate.m */, 143CCC414A02F0DD2FCC137AF1BC9187 /* NSObject+A2DynamicDelegate.h */, 937C6B15BB3B289271417E4A31D2CC56 /* NSObject+A2DynamicDelegate.m */, 6CBCCDF78C46DB5F52421D85CFB809EF /* NSURLConnection+BlocksKit.h */, 199655B8F3ACCD00C27AECE62B405726 /* NSURLConnection+BlocksKit.m */, ); name = DynamicDelegate; sourceTree = ""; }; 5BCA2EACE5018207A51B743600AE4CC9 /* Pods */ = { isa = PBXGroup; children = ( 093D43DE6B698080B8BB8193E7BF0D35 /* BlocksKit */, 1129A49CEBFD30BE6B62FA28D7F4059E /* NBSwipePageView */, ); name = Pods; sourceTree = ""; }; 5CC37690864A96B8082CF9D4A626D531 /* UIKit */ = { isa = PBXGroup; children = ( B528444B31C485419EDB3ED4A45C4C0E /* BlocksKit+UIKit.h */, 0440BC37D29AEF8B3F714A656300E905 /* UIActionSheet+BlocksKit.h */, F0E6B57E0BE3118912DF7A17CEAFBC55 /* UIActionSheet+BlocksKit.m */, 33D000060EBEA0877D9D3D4D8C13A946 /* UIAlertView+BlocksKit.h */, 9910D6958916F2D04CC043A0E4984AFD /* UIAlertView+BlocksKit.m */, 364BD1494421E8B900DB4DA2A40A600F /* UIBarButtonItem+BlocksKit.h */, 2AEB0CB1AE9B06F4C7C8CC1B15C6B7B1 /* UIBarButtonItem+BlocksKit.m */, 9FB5DA3DA29B7F25193DE7E4F59EB59F /* UIControl+BlocksKit.h */, 695220B18921774E4B9C4485DFE2ECEB /* UIControl+BlocksKit.m */, 484C959134D86C5B50B0B97A88AAE812 /* UIGestureRecognizer+BlocksKit.h */, 740B1526DF32677371C7A2DF105FAE4C /* UIGestureRecognizer+BlocksKit.m */, FC58DFFAE0793B2B3045B4732E2CD03E /* UIImagePickerController+BlocksKit.h */, BA03FA5E90293A8A242661B033CE510B /* UIImagePickerController+BlocksKit.m */, 5E033364536F067BF46B9EC6E167D278 /* UIPopoverController+BlocksKit.h */, 407D6DC4ACE2CC84080DB3E3C8CA73A5 /* UIPopoverController+BlocksKit.m */, 881990B0A7EDA7C9A0FFFA8211B4F700 /* UITextField+BlocksKit.h */, 7988F167AF2CB0EF3EDDE88B91F9FD6A /* UITextField+BlocksKit.m */, F3E890DE7A3601C854CC8D25DDAED06D /* UIView+BlocksKit.h */, 6333B315B5444FC7ADE1236E2FD2BACF /* UIView+BlocksKit.m */, 41D6CCC50142DC73264F3B2564675B4D /* UIWebView+BlocksKit.h */, 79ADF0B4DB0DE9BCBB8A4498A6DDA10D /* UIWebView+BlocksKit.m */, ); name = UIKit; sourceTree = ""; }; 776E2A08A21AF1309108AF65E833B8E1 /* Pods-testPasterImage */ = { isa = PBXGroup; children = ( C4AF27C25935F8F90BBC88CD0DAA19C3 /* Pods-testPasterImage-acknowledgements.markdown */, 012283CDA7885A24CB83F6722C2C21AB /* Pods-testPasterImage-acknowledgements.plist */, DAB4C3670351DE9A3F9CFABDB83B1EA8 /* Pods-testPasterImage-dummy.m */, D574531AE45C3322A21EEB8628986242 /* Pods-testPasterImage-frameworks.sh */, 940DBD94A05688547906B48F4FBF5CAF /* Pods-testPasterImage-resources.sh */, C71C3F131A855C7CD9143B43D775A182 /* Pods-testPasterImage.debug.xcconfig */, 29C868A366BA357EA2ECCFFE176E0BBF /* Pods-testPasterImage.release.xcconfig */, ); name = "Pods-testPasterImage"; path = "Target Support Files/Pods-testPasterImage"; sourceTree = ""; }; 7DB346D0F39D3F0E887471402A8071AB = { isa = PBXGroup; children = ( 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, 433CD3331B6C3787F473C941B61FC68F /* Frameworks */, 5BCA2EACE5018207A51B743600AE4CC9 /* Pods */, 9A5CCE0B8EE1965591F137FAB3A255A2 /* Products */, FD79ADB775FA1C18313058307DBD5B48 /* Targets Support Files */, ); sourceTree = ""; }; 9A5CCE0B8EE1965591F137FAB3A255A2 /* Products */ = { isa = PBXGroup; children = ( A855DC09868C0AF098946E945FF59AE8 /* libBlocksKit.a */, 745574CB3EE981C509D1E2696FFE092F /* libNBSwipePageView.a */, E7F011EB4C9F94875BC0C31D693729FE /* libPods-testPasterImage.a */, ); name = Products; sourceTree = ""; }; A61995544C61F7AE8945ACCFAD4CC9B0 /* Core */ = { isa = PBXGroup; children = ( 0FC4BA1E19DC4B493F408D635ABBF62B /* BKMacros.h */, 4893F44277A4C37383B3D17C95B83FCD /* BlocksKit.h */, EEFAAEE862815EC5E9B4F1DCBA6F17FE /* NSArray+BlocksKit.h */, 10DF349A029A74E7E70830C83EEFF691 /* NSArray+BlocksKit.m */, 85724216A6B67A7836F8691210733738 /* NSDictionary+BlocksKit.h */, B22BB841E22A6C72E1D7FBF093387257 /* NSDictionary+BlocksKit.m */, 9FA4B445912F0749A52EE63D4E05B6D8 /* NSIndexSet+BlocksKit.h */, 2EF4CE8CFA59BBEAF766F3A03296E09C /* NSIndexSet+BlocksKit.m */, 3A58BA0A4C3DFDB1C8868C9C470884B0 /* NSInvocation+BlocksKit.h */, 311AC030AF157B5858A0858B3867F546 /* NSInvocation+BlocksKit.m */, 43F3926287AD7C1C9985FAB1B0D59DB8 /* NSMutableArray+BlocksKit.h */, 5D85C27D9CC6618BD9D712896EE1FE19 /* NSMutableArray+BlocksKit.m */, C10BF9320F1F503BFC80200239C3D561 /* NSMutableDictionary+BlocksKit.h */, 309914CD0767C7A8A1C8506412C735E0 /* NSMutableDictionary+BlocksKit.m */, 1252D073D9C58FC751C660D1703BEB3E /* NSMutableIndexSet+BlocksKit.h */, 614B88C7540695BA460B2D36A1B05409 /* NSMutableIndexSet+BlocksKit.m */, C789E1C7C1C97EC081F026883D17433D /* NSMutableOrderedSet+BlocksKit.h */, 5C5B6808ACA80A0065D2603DE05E203C /* NSMutableOrderedSet+BlocksKit.m */, B6823A4FF3E238DF1137CACBF4C46821 /* NSMutableSet+BlocksKit.h */, A77A230DD6AF310C41E9C858AAE6F935 /* NSMutableSet+BlocksKit.m */, 46EFDC605BDEB95E1A9B82AEF274BD22 /* NSObject+BKAssociatedObjects.h */, C01BD2B1CC9309D65230900534DF7C40 /* NSObject+BKAssociatedObjects.m */, B510783B568A6D55FCAAFE7A8BBB35EC /* NSObject+BKBlockExecution.h */, 33BC212BC63A8F33CB9874D61425C2A6 /* NSObject+BKBlockExecution.m */, 97A6FD59B94F19837F47228762F60765 /* NSObject+BKBlockObservation.h */, BE2997B16159B7B5802CEB7CCA4F21BA /* NSObject+BKBlockObservation.m */, 785F482D4C83DF5936253BF9509A20E9 /* NSOrderedSet+BlocksKit.h */, C5D6B3E5DEC02F3C9DE27DD8628A08DC /* NSOrderedSet+BlocksKit.m */, 77DE1165EA844BC34C8346F58A8F0A5A /* NSSet+BlocksKit.h */, 8CAD913AE197086CEEE294B9F5502653 /* NSSet+BlocksKit.m */, E7722EACAD43F5A9B234A80B32CB11C8 /* NSTimer+BlocksKit.h */, 2DDB454F9D30684567C7FF47639F70CB /* NSTimer+BlocksKit.m */, ); name = Core; sourceTree = ""; }; CC333F97E94301B7BED7C872F3A6BB41 /* MessageUI */ = { isa = PBXGroup; children = ( 21F951F391EDAD89F86B953947D86B2F /* BlocksKit+MessageUI.h */, B46E021A91570EABA92EE2A75C32BE12 /* MFMailComposeViewController+BlocksKit.h */, 3C50D73F1B981F3B038DF62C2F60A37C /* MFMailComposeViewController+BlocksKit.m */, 634D4C0636DCCAFFBD36469460668E7E /* MFMessageComposeViewController+BlocksKit.h */, 11F45121D62B3EEBDB4A186317A573F5 /* MFMessageComposeViewController+BlocksKit.m */, ); name = MessageUI; sourceTree = ""; }; E4270B0AD4C62C0E70D034DF108FC1BB /* Support Files */ = { isa = PBXGroup; children = ( 1169513FD91CD57AB8AC5BB9E020DDB3 /* NBSwipePageView.xcconfig */, 34A1A8EBB6B2BE8DD6FEEF00D06054E4 /* NBSwipePageView-dummy.m */, E4F9ABD6A796F565BA3FE9C92C648F98 /* NBSwipePageView-prefix.pch */, ); name = "Support Files"; path = "../Target Support Files/NBSwipePageView"; sourceTree = ""; }; EA235F8A517EEBF391EF796EECC81405 /* Support Files */ = { isa = PBXGroup; children = ( A08A8DB765006DD2C2B3B2C680FCF822 /* BlocksKit.xcconfig */, 13383F03F54652A8599B82F086D0331C /* BlocksKit-dummy.m */, A20A06929A4BC668B1088FBFA4C78044 /* BlocksKit-prefix.pch */, ); name = "Support Files"; path = "../Target Support Files/BlocksKit"; sourceTree = ""; }; FD79ADB775FA1C18313058307DBD5B48 /* Targets Support Files */ = { isa = PBXGroup; children = ( 776E2A08A21AF1309108AF65E833B8E1 /* Pods-testPasterImage */, ); name = "Targets Support Files"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 3CD240D680E588C3F917736F4D3360EA /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 0F4EF1312B94E272652DA22CCDF8E52D /* NBSwipePageView.h in Headers */, A02CE14E5350ABACF361F7EB4696AA42 /* NBSwipePageViewSheet.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; 9F9FD509AAD735AC4AB664BAA7649312 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 8517BE33C254EE906D831579DD8C72B3 /* A2BlockInvocation.h in Headers */, 0692E35064349B6FA8C1EFD50B7B1F45 /* A2DynamicDelegate.h in Headers */, 1FACCDACF70A7AF5AAED0F35D9AC0642 /* BKMacros.h in Headers */, D7AFF4F4AA1900F1FDD8CCC28367CD1C /* BlocksKit+MessageUI.h in Headers */, C2BFF405BE0AEE5C66C90E6FD8B10415 /* BlocksKit+UIKit.h in Headers */, BE2BE12ECE566C14238DD7845DEDD84B /* BlocksKit.h in Headers */, EF87B1AB7825C0B9244F364CEAC1EF31 /* MFMailComposeViewController+BlocksKit.h in Headers */, 33C43B6C020C6A9CC4EE5C22650C550E /* MFMessageComposeViewController+BlocksKit.h in Headers */, 28A0BEDF1DB5E178DEAF1D03F718557B /* NSArray+BlocksKit.h in Headers */, D9D88ED515332296D0EE0C7129EDAAA0 /* NSCache+BlocksKit.h in Headers */, A5DBFF76EDEC1BCDA0351DCE8407ACA9 /* NSDictionary+BlocksKit.h in Headers */, 3CF5DE3EC202C9678B0120CB3CC93FE3 /* NSIndexSet+BlocksKit.h in Headers */, C9B6328F023FF633ABA6879D50FC90DE /* NSInvocation+BlocksKit.h in Headers */, 1BE7CD118C7601DDD1629547E938ED5E /* NSMutableArray+BlocksKit.h in Headers */, 9F9CFBD464085524F455C4D19211E69E /* NSMutableDictionary+BlocksKit.h in Headers */, 3DF2307D736F5A334CC5392A06B142C0 /* NSMutableIndexSet+BlocksKit.h in Headers */, CC7E36A547AEE6456442AF7F5C60E2F9 /* NSMutableOrderedSet+BlocksKit.h in Headers */, 03592DBD830EF65C1AE796A0697F46E1 /* NSMutableSet+BlocksKit.h in Headers */, 484776F8B4CF9A89AA18C6874E246DF6 /* NSObject+A2BlockDelegate.h in Headers */, EC783E9B9EA9DDFC778E4AA0D5065097 /* NSObject+A2DynamicDelegate.h in Headers */, 0F0550B889810895B32BCA065DD6CFC4 /* NSObject+BKAssociatedObjects.h in Headers */, F6516207095BAB4A00C52187CFAD097B /* NSObject+BKBlockExecution.h in Headers */, C7E0B31A7916AABF23A79CB06E1F5272 /* NSObject+BKBlockObservation.h in Headers */, A026405E495CA2EFF557A70D1515A689 /* NSOrderedSet+BlocksKit.h in Headers */, 01149FA585A714569093657B85C1A350 /* NSSet+BlocksKit.h in Headers */, 58F4C1C349633CE28F242E5FC8518636 /* NSTimer+BlocksKit.h in Headers */, 423CD981F80732AA6C075F7F633CFBBD /* NSURLConnection+BlocksKit.h in Headers */, E32DDF26286A2F7F77F8B90754373696 /* UIActionSheet+BlocksKit.h in Headers */, 5467BA80FE76E5928DBC92FCA8F319DD /* UIAlertView+BlocksKit.h in Headers */, A229FCF9FEBBF16977B33AB2FEF23830 /* UIBarButtonItem+BlocksKit.h in Headers */, A1968C04873813D7CEB076FDFCBC479C /* UIControl+BlocksKit.h in Headers */, B25F8085B440D68735024862A5F6AD9F /* UIGestureRecognizer+BlocksKit.h in Headers */, 61898DE2259DB9ECC1F23C538FCE7BBB /* UIImagePickerController+BlocksKit.h in Headers */, 455F71D95890455473B3AF068D2003D1 /* UIPopoverController+BlocksKit.h in Headers */, 77515111C9AFE11AB1287761150614F5 /* UITextField+BlocksKit.h in Headers */, F60CAF477B4F4573C02F675C42DFFD2D /* UIView+BlocksKit.h in Headers */, 12F7B27FB2422AC6413E77B7F98812C4 /* UIWebView+BlocksKit.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ 9C6466D79F40B07C4D15FDE68159545C /* NBSwipePageView */ = { isa = PBXNativeTarget; buildConfigurationList = 57A1A18A9407B891DD205E45A6595818 /* Build configuration list for PBXNativeTarget "NBSwipePageView" */; buildPhases = ( 87C3337015A4C26A323FC00B5507A546 /* Sources */, 8B550906D4EEAFEF38AACE8AD606D2D9 /* Frameworks */, 3CD240D680E588C3F917736F4D3360EA /* Headers */, ); buildRules = ( ); dependencies = ( ); name = NBSwipePageView; productName = NBSwipePageView; productReference = 745574CB3EE981C509D1E2696FFE092F /* libNBSwipePageView.a */; productType = "com.apple.product-type.library.static"; }; A09705FA24834CF6EA77A258F75D7570 /* Pods-testPasterImage */ = { isa = PBXNativeTarget; buildConfigurationList = 7F016A1D594379C3949F8A97016F718C /* Build configuration list for PBXNativeTarget "Pods-testPasterImage" */; buildPhases = ( D6D2657C23DD722242EF7C5929886B32 /* Sources */, F4195BEBE6C06638A02A058FF98AB60E /* Frameworks */, ); buildRules = ( ); dependencies = ( EA096BEBB65B906AEBDAF732DDE3066B /* PBXTargetDependency */, B22F90C5C007A968BD34DB33162D548B /* PBXTargetDependency */, ); name = "Pods-testPasterImage"; productName = "Pods-testPasterImage"; productReference = E7F011EB4C9F94875BC0C31D693729FE /* libPods-testPasterImage.a */; productType = "com.apple.product-type.library.static"; }; DA1A7295DF2A99609DA0EEBF5E83233D /* BlocksKit */ = { isa = PBXNativeTarget; buildConfigurationList = 7B67B960A5D1DDC3FB6CC2E37DBBFD9F /* Build configuration list for PBXNativeTarget "BlocksKit" */; buildPhases = ( 5913D2DD4D386875C7FDF1DB4A94AC99 /* Sources */, 87D63FC8B5A5501852974C5E1F3328A6 /* Frameworks */, 9F9FD509AAD735AC4AB664BAA7649312 /* Headers */, ); buildRules = ( ); dependencies = ( ); name = BlocksKit; productName = BlocksKit; productReference = A855DC09868C0AF098946E945FF59AE8 /* libBlocksKit.a */; productType = "com.apple.product-type.library.static"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; LastUpgradeCheck = 0700; }; buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 7DB346D0F39D3F0E887471402A8071AB; productRefGroup = 9A5CCE0B8EE1965591F137FAB3A255A2 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( DA1A7295DF2A99609DA0EEBF5E83233D /* BlocksKit */, 9C6466D79F40B07C4D15FDE68159545C /* NBSwipePageView */, A09705FA24834CF6EA77A258F75D7570 /* Pods-testPasterImage */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ 5913D2DD4D386875C7FDF1DB4A94AC99 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 3221D2FE805E7A2E298CB3B9CC4E6AF0 /* A2BlockInvocation.m in Sources */, 0A288C4D0ED296320F86966D45E8D5E9 /* A2DynamicDelegate.m in Sources */, DB21A546C83305719CD699E00E36AA3F /* BlocksKit-dummy.m in Sources */, 37A05672C67666332CF82130E9A461C2 /* MFMailComposeViewController+BlocksKit.m in Sources */, 7E8DF508233A1A7A663933939A6D5FE8 /* MFMessageComposeViewController+BlocksKit.m in Sources */, 6F6DD1FA269EB37E6CC9722C59AFBA5B /* NSArray+BlocksKit.m in Sources */, C237814AF824CAE9A479AD0F4DB151AA /* NSCache+BlocksKit.m in Sources */, F3040EE21525146A4AABD68CFF758D23 /* NSDictionary+BlocksKit.m in Sources */, F67325523D6DDBF4AF0C19A02ED3FDBD /* NSIndexSet+BlocksKit.m in Sources */, B6947A884743188A3E6C81EA172D4DCE /* NSInvocation+BlocksKit.m in Sources */, B74B90AB5E2F98B82040E5B791B1E513 /* NSMutableArray+BlocksKit.m in Sources */, A5CA4DD465154E16BF094796B56E7E52 /* NSMutableDictionary+BlocksKit.m in Sources */, 149B9A4BDC7FB1FEDE01059764F1D584 /* NSMutableIndexSet+BlocksKit.m in Sources */, 14BAF7AE2D75E18559739D71CFF10C84 /* NSMutableOrderedSet+BlocksKit.m in Sources */, A2FC6CF3F13C4799D04AC89ADD403AED /* NSMutableSet+BlocksKit.m in Sources */, 79588DF8F673302C22F3C81278A0B98E /* NSObject+A2BlockDelegate.m in Sources */, F09A8E1234A6B7D95122D5DAEA3870FF /* NSObject+A2DynamicDelegate.m in Sources */, 7D2D914EEDBCFF0F225F680F75D5694E /* NSObject+BKAssociatedObjects.m in Sources */, D6017E171F626B176414E066B800C1AF /* NSObject+BKBlockExecution.m in Sources */, 9C639C4D43608486642208566DF05AF5 /* NSObject+BKBlockObservation.m in Sources */, 213BDA0BFDC7FA8B00CD8395940400E2 /* NSOrderedSet+BlocksKit.m in Sources */, D53F7D2E487057DC8EDA59A6DD54FF7A /* NSSet+BlocksKit.m in Sources */, 6F2746610AB8BBFA162997F6AED950F7 /* NSTimer+BlocksKit.m in Sources */, 9FADA4523CE1BFD6E588D400285BAC0E /* NSURLConnection+BlocksKit.m in Sources */, C7C6F46E66572803459747BD9121EB20 /* UIActionSheet+BlocksKit.m in Sources */, F222764F0ED41EF907EE5D439DA182A1 /* UIAlertView+BlocksKit.m in Sources */, 6DCBF5A3569BA772FBAB3379A00464D2 /* UIBarButtonItem+BlocksKit.m in Sources */, 80D7B80A26162132A65EE9167AEAE94F /* UIControl+BlocksKit.m in Sources */, 2CE50403797DDF662DAE1DBDEF30A901 /* UIGestureRecognizer+BlocksKit.m in Sources */, CB21742066F67241062931F6F568D071 /* UIImagePickerController+BlocksKit.m in Sources */, F5C8F609901D5C71DC95528248D1D0F3 /* UIPopoverController+BlocksKit.m in Sources */, 6FE51449ABAA54EF33F44CE810BAD905 /* UITextField+BlocksKit.m in Sources */, 992944F68F8CC38008B2C611A0107FDE /* UIView+BlocksKit.m in Sources */, E09FAE444FA9AAC6F1F0295F5092A2FC /* UIWebView+BlocksKit.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 87C3337015A4C26A323FC00B5507A546 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 73B9779AEDACEB09223A4474DCE9F330 /* NBSwipePageView-dummy.m in Sources */, DD97B6AC8570C045E8327C7E8118E0A4 /* NBSwipePageView.m in Sources */, 0B1447334EF3FCD08E783F72251FC1EB /* NBSwipePageViewSheet.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; D6D2657C23DD722242EF7C5929886B32 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( E0C060F23AA82483327B74CCD9B72676 /* Pods-testPasterImage-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ B22F90C5C007A968BD34DB33162D548B /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = NBSwipePageView; target = 9C6466D79F40B07C4D15FDE68159545C /* NBSwipePageView */; targetProxy = CA315BBEDAB8A2B4955C90AD54907F2F /* PBXContainerItemProxy */; }; EA096BEBB65B906AEBDAF732DDE3066B /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = BlocksKit; target = DA1A7295DF2A99609DA0EEBF5E83233D /* BlocksKit */; targetProxy = 371ED08071AFFDADE018659914EF5E2E /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ 084FC4A07EC34209662C66F29F7681AD /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = A08A8DB765006DD2C2B3B2C680FCF822 /* BlocksKit.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; GCC_PREFIX_HEADER = "Target Support Files/BlocksKit/BlocksKit-prefix.pch"; IPHONEOS_DEPLOYMENT_TARGET = 6.0; MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PRIVATE_HEADERS_FOLDER_PATH = ""; PRODUCT_NAME = "$(TARGET_NAME)"; PUBLIC_HEADERS_FOLDER_PATH = ""; SDKROOT = iphoneos; SKIP_INSTALL = YES; }; name = Release; }; 185A114B40621806837E96546C23AFB0 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 1169513FD91CD57AB8AC5BB9E020DDB3 /* NBSwipePageView.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; GCC_PREFIX_HEADER = "Target Support Files/NBSwipePageView/NBSwipePageView-prefix.pch"; IPHONEOS_DEPLOYMENT_TARGET = 5.0; MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PRIVATE_HEADERS_FOLDER_PATH = ""; PRODUCT_NAME = "$(TARGET_NAME)"; PUBLIC_HEADERS_FOLDER_PATH = ""; SDKROOT = iphoneos; SKIP_INSTALL = YES; }; name = Release; }; 3911AA788B81DA714CBD18F5C8147B44 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 1169513FD91CD57AB8AC5BB9E020DDB3 /* NBSwipePageView.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; GCC_PREFIX_HEADER = "Target Support Files/NBSwipePageView/NBSwipePageView-prefix.pch"; IPHONEOS_DEPLOYMENT_TARGET = 5.0; MTL_ENABLE_DEBUG_INFO = YES; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PRIVATE_HEADERS_FOLDER_PATH = ""; PRODUCT_NAME = "$(TARGET_NAME)"; PUBLIC_HEADERS_FOLDER_PATH = ""; SDKROOT = iphoneos; SKIP_INSTALL = YES; }; name = Debug; }; 47BEF9D903506B003EA5C2B249729489 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "POD_CONFIGURATION_DEBUG=1", "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.0; ONLY_ACTIVE_ARCH = YES; STRIP_INSTALLED_PRODUCT = NO; SYMROOT = "${SRCROOT}/../build"; }; name = Debug; }; 7B1E53CA582D1E63E46755F6803BCCFC /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = C71C3F131A855C7CD9143B43D775A182 /* Pods-testPasterImage.debug.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.0; MACH_O_TYPE = staticlib; MTL_ENABLE_DEBUG_INFO = YES; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; }; name = Debug; }; 80EE96C354F26F909C6EBE5E162235BD /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = A08A8DB765006DD2C2B3B2C680FCF822 /* BlocksKit.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; GCC_PREFIX_HEADER = "Target Support Files/BlocksKit/BlocksKit-prefix.pch"; IPHONEOS_DEPLOYMENT_TARGET = 6.0; MTL_ENABLE_DEBUG_INFO = YES; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PRIVATE_HEADERS_FOLDER_PATH = ""; PRODUCT_NAME = "$(TARGET_NAME)"; PUBLIC_HEADERS_FOLDER_PATH = ""; SDKROOT = iphoneos; SKIP_INSTALL = YES; }; name = Debug; }; A58654E010E1195BCD6574D6A5F2A9A1 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 29C868A366BA357EA2ECCFFE176E0BBF /* Pods-testPasterImage.release.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.0; MACH_O_TYPE = staticlib; MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; }; name = Release; }; AAF678CED40D3499169D10F63CA0719E /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_PREPROCESSOR_DEFINITIONS = ( "POD_CONFIGURATION_RELEASE=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.0; STRIP_INSTALLED_PRODUCT = NO; SYMROOT = "${SRCROOT}/../build"; VALIDATE_PRODUCT = YES; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( 47BEF9D903506B003EA5C2B249729489 /* Debug */, AAF678CED40D3499169D10F63CA0719E /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 57A1A18A9407B891DD205E45A6595818 /* Build configuration list for PBXNativeTarget "NBSwipePageView" */ = { isa = XCConfigurationList; buildConfigurations = ( 3911AA788B81DA714CBD18F5C8147B44 /* Debug */, 185A114B40621806837E96546C23AFB0 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B67B960A5D1DDC3FB6CC2E37DBBFD9F /* Build configuration list for PBXNativeTarget "BlocksKit" */ = { isa = XCConfigurationList; buildConfigurations = ( 80EE96C354F26F909C6EBE5E162235BD /* Debug */, 084FC4A07EC34209662C66F29F7681AD /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7F016A1D594379C3949F8A97016F718C /* Build configuration list for PBXNativeTarget "Pods-testPasterImage" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B1E53CA582D1E63E46755F6803BCCFC /* Debug */, A58654E010E1195BCD6574D6A5F2A9A1 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; } ================================================ FILE: Pods/Pods.xcodeproj/xcuserdata/vipstore.xcuserdatad/xcschemes/BlocksKit.xcscheme ================================================ ================================================ FILE: Pods/Pods.xcodeproj/xcuserdata/vipstore.xcuserdatad/xcschemes/NBSwipePageView.xcscheme ================================================ ================================================ FILE: Pods/Pods.xcodeproj/xcuserdata/vipstore.xcuserdatad/xcschemes/Pods-testPasterImage.xcscheme ================================================ ================================================ FILE: Pods/Pods.xcodeproj/xcuserdata/vipstore.xcuserdatad/xcschemes/xcschememanagement.plist ================================================ SchemeUserState BlocksKit.xcscheme isShown NBSwipePageView.xcscheme isShown Pods-testPasterImage.xcscheme isShown SuppressBuildableAutocreation 9C6466D79F40B07C4D15FDE68159545C primary A09705FA24834CF6EA77A258F75D7570 primary DA1A7295DF2A99609DA0EEBF5E83233D primary ================================================ FILE: Pods/Pods.xcodeproj/xcuserdata/wangyingbo.xcuserdatad/xcschemes/BlocksKit.xcscheme ================================================ ================================================ FILE: Pods/Pods.xcodeproj/xcuserdata/wangyingbo.xcuserdatad/xcschemes/NBSwipePageView.xcscheme ================================================ ================================================ FILE: Pods/Pods.xcodeproj/xcuserdata/wangyingbo.xcuserdatad/xcschemes/Pods-testPasterImage.xcscheme ================================================ ================================================ FILE: Pods/Pods.xcodeproj/xcuserdata/wangyingbo.xcuserdatad/xcschemes/xcschememanagement.plist ================================================ SchemeUserState BlocksKit.xcscheme orderHint 1 NBSwipePageView.xcscheme orderHint 2 Pods-testPasterImage.xcscheme orderHint 3 SuppressBuildableAutocreation 9C6466D79F40B07C4D15FDE68159545C primary A09705FA24834CF6EA77A258F75D7570 primary DA1A7295DF2A99609DA0EEBF5E83233D primary ================================================ FILE: Pods/Target Support Files/BlocksKit/BlocksKit-dummy.m ================================================ #import @interface PodsDummy_BlocksKit : NSObject @end @implementation PodsDummy_BlocksKit @end ================================================ FILE: Pods/Target Support Files/BlocksKit/BlocksKit-prefix.pch ================================================ #ifdef __OBJC__ #import #endif ================================================ FILE: Pods/Target Support Files/BlocksKit/BlocksKit.xcconfig ================================================ CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/BlocksKit GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/BlocksKit" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/BlocksKit" "${PODS_ROOT}/Headers/Public/NBSwipePageView" OTHER_LDFLAGS = -framework "MessageUI" PODS_BUILD_DIR = $BUILD_DIR PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_ROOT = ${SRCROOT} PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} SKIP_INSTALL = YES ================================================ FILE: Pods/Target Support Files/NBSwipePageView/NBSwipePageView-dummy.m ================================================ #import @interface PodsDummy_NBSwipePageView : NSObject @end @implementation PodsDummy_NBSwipePageView @end ================================================ FILE: Pods/Target Support Files/NBSwipePageView/NBSwipePageView-prefix.pch ================================================ #ifdef __OBJC__ #import #endif ================================================ FILE: Pods/Target Support Files/NBSwipePageView/NBSwipePageView.xcconfig ================================================ CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/NBSwipePageView GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/NBSwipePageView" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/BlocksKit" "${PODS_ROOT}/Headers/Public/NBSwipePageView" PODS_BUILD_DIR = $BUILD_DIR PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_ROOT = ${SRCROOT} PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} SKIP_INSTALL = YES ================================================ FILE: Pods/Target Support Files/Pods-testPasterImage/Pods-testPasterImage-acknowledgements.markdown ================================================ # Acknowledgements This application makes use of the following third party libraries: ## BlocksKit // // LICENSE // BlocksKit // Copyright (c) 2011-2014 Zachary Waldowski, Alexsander Akers, and the BlocksKit Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Generated by CocoaPods - https://cocoapods.org ================================================ FILE: Pods/Target Support Files/Pods-testPasterImage/Pods-testPasterImage-acknowledgements.plist ================================================ PreferenceSpecifiers FooterText This application makes use of the following third party libraries: Title Acknowledgements Type PSGroupSpecifier FooterText // // LICENSE // BlocksKit // Copyright (c) 2011-2014 Zachary Waldowski, Alexsander Akers, and the BlocksKit Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Title BlocksKit Type PSGroupSpecifier FooterText Generated by CocoaPods - https://cocoapods.org Title Type PSGroupSpecifier StringsTable Acknowledgements Title Acknowledgements ================================================ FILE: Pods/Target Support Files/Pods-testPasterImage/Pods-testPasterImage-dummy.m ================================================ #import @interface PodsDummy_Pods_testPasterImage : NSObject @end @implementation PodsDummy_Pods_testPasterImage @end ================================================ FILE: Pods/Target Support Files/Pods-testPasterImage/Pods-testPasterImage-frameworks.sh ================================================ #!/bin/sh set -e echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" install_framework() { if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then local source="${BUILT_PRODUCTS_DIR}/$1" elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" elif [ -r "$1" ]; then local source="$1" fi local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" if [ -L "${source}" ]; then echo "Symlinked..." source="$(readlink "${source}")" fi # use filter instead of exclude so missing patterns dont' throw errors echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" local basename basename="$(basename -s .framework "$1")" binary="${destination}/${basename}.framework/${basename}" if ! [ -r "$binary" ]; then binary="${destination}/${basename}" fi # Strip invalid architectures so "fat" simulator / device frameworks work on device if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then strip_invalid_archs "$binary" fi # Resign the code if required by the build settings to avoid unstable apps code_sign_if_enabled "${destination}/$(basename "$1")" # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then local swift_runtime_libs swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) for lib in $swift_runtime_libs; do echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" code_sign_if_enabled "${destination}/${lib}" done fi } # Signs a framework with the provided identity code_sign_if_enabled() { if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then # Use the current code_sign_identitiy echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\"" /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1" fi } # Strip invalid architectures strip_invalid_archs() { binary="$1" # Get architectures for current file archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" stripped="" for arch in $archs; do if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then # Strip non-valid architectures in-place lipo -remove "$arch" -output "$binary" "$binary" || exit 1 stripped="$stripped $arch" fi done if [[ "$stripped" ]]; then echo "Stripped $binary of architectures:$stripped" fi } ================================================ FILE: Pods/Target Support Files/Pods-testPasterImage/Pods-testPasterImage-resources.sh ================================================ #!/bin/sh set -e mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt > "$RESOURCES_TO_COPY" XCASSET_FILES=() case "${TARGETED_DEVICE_FAMILY}" in 1,2) TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" ;; 1) TARGET_DEVICE_ARGS="--target-device iphone" ;; 2) TARGET_DEVICE_ARGS="--target-device ipad" ;; *) TARGET_DEVICE_ARGS="--target-device mac" ;; esac realpath() { DIRECTORY="$(cd "${1%/*}" && pwd)" FILENAME="${1##*/}" echo "$DIRECTORY/$FILENAME" } install_resource() { if [[ "$1" = /* ]] ; then RESOURCE_PATH="$1" else RESOURCE_PATH="${PODS_ROOT}/$1" fi if [[ ! -e "$RESOURCE_PATH" ]] ; then cat << EOM error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. EOM exit 1 fi case $RESOURCE_PATH in *.storyboard) echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} ;; *.xib) echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} ;; *.framework) echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" ;; *.xcdatamodel) echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" ;; *.xcdatamodeld) echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" ;; *.xcmappingmodel) echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" ;; *.xcassets) ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH") XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") ;; *) echo "$RESOURCE_PATH" echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" ;; esac } mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" fi rm -f "$RESOURCES_TO_COPY" if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] then # Find all other xcassets (this unfortunately includes those of path pods and other targets). OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) while read line; do if [[ $line != "`realpath $PODS_ROOT`*" ]]; then XCASSET_FILES+=("$line") fi done <<<"$OTHER_XCASSETS" printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" fi ================================================ FILE: Pods/Target Support Files/Pods-testPasterImage/Pods-testPasterImage.debug.xcconfig ================================================ GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/BlocksKit" "${PODS_ROOT}/Headers/Public/NBSwipePageView" LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/BlocksKit" "$PODS_CONFIGURATION_BUILD_DIR/NBSwipePageView" OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/BlocksKit" -isystem "${PODS_ROOT}/Headers/Public/NBSwipePageView" OTHER_LDFLAGS = $(inherited) -ObjC -l"BlocksKit" -l"NBSwipePageView" -framework "MessageUI" PODS_BUILD_DIR = $BUILD_DIR PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_ROOT = ${SRCROOT}/Pods ================================================ FILE: Pods/Target Support Files/Pods-testPasterImage/Pods-testPasterImage.release.xcconfig ================================================ GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/BlocksKit" "${PODS_ROOT}/Headers/Public/NBSwipePageView" LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/BlocksKit" "$PODS_CONFIGURATION_BUILD_DIR/NBSwipePageView" OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/BlocksKit" -isystem "${PODS_ROOT}/Headers/Public/NBSwipePageView" OTHER_LDFLAGS = $(inherited) -ObjC -l"BlocksKit" -l"NBSwipePageView" -framework "MessageUI" PODS_BUILD_DIR = $BUILD_DIR PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_ROOT = ${SRCROOT}/Pods ================================================ FILE: README.md ================================================ # YBPasterImage ### ***给图片添加滤镜和贴纸,支持14种滤镜效果*** ### 一、介绍 ##### 这是一个关于在图片上添加贴纸的demo,动图里演示了操作方法。 >+ 项目里要求,要实现下面三种功能: >+ 对图片添加滤镜; >+ 对图片添加标签; >+ 对图片添加贴纸。 ### 二、怎么给图片添加标签可参考我的另外一个[项目](https://github.com/wangyingbo/YBTagViewLib),效果图如下: 动图 [![gif图](https://raw.githubusercontent.com/wangyingbo/YBTagViewLib/master/gif.gif)](https://github.com/wangyingbo/YBTagViewLib/archive/master.zip) ### 三、给图片添加滤镜和贴纸的效果图如下: 动图 ![gif图](https://raw.githubusercontent.com/wangyingbo/YBPasterImage/master/gif.gif) ### 四、项目下载地址 [项目](https://github.com/wangyingbo/YBPasterImage/archive/master.zip) ================================================ FILE: files/README发帖专用.md ================================================ # YBPasterImage ## ***给图片添加滤镜和贴纸,支持14种滤镜效果*** ####修复了一些已知的bug,重新发帖上传,欢迎大家提意见。 ###项目地址[DEMO](https://github.com/wangyingbo/YBPasterImage),欢迎fork,欢迎start ### 一、介绍 ##### 这是一个关于在图片上添加贴纸的demo,动图里演示了操作方法。 >+ 项目里要求,要实现下面三种功能: >+ 对图片添加滤镜; >+ 对图片添加标签; >+ 对图片添加贴纸。 ### 二、怎么给图片添加标签可参考我的另外一个[项目](https://github.com/wangyingbo/YBTagViewLib),欢迎fork,欢迎start。效果图如下(点击动图下载): 动图 [![gif图](https://raw.githubusercontent.com/wangyingbo/YBTagViewLib/master/gif.gif)](https://github.com/wangyingbo/YBTagViewLib/archive/master.zip) ### 三、给图片添加滤镜和贴纸的效果图如下: 动图 ![gif图](https://raw.githubusercontent.com/wangyingbo/YBPasterImage/master/gif.gif) ### 四、最后,欢迎fork,欢迎start,多提Issues给出意见 项目地址:https://github.com/wangyingbo/YBPasterImage ================================================ FILE: testPasterImage/AppDelegate.h ================================================ // // AppDelegate.h // testPasterImage // // Created by 王迎博 on 16/9/5. // Copyright © 2016年 王迎博. All rights reserved. // #import @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end ================================================ FILE: testPasterImage/AppDelegate.m ================================================ // // AppDelegate.m // testPasterImage // // Created by 王迎博 on 16/9/5. // Copyright © 2016年 王迎博. All rights reserved. // #import "AppDelegate.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { return YES; } - (void)applicationWillResignActive:(UIApplication *)application { } - (void)applicationDidEnterBackground:(UIApplication *)application { } - (void)applicationWillEnterForeground:(UIApplication *)application { } - (void)applicationDidBecomeActive:(UIApplication *)application { } - (void)applicationWillTerminate:(UIApplication *)application { } @end ================================================ FILE: testPasterImage/Assets.xcassets/1.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "1.png", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: testPasterImage/Assets.xcassets/2.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "2.png", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: testPasterImage/Assets.xcassets/3.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "3.png", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: testPasterImage/Assets.xcassets/4.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "4.png", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: testPasterImage/Assets.xcassets/5.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "5.png", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: testPasterImage/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: testPasterImage/Assets.xcassets/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: testPasterImage/Assets.xcassets/bt_paster_delete.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "删除.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "删除@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "删除@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: testPasterImage/Assets.xcassets/bt_paster_transform.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "大小.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "大小@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "大小@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: testPasterImage/Assets.xcassets/dogs.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "dogs.jpeg", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: testPasterImage/Assets.xcassets/gao4.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "gao4.jpg", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: testPasterImage/Assets.xcassets/gaoyuanyuan.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "gaoyuanyuan.png", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: testPasterImage/Base.lproj/LaunchScreen.storyboard ================================================ ================================================ FILE: testPasterImage/Base.lproj/Main.storyboard ================================================ ================================================ FILE: testPasterImage/Categories/UIImage+AddFunction.h ================================================ // UIImage+AddFunction.h // testPasterImage // // Created by 王迎博 on 16/9/5. // Copyright © 2016年 王迎博. All rights reserved. // #import @interface UIImage (AddFunction) + (UIImage *)squareImageFromImage:(UIImage *)image scaledToSize:(CGFloat)newSize ; + (UIImage *)getImageFromView:(UIView *)theView ; @end ================================================ FILE: testPasterImage/Categories/UIImage+AddFunction.m ================================================ // UIImage+AddFunction.h // testPasterImage // // Created by 王迎博 on 16/9/5. // Copyright © 2016年 王迎博. All rights reserved. // #import "UIImage+AddFunction.h" @implementation UIImage (AddFunction) //裁剪正方 /** * 剪切图片为正方形 * * @param image 原始图片比如size大小为(400x200)pixels * @param newSize 正方形的size比如400pixels * * @return 返回正方形图片(400x400)pixels */ + (UIImage *)squareImageFromImage:(UIImage *)image scaledToSize:(CGFloat)newSize { CGAffineTransform scaleTransform; CGPoint origin; if (image.size.width > image.size.height) { //image原始高度为200,缩放image的高度为400pixels,所以缩放比率为2 CGFloat scaleRatio = newSize / image.size.height; scaleTransform = CGAffineTransformMakeScale(scaleRatio, scaleRatio); //设置绘制原始图片的画笔坐标为CGPoint(-100, 0)pixels origin = CGPointMake(-(image.size.width - image.size.height) / 2.0f, 0); } else { CGFloat scaleRatio = newSize / image.size.width; scaleTransform = CGAffineTransformMakeScale(scaleRatio, scaleRatio); origin = CGPointMake(0, -(image.size.height - image.size.width) / 2.0f); } CGSize size = CGSizeMake(newSize, newSize); //创建画板为(400x400)pixels if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) { UIGraphicsBeginImageContextWithOptions(size, YES, 1); } else { UIGraphicsBeginImageContext(size); } CGContextRef context = UIGraphicsGetCurrentContext(); //将image原始图片(400x200)pixels缩放为(800x400)pixels CGContextConcatCTM(context, scaleTransform); //origin也会从原始(-100, 0)缩放到(-200, 0) [image drawAtPoint:origin]; //获取缩放后剪切的image图片 image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; } // 将UIView转成UIImage + (UIImage *)getImageFromView:(UIView *)theView { CGSize orgSize = theView.bounds.size ; UIGraphicsBeginImageContextWithOptions(orgSize, NO, 1); [theView.layer renderInContext:UIGraphicsGetCurrentContext()] ; UIImage *image = UIGraphicsGetImageFromCurrentImageContext() ; UIGraphicsEndImageContext() ; return image ; } @end ================================================ FILE: testPasterImage/Categories/UIViewController+Example.h ================================================ // // UIViewController+Example.h // Kergou // // Created by 王迎博 on 16/4/28. // Copyright © 2016年 张帅. All rights reserved. // #import @interface UIViewController (Example) @property (copy, nonatomic) NSString *method; @end ================================================ FILE: testPasterImage/Categories/UIViewController+Example.m ================================================ // // UIViewController+Example.m // Kergou // // Created by 王迎博 on 16/4/28. // Copyright © 2016年 张帅. All rights reserved. // #import "UIViewController+Example.h" #import @implementation UIViewController (Example) #pragma mark - swizzle + (void)load { Method method1 = class_getInstanceMethod([self class], NSSelectorFromString(@"dealloc")); Method method2 = class_getInstanceMethod([self class], @selector(deallocSwizzle)); method_exchangeImplementations(method1, method2); } - (void)deallocSwizzle { NSLog(@"%@被销毁了", self); [self deallocSwizzle]; } static char MethodKey; - (void)setMethod:(NSString *)method { objc_setAssociatedObject(self, &MethodKey, method, OBJC_ASSOCIATION_COPY_NONATOMIC); } - (NSString *)method { return objc_getAssociatedObject(self, &MethodKey); } @end ================================================ FILE: testPasterImage/Categories/UIViewController+Extension.h ================================================ // // UIViewController+Extension.h // Kergou // // Created by 王迎博 on 16/4/28. // Copyright © 2016年 张帅. All rights reserved. // #import /**定义左边按钮block*/ typedef void(^backButtonBlock)(UIButton *BackButton); /**定义右边按钮block*/ typedef void(^rightButtonBlock)(UIButton *rightButton); /**定义左边按钮点击事件block*/ typedef void(^leftBtnTargetBlock)(NSString *string); /**定义右边按钮点击事件block*/ typedef void(^rightBtnTargetBlock)(NSString *string); @interface UIViewController (Extension) @property (nonatomic, copy) NSString *name; //视图名字 @property (nonatomic, assign) BOOL hasChildViewController;//是否有子视图 @property (nonatomic, strong) UIImage *backgroundImage; //背景图片 /**右边按钮点击事件block*/ @property (nonatomic, copy) rightBtnTargetBlock rightBtnBlock; /**左边按钮点击事件block*/ @property (nonatomic, copy) leftBtnTargetBlock leftBtnBlock; /** * 添加左边返回按钮 * * @param buttonW 返回按钮宽 * @param buttonH 返回按钮高 * @param title 返回按钮的title * @param titleColor 字体颜色 * @param buttonImage 北京图片 * @param negativeSpacer 间隔距离 * @param block 回调block */ - (void)initBackButtonWithButtonW:(CGFloat)buttonW buttonH:(CGFloat)buttonH title:(NSString *)title titleColor:(UIColor *)titleColor buttonImage:(UIImage *)buttonImage negativeSpacer:(CGFloat)negativeSpacer touchBlock:(backButtonBlock)block; /** * 添加右边返回按钮 * * @param buttonW 右边按钮宽 * @param buttonH 右边按钮高 * @param title 右边按钮的title * @param titleColor 字体颜色 * @param block 回调block */ - (void)initRightButtonWithButtonW:(CGFloat)buttonW buttonH:(CGFloat)buttonH title:(NSString *)title titleColor:(UIColor *)titleColor touchBlock:(rightButtonBlock)block; /** * 触摸屏幕隐藏键盘 */ - (void)setUpForDismissKeyboard:(UIView *)selfView; @end ================================================ FILE: testPasterImage/Categories/UIViewController+Extension.m ================================================ // // UIViewController+Extension.m // Kergou // // Created by 王迎博 on 16/4/28. // Copyright © 2016年 张帅. All rights reserved. // #import "UIViewController+Extension.h" #import static const void *kName = "name"; static const void *kHasChildViewController = @"hasChildViewController"; static const void *kBackgroundImage = @"backgroundImage"; static const void *leftBlock = &leftBlock; static const void *rightBlock = &rightBlock; @implementation UIViewController (Extension) @dynamic leftBtnBlock; @dynamic rightBtnBlock; #pragma mark - 左边按钮点击事件block绑定 - (leftBtnTargetBlock)leftBtnBlock { return objc_getAssociatedObject(self, leftBlock); } - (void)setLeftBtnBlock:(leftBtnTargetBlock)leftBtnBlock { objc_setAssociatedObject(self, leftBlock, leftBtnBlock, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } #pragma mark - 右边按钮点击事件block绑定 - (rightBtnTargetBlock)rightBtnBlock { return objc_getAssociatedObject(self, rightBlock); } - (void)setRightBtnBlock:(rightBtnTargetBlock)rightBtnBlock { objc_setAssociatedObject(self, rightBlock, rightBtnBlock, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } #pragma mark - 字符串类型的动态绑定 - (NSString *)name { return objc_getAssociatedObject(self, kName); } - (void)setName:(NSString *)name { objc_setAssociatedObject(self, kName, name, OBJC_ASSOCIATION_COPY_NONATOMIC); } #pragma mark - BOOL类型的动态绑定 - (BOOL)hasChildViewController { return [objc_getAssociatedObject(self, kHasChildViewController) boolValue]; } - (void)setHasChildViewController:(BOOL)hasChildViewController { objc_setAssociatedObject(self, kHasChildViewController, [NSNumber numberWithBool:hasChildViewController], OBJC_ASSOCIATION_ASSIGN); } #pragma mark - 类类型的动态绑定 - (UIImage *)backgroundImage { return objc_getAssociatedObject(self, kBackgroundImage); } - (void)setBackgroundImage:(UIImage *)backgroundImage { objc_setAssociatedObject(self, kBackgroundImage, backgroundImage, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } //*************************************************************** /** * 添加左边返回按钮 * * @param buttonW 返回按钮宽 * @param buttonH 返回按钮高 * @param title 返回按钮的title * @param titleColor 字体颜色 * @param buttonImage 北京图片 * @param negativeSpacer 间隔距离 * @param block 回调block */ - (void)initBackButtonWithButtonW:(CGFloat)buttonW buttonH:(CGFloat)buttonH title:(NSString *)title titleColor:(UIColor *)titleColor buttonImage:(UIImage *)buttonImage negativeSpacer:(CGFloat)negativeSpacer touchBlock:(backButtonBlock)block { [self.navigationItem.backBarButtonItem setTitle:@""]; [self.navigationItem setHidesBackButton:YES]; self.navigationController.navigationBar.backgroundColor = [UIColor grayColor]; UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom]; if (title.length != 0) { [backBtn setTitle:title forState:UIControlStateNormal]; }else { if (buttonImage) { [backBtn setImage:buttonImage forState:UIControlStateNormal]; }else { [backBtn setImage:[UIImage imageNamed:@"zuojiantou.png"] forState:UIControlStateNormal]; } } if (titleColor) { [backBtn setTitleColor:titleColor forState:UIControlStateNormal]; }else { [backBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; } if (buttonH!=0 && buttonW!=0) { backBtn.frame = CGRectMake(0,0, buttonW, buttonH); }else { backBtn.frame = CGRectMake(0,0, 40, 20); } [backBtn addTarget:self action:@selector(backButtonClick:) forControlEvents:UIControlEventTouchUpInside]; UIBarButtonItem *barBtn = [[UIBarButtonItem alloc]initWithCustomView:backBtn]; if (negativeSpacer!=0) { //设置返回按钮到手机左边框的距离 UIBarButtonItem *negativeSpa = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; negativeSpa.width = -negativeSpacer; self.navigationItem.leftBarButtonItems = [NSArray arrayWithObjects:negativeSpa, barBtn ,nil]; }else { self.navigationItem.leftBarButtonItem = barBtn; } block(backBtn); } /** * 左按钮点击方法 */ - (void)backButtonClick:(UIButton *)backButton { self.leftBtnBlock(@"左按钮"); } /** * 添加右边返回按钮 * * @param buttonW 右边按钮宽 * @param buttonH 右边按钮高 * @param title 右边按钮的title * @param titleColor 字体颜色 * @param block 回调block */ - (void)initRightButtonWithButtonW:(CGFloat)buttonW buttonH:(CGFloat)buttonH title:(NSString *)title titleColor:(UIColor *)titleColor touchBlock:(rightButtonBlock)block { UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeCustom]; if (buttonW!=0 && buttonH!=0) { rightButton.frame = CGRectMake(0,0, buttonW, buttonH); }else { rightButton.frame = CGRectMake(0,0, 40, 30); } if (title.length!=0) { [rightButton setTitle:title forState:UIControlStateNormal]; }else { [rightButton setTitle:@"取消" forState:UIControlStateNormal]; } if (titleColor) { [rightButton setTitleColor:titleColor forState:UIControlStateNormal]; }else { [rightButton setTitleColor:[UIColor grayColor] forState:UIControlStateNormal]; } [rightButton addTarget:self action:@selector(rightButtonClick:) forControlEvents:UIControlEventTouchUpInside]; UIBarButtonItem *rightButtonItem = [[UIBarButtonItem alloc] initWithCustomView:rightButton]; self.navigationItem.rightBarButtonItem = rightButtonItem; block(rightButton); } /** * 右键点击方法 */ - (void)rightButtonClick:(UIButton *)rightButton { self.rightBtnBlock(@"右按钮"); } /** * 触摸屏幕隐藏键盘 */ - (void)setUpForDismissKeyboard:(UIView *)selfView { NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; UITapGestureRecognizer *singleTapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAnywhereToDismissKeyboard:)]; NSOperationQueue *mainQuene =[NSOperationQueue mainQueue]; [nc addObserverForName:UIKeyboardWillShowNotification object:nil queue:mainQuene usingBlock:^(NSNotification *note){ [selfView addGestureRecognizer:singleTapGR]; }]; [nc addObserverForName:UIKeyboardWillHideNotification object:nil queue:mainQuene usingBlock:^(NSNotification *note){ [selfView removeGestureRecognizer:singleTapGR]; }]; } /** * 触摸屏幕隐藏键盘的事件 */ - (void)tapAnywhereToDismissKeyboard:(UIGestureRecognizer *)gestureRecognizer { //此method会将self.view里所有的subview的first responder都resign掉 [self.view endEditing:YES]; } @end ================================================ FILE: testPasterImage/Categories/UIViewController+Swizzling.h ================================================ // // UIViewController+Swizzling.h // testPasterImage // // Created by 王迎博 on 16/10/19. // Copyright © 2016年 王迎博. All rights reserved. // #import #import @interface UIViewController (Swizzling) @end ================================================ FILE: testPasterImage/Categories/UIViewController+Swizzling.m ================================================ // // UIViewController+Swizzling.m // testPasterImage // // Created by 王迎博 on 16/10/19. // Copyright © 2016年 王迎博. All rights reserved. // #import "UIViewController+Swizzling.h" @implementation UIViewController (Swizzling) + (void)load { //我们只有在开发的时候才需要查看哪个viewController将出现 //所以在release模式下就没必要进行方法的交换 #ifdef DEBUG //原本的viewWillAppear方法 Method viewWillAppear = class_getInstanceMethod(self, @selector(viewWillAppear:)); //需要替换成 能够输出日志的viewWillAppear Method logViewWillAppear = class_getInstanceMethod(self, @selector(logViewWillAppear:)); //两方法进行交换 method_exchangeImplementations(viewWillAppear, logViewWillAppear); #endif } - (void)logViewWillAppear:(BOOL)animated { NSString *className = NSStringFromClass([self class]); //在这里,你可以进行过滤操作,指定哪些viewController需要打印,哪些不需要打印 if ([className hasPrefix:@"UI"] == NO) { NSLog(@"%@ will appear",className); } //下面方法的调用,其实是调用viewWillAppear [self logViewWillAppear:animated]; } @end ================================================ FILE: testPasterImage/Controllers/ViewController.h ================================================ // // ViewController.h // testPasterImage // // Created by 王迎博 on 16/9/5. // Copyright © 2016年 王迎博. All rights reserved. // #import @interface ViewController : UIViewController @end ================================================ FILE: testPasterImage/Controllers/ViewController.m ================================================ // // ViewController.m // testPasterImage // // Created by 王迎博 on 16/9/5. // Copyright © 2016年 王迎博. All rights reserved. // #import "ViewController.h" #import "YBPasterImageVC.h" #import "UIViewController+Swizzling.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UIImageView *imageView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self.navigationController setNavigationBarHidden:YES] ; [[UIApplication sharedApplication] setStatusBarHidden:YES] ; } /** * 跳转到下页 */ - (IBAction)addPasterImage:(UIButton *)sender { YBPasterImageVC *pasterVC = [[YBPasterImageVC alloc]init]; pasterVC.originalImage = [UIImage imageNamed:@"gao4"]; pasterVC.block = ^(UIImage *editedImage){ self.imageView.image = editedImage; }; [self.navigationController pushViewController:pasterVC animated:YES]; } @end ================================================ FILE: testPasterImage/Controllers/YBBaseViewController.h ================================================ // // YBBaseViewController.h // testPasterImage // // Created by 王迎博 on 16/10/19. // Copyright © 2016年 王迎博. All rights reserved. // #import @interface YBBaseViewController : UIViewController @end ================================================ FILE: testPasterImage/Controllers/YBBaseViewController.m ================================================ // // YBBaseViewController.m // testPasterImage // // Created by 王迎博 on 16/10/19. // Copyright © 2016年 王迎博. All rights reserved. // #import "YBBaseViewController.h" @interface YBBaseViewController () @end @implementation YBBaseViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; NSString *className = NSStringFromClass([self class]); NSLog(@"%@ will appear", className); } /* #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. } */ @end ================================================ FILE: testPasterImage/Controllers/YBPasterImageVC.h ================================================ // // YBPasterImageVC.h // testPasterImage // // Created by 王迎博 on 16/9/5. // Copyright © 2016年 王迎博. All rights reserved. // #import #define YBWeak(selfName,weakSelf) __weak __typeof(selfName *)weakSelf = self #define WS(weakSelf) __weak __typeof(&*self)weakSelf = self /**传给上个页面图片的block*/ typedef void(^PasterBlock)(UIImage *image); @interface YBPasterImageVC : UIViewController /**传数据的block*/ @property (nonatomic, copy) PasterBlock block; /**从上页带回来的原始image*/ @property (nonatomic, strong) UIImage *originalImage; /** * 初始化一个对象 * * @param name 名字 * * @return 自己 */ - (instancetype)initWithName:(NSString *)name; /**尽量不使用以下形式: @interface B : UIViewController @property (strong) NSString* name; @end //然后使用的时候这个样子: B* vc = [B new]; vc.name = @"xx"; [self.navigationController push:vc]; */ @end ================================================ FILE: testPasterImage/Controllers/YBPasterImageVC.m ================================================ // // YBPasterImageVC.m // testPasterImage // // Created by 王迎博 on 16/9/5. // Copyright © 2016年 王迎博. All rights reserved. // #import "YBPasterImageVC.h" #import "UIViewController+Extension.h" #import "YBPasterScrollView.h" #import "YBPasterView.h" #import "UIImage+AddFunction.h" #import "YBCustomButton.h" #import "BlocksKit.h" #import "BlocksKit+UIKit.h" #import "YBFilterScrollView.h" #import "UIViewController+Example.h" #import "UIViewController+Swizzling.h" /** * "滤镜",“标签”,“贴纸” */ typedef NS_ENUM(NSInteger, YBImageDecoration) { /*** 滤镜*/ YBImageFilter = 0, /*** 标签*/ YBImageTag, /*** 贴纸*/ YBImagePaster, }; #define FULL_SCREEN_H [UIScreen mainScreen].bounds.size.height #define FULL_SCREEN_W [UIScreen mainScreen].bounds.size.width /**底部的scrollView的高*/ const CGFloat pasterScrollView_H = 120; /**空白的距离间隔*/ extern CGFloat inset_space; /**默认的图片上的贴纸大小*/ static const CGFloat defaultPasterViewW_H = 120; /**底部按钮的高度*/ static CGFloat bottomButtonH = 44; @interface YBPasterImageVC () { NSInteger defaultIndex; NSString* _name; } /**上部的图片imageView*/ @property (nonatomic, strong) UIImageView *pasterImageView; /**多个贴纸样式的scrollView*/ @property (nonatomic, strong) YBPasterScrollView *pasterScrollView; /**装多个滤镜样式的scrollView*/ @property (nonatomic, strong) YBFilterScrollView *filterScrollView; /**图片数组*/ @property (nonatomic, copy) NSArray *imageArray; /**可变的装多个贴纸标签的数组*/ @property (nonatomic, strong) NSMutableArray *pasterViewMutArr; /**贴纸*/ @property (nonatomic, strong) YBPasterView *pasterView; /**底部的公共的按钮*/ @property (nonatomic, strong) YBCustomButton *bottomButton; /**底部滑动的红色的线*/ @property (nonatomic, strong) UIView *lineView; @end #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-variable" //消除没有用到的变量产生的警告 @implementation YBPasterImageVC /** * 初始化一个对象 * * @param name 名字 * * @return 自己 */ - (instancetype)initWithName:(NSString *)name { self = [super init]; if(!self) return self; _name = name; return self; } - (void)viewDidLoad { [super viewDidLoad]; //设置一些通用属性 [self setGeneralPropetory]; //添加右键 [self setRightButton]; //设置UI [self setupUI]; } /** * 设置一些通用属性 */ - (void)setGeneralPropetory { self.view.backgroundColor = [UIColor whiteColor]; self.automaticallyAdjustsScrollViewInsets = NO; [self.navigationController setNavigationBarHidden:NO]; [[UIApplication sharedApplication] setStatusBarHidden:YES]; } /** * 懒加载-装多张贴纸的可变数组 */ - (NSMutableArray *)pasterViewMutArr { if (!_pasterViewMutArr) { _pasterViewMutArr = [NSMutableArray array]; } return _pasterViewMutArr; } /** * 懒加载-图片数组 */ - (NSArray *)imageArray { if (!_imageArray) { NSMutableArray *mutArr = [NSMutableArray arrayWithCapacity:0]; NSArray *arr = @[@"1",@"2",@"3",@"4",@"5"]; for (NSString *imageName in arr) { UIImage *image = [UIImage imageNamed:imageName]; [mutArr addObject:image]; } _imageArray = mutArr; } return _imageArray; } /** * 懒加载-get方法设置自定义贴纸的scrollView */ - (YBPasterScrollView *)pasterScrollView { if (!_pasterScrollView) { _pasterScrollView = [[YBPasterScrollView alloc]initScrollViewWithPasterImageArray:self.imageArray]; _pasterScrollView.frame = CGRectMake(0, FULL_SCREEN_H - pasterScrollView_H - bottomButtonH, FULL_SCREEN_W, pasterScrollView_H); _pasterScrollView.backgroundColor = [UIColor lightGrayColor]; _pasterScrollView.showsHorizontalScrollIndicator = YES; _pasterScrollView.bounces = YES; _pasterScrollView.contentSize = CGSizeMake(_pasterScrollView.pasterImage_W_H * _pasterScrollView.pasterImageArray.count + inset_space * 6, pasterScrollView_H); _pasterScrollView.pasterDelegate = self; } return _pasterScrollView; } /** * 懒加载-get方法设置自定义滤镜的scrollView */ - (YBFilterScrollView *)filterScrollView { if (!_filterScrollView) { _filterScrollView = [[YBFilterScrollView alloc]initWithFrame:CGRectMake(0, FULL_SCREEN_H - pasterScrollView_H - bottomButtonH, FULL_SCREEN_W, pasterScrollView_H)]; _filterScrollView.backgroundColor = [UIColor lightGrayColor]; _filterScrollView.showsHorizontalScrollIndicator = YES; _filterScrollView.bounces = YES; NSArray *titleArray = @[@"原图",@"LOMO",@"黑白",@"复古",@"哥特",@"瑞华",@"淡雅",@"酒红",@"青柠",@"浪漫",@"光晕",@"蓝调",@"梦幻",@"夜色"]; _filterScrollView.titleArray = titleArray; _filterScrollView.filterScrollViewW = pasterScrollView_H; _filterScrollView.insert_space = inset_space*2/3; _filterScrollView.labelH = 30; _filterScrollView.originImage = self.originalImage; _filterScrollView.perButtonW_H = _filterScrollView.filterScrollViewW - 2*_filterScrollView.insert_space - 30; _filterScrollView.contentSize = CGSizeMake(_filterScrollView.perButtonW_H * titleArray.count + _filterScrollView.insert_space * (titleArray.count + 1), pasterScrollView_H); _filterScrollView.filterDelegate = self; [_filterScrollView loadScrollView]; } return _filterScrollView; } /** * 设置UI */ - (void)setupUI { //默认选中“滤镜”位置 defaultIndex = 0; UIImageView *pasterImageView = [[UIImageView alloc]initWithFrame:CGRectMake(20, 100, FULL_SCREEN_W - 40, FULL_SCREEN_W - 40)]; pasterImageView.image = self.originalImage; pasterImageView.userInteractionEnabled = YES; [self.view addSubview:pasterImageView]; self.pasterImageView = pasterImageView; UIView *bottomBackView = [[UIView alloc]initWithFrame:CGRectMake(0, FULL_SCREEN_H - bottomButtonH, FULL_SCREEN_W, bottomButtonH)]; bottomBackView.backgroundColor = [UIColor whiteColor]; [self.view addSubview:bottomBackView]; NSArray *array = @[@"滤镜",@"标签",@"贴纸"]; for (int i = 0; i < array.count; i ++) { CGFloat perButtonW = FULL_SCREEN_W/3; YBCustomButton *button = [[YBCustomButton alloc]initWithFrame:CGRectMake(perButtonW * i , 0, perButtonW, bottomButtonH)]; [button setTitle:[array objectAtIndex:i] forState:UIControlStateNormal]; [button setTitleColor:[UIColor grayColor] forState:UIControlStateNormal]; [button setTitleColor:[UIColor redColor] forState:UIControlStateSelected]; button.titleLabel.font = [UIFont systemFontOfSize:15.0]; button.tag = 5000 + i; if (i == defaultIndex) { button.selected = YES; self.bottomButton = button; } [button addTarget:self action:@selector(bottomButtonClick:) forControlEvents:UIControlEventTouchUpInside]; [bottomBackView addSubview:button]; } CGFloat lineViewW = bottomBackView.frame.size.width/6; CGFloat lineViewX = bottomBackView.frame.size.width/6 - lineViewW/2; UIView *lineView = [[UIView alloc]initWithFrame:CGRectMake(lineViewX, bottomButtonH - 3, lineViewW, 3)]; lineView.backgroundColor = [UIColor redColor]; [bottomBackView addSubview:lineView]; self.lineView = lineView; //底部“贴纸”的scrollView [self.view addSubview:self.pasterScrollView]; self.pasterScrollView.hidden = YES; self.pasterScrollView.alpha = 0.0; //底部“滤镜”的scrollView [self.view addSubview:self.filterScrollView]; } /** * 底部“滤镜”、“标签”、“贴纸”的按钮点击方法 */ - (void)bottomButtonClick:(YBCustomButton *)sender { self.bottomButton.selected = NO; sender.selected = !sender.selected; self.bottomButton = sender; // 底部的lineView转移位置 [self lineViewTransform:sender]; // 根据当前的index切换底部的scrollView [self changeDecorateImageWithButtonTag:sender]; } /** * 根据当前的index切换底部的scrollView */ - (void)changeDecorateImageWithButtonTag:(YBCustomButton *)sender { // 当前位置是贴纸 if (sender.tag - 5000 == YBImagePaster) { [UIView animateWithDuration:.5 animations:^{ self.pasterScrollView.alpha = 1.0; self.pasterScrollView.hidden = NO; if (self.pasterView) { [self.pasterView showBtn]; } }]; }else { self.pasterScrollView.hidden = YES; self.pasterScrollView.alpha = .0; if (self.pasterView) { [self.pasterView hiddenBtn]; } } // 当前位置是滤镜 if (sender.tag - 5000 == YBImageFilter) { [UIView animateWithDuration:.5 animations:^{ self.filterScrollView.alpha = 1.0; self.filterScrollView.hidden = NO; }]; } else { self.filterScrollView.hidden = YES; self.filterScrollView.alpha = .0; } } /** * 底部的lineView转移位置 */ - (void)lineViewTransform:(YBCustomButton *)sender { CGFloat sendW = sender.frame.size.width; NSInteger currentIndex = sender.tag - 5000; CGFloat lineViewH = self.lineView.frame.size.height; CGFloat lineViewX = sendW * currentIndex + sendW / 2 - self.lineView.frame.size.width/2; CGFloat lineViewY = bottomButtonH - lineViewH; CGFloat lineViewW = sendW/2; [UIView animateWithDuration:.5 animations:^{ self.lineView.frame = CGRectMake(lineViewX, lineViewY, lineViewW, lineViewH); }]; } /** * 导航栏的“完成”右键 */ - (void)setRightButton { [self initRightButtonWithButtonW:50 buttonH:50 title:@"完成" titleColor:[UIColor redColor] touchBlock:^(UIButton *rightButton) { }]; WS(weakSelf); YBWeak(YBPasterImageVC, weakMy); //按钮的点击事件封装的block weakSelf.rightBtnBlock = ^(NSString *string){ [weakSelf.pasterView hiddenBtn]; if (weakSelf.block) { if (weakSelf.pasterView != nil) { UIImage *editedImage = [weakSelf doneEdit]; weakSelf.block(editedImage); } else { weakSelf.block(weakSelf.pasterImageView.image); } [weakSelf.pasterImageView removeFromSuperview]; [weakSelf.filterScrollView removeFromSuperview]; [weakSelf.navigationController popViewControllerAnimated:YES]; } }; } /** * 图片合成 * * @return 返回合成好的图片 */ - (UIImage *)doneEdit { CGFloat org_width = self.originalImage.size.width ; CGFloat org_heigh = self.originalImage.size.height ; CGFloat rateOfScreen = org_width / org_heigh ; CGFloat inScreenH = self.pasterImageView.frame.size.width / rateOfScreen ; CGRect rect = CGRectZero ; rect.size = CGSizeMake(self.pasterImageView.frame.size.width, inScreenH) ; rect.origin = CGPointMake(0, (self.pasterImageView.frame.size.height - inScreenH) / 2) ; UIImage *imgTemp = [UIImage getImageFromView:self.pasterImageView] ; UIImage *imgCut = [UIImage squareImageFromImage:imgTemp scaledToSize:rect.size.width] ; return imgCut ; } #pragma mark - YBPasterScrollViewDelegate - (void)pasterTag:(NSInteger)pasterTag pasterImage:(UIImage *)pasterImage { if (self.pasterView) { [self.pasterView removeFromSuperview]; self.pasterView = nil; } YBPasterView *pasterView = [[YBPasterView alloc]initWithFrame:CGRectMake(0, 0, defaultPasterViewW_H, defaultPasterViewW_H)]; pasterView.center = CGPointMake(self.pasterImageView.frame.size.width/2, self.pasterImageView.frame.size.height/2); pasterView.pasterImage = pasterImage; pasterView.delegate = self; [self.pasterImageView addSubview:pasterView]; self.pasterView = pasterView; //[self.pasterViewMutArr addObject:pasterView]; //NSLog(@"%lu",(unsigned long)self.pasterViewMutArr.count); } #pragma mark - YBFilterScrollViewDelegate - (void)filterImage:(UIImage *)editedImage { self.pasterImageView.image = editedImage; } /** * 测试有返回值的代理 */ - (NSString *)deliverStr:(NSString *)originalStr { NSString *string; string = originalStr; return string; } #pragma mark - YBPasterViewDelegate - (void)deleteThePaster { self.pasterScrollView.defaultButton.selected = NO; self.pasterScrollView.defaultButton.layer.borderColor = [UIColor clearColor].CGColor; self.pasterScrollView.defaultButton.layer.borderWidth = 0.1; self.pasterView = nil; } #pragma clang diagnostic pop @end ================================================ FILE: testPasterImage/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: testPasterImage/Libs/FilterImageLibs/ColorMatrix.h ================================================ // // RootViewController.h // pictureProcess // // Created by Ibokan on 12-9-7. // Copyright (c) 2012年 __MyCompanyName__. All rights reserved. // // 1、LOMO const float colormatrix_lomo[] = { 1.7f, 0.1f, 0.1f, 0, -73.1f, 0, 1.7f, 0.1f, 0, -73.1f, 0, 0.1f, 1.6f, 0, -73.1f, 0, 0, 0, 1.0f, 0 }; // 2、黑白 const float colormatrix_heibai[] = { 0.8f, 1.6f, 0.2f, 0, -163.9f, 0.8f, 1.6f, 0.2f, 0, -163.9f, 0.8f, 1.6f, 0.2f, 0, -163.9f, 0, 0, 0, 1.0f, 0 }; // 3、复古 const float colormatrix_huajiu[] = { 0.2f,0.5f, 0.1f, 0, 40.8f, 0.2f, 0.5f, 0.1f, 0, 40.8f, 0.2f,0.5f, 0.1f, 0, 40.8f, 0, 0, 0, 1, 0 }; // 4、哥特 const float colormatrix_gete[] = { 1.9f,-0.3f, -0.2f, 0,-87.0f, -0.2f, 1.7f, -0.1f, 0, -87.0f, -0.1f,-0.6f, 2.0f, 0, -87.0f, 0, 0, 0, 1.0f, 0 }; // 5、锐化 const float colormatrix_ruise[] = { 4.8f,-1.0f, -0.1f, 0,-388.4f, -0.5f,4.4f, -0.1f, 0,-388.4f, -0.5f,-1.0f, 5.2f, 0,-388.4f, 0, 0, 0, 1.0f, 0 }; // 6、淡雅 const float colormatrix_danya[] = { 0.6f,0.3f, 0.1f, 0,73.3f, 0.2f,0.7f, 0.1f, 0,73.3f, 0.2f,0.3f, 0.4f, 0,73.3f, 0, 0, 0, 1.0f, 0 }; // 7、酒红 const float colormatrix_jiuhong[] = { 1.2f,0.0f, 0.0f, 0.0f,0.0f, 0.0f,0.9f, 0.0f, 0.0f,0.0f, 0.0f,0.0f, 0.8f, 0.0f,0.0f, 0, 0, 0, 1.0f, 0 }; // 8、清宁 const float colormatrix_qingning[] = { 0.9f, 0, 0, 0, 0, 0, 1.1f,0, 0, 0, 0, 0, 0.9f, 0, 0, 0, 0, 0, 1.0f, 0 }; // 9、浪漫 const float colormatrix_langman[] = { 0.9f, 0, 0, 0, 63.0f, 0, 0.9f,0, 0, 63.0f, 0, 0, 0.9f, 0, 63.0f, 0, 0, 0, 1.0f, 0 }; // 10、光晕 const float colormatrix_guangyun[] = { 0.9f, 0, 0, 0, 64.9f, 0, 0.9f,0, 0, 64.9f, 0, 0, 0.9f, 0, 64.9f, 0, 0, 0, 1.0f, 0 }; // 11、蓝调 const float colormatrix_landiao[] = { 2.1f, -1.4f, 0.6f, 0.0f, -31.0f, -0.3f, 2.0f, -0.3f, 0.0f, -31.0f, -1.1f, -0.2f, 2.6f, 0.0f, -31.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f }; // 12、梦幻 const float colormatrix_menghuan[] = { 0.8f, 0.3f, 0.1f, 0.0f, 46.5f, 0.1f, 0.9f, 0.0f, 0.0f, 46.5f, 0.1f, 0.3f, 0.7f, 0.0f, 46.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f }; // 13、夜色 const float colormatrix_yese[] = { 1.0f, 0.0f, 0.0f, 0.0f, -66.6f, 0.0f, 1.1f, 0.0f, 0.0f, -66.6f, 0.0f, 0.0f, 1.0f, 0.0f, -66.6f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f }; ================================================ FILE: testPasterImage/Libs/FilterImageLibs/ImageUtil.h ================================================ // // RootViewController.h // pictureProcess // // Created by Ibokan on 12-9-7. // Copyright (c) 2012年 __MyCompanyName__. All rights reserved. // #import #import #import #import @interface ImageUtil : NSObject + (UIImage *)imageWithImage:(UIImage*)inImage withColorMatrix:(const float*)f; @end ================================================ FILE: testPasterImage/Libs/FilterImageLibs/ImageUtil.m ================================================ // // RootViewController.h // pictureProcess // // Created by Ibokan on 12-9-7. // Copyright (c) 2012年 __MyCompanyName__. All rights reserved. // #import "ImageUtil.h" @implementation ImageUtil static CGContextRef CreateRGBABitmapContext (CGImageRef inImage)// 返回一个使用RGBA通道的位图上下文 { CGContextRef context = NULL; CGColorSpaceRef colorSpace; void *bitmapData; //内存空间的指针,该内存空间的大小等于图像使用RGB通道所占用的字节数。 unsigned long bitmapByteCount; unsigned long bitmapBytesPerRow; size_t pixelsWide = CGImageGetWidth(inImage); //获取横向的像素点的个数 size_t pixelsHigh = CGImageGetHeight(inImage); //纵向 bitmapBytesPerRow = (pixelsWide * 4); //每一行的像素点占用的字节数,每个像素点的ARGB四个通道各占8个bit(0-255)的空间 bitmapByteCount = (bitmapBytesPerRow * pixelsHigh); //计算整张图占用的字节数 colorSpace = CGColorSpaceCreateDeviceRGB();//创建依赖于设备的RGB通道 bitmapData = malloc(bitmapByteCount); //分配足够容纳图片字节数的内存空间 context = CGBitmapContextCreate (bitmapData, pixelsWide, pixelsHigh, 8, bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast); //创建CoreGraphic的图形上下文,该上下文描述了bitmaData指向的内存空间需要绘制的图像的一些绘制参数 CGColorSpaceRelease( colorSpace ); //Core Foundation中通过含有Create、Alloc的方法名字创建的指针,需要使用CFRelease()函数释放 return context; } static unsigned char *RequestImagePixelData(UIImage *inImage) // 返回一个指针,该指针指向一个数组,数组中的每四个元素都是图像上的一个像素点的RGBA的数值(0-255),用无符号的char是因为它正好的取值范围就是0-255 { CGImageRef img = [inImage CGImage]; CGSize size = [inImage size]; CGContextRef cgctx = CreateRGBABitmapContext(img); //使用上面的函数创建上下文 CGRect rect = {{0,0},{size.width, size.height}}; CGContextDrawImage(cgctx, rect, img); //将目标图像绘制到指定的上下文,实际为上下文内的bitmapData。 unsigned char *data = CGBitmapContextGetData (cgctx); CGContextRelease(cgctx);//释放上面的函数创建的上下文 return data; } static void changeRGBA(int *red,int *green,int *blue,int *alpha, const float* f)//修改RGB的值 { int redV = *red; int greenV = *green; int blueV = *blue; int alphaV = *alpha; *red = f[0] * redV + f[1] * greenV + f[2] * blueV + f[3] * alphaV + f[4]; *green = f[0+5] * redV + f[1+5] * greenV + f[2+5] * blueV + f[3+5] * alphaV + f[4+5]; *blue = f[0+5*2] * redV + f[1+5*2] * greenV + f[2+5*2] * blueV + f[3+5*2] * alphaV + f[4+5*2]; *alpha = f[0+5*3] * redV + f[1+5*3] * greenV + f[2+5*3] * blueV + f[3+5*3] * alphaV + f[4+5*3]; if (*red > 255) { *red = 255; } if(*red < 0) { *red = 0; } if (*green > 255) { *green = 255; } if (*green < 0) { *green = 0; } if (*blue > 255) { *blue = 255; } if (*blue < 0) { *blue = 0; } if (*alpha > 255) { *alpha = 255; } if (*alpha < 0) { *alpha = 0; } } + (UIImage*)imageWithImage:(UIImage*)inImage withColorMatrix:(const float*) f { unsigned char *imgPixel = RequestImagePixelData(inImage); CGImageRef inImageRef = [inImage CGImage]; size_t w = CGImageGetWidth(inImageRef); size_t h = CGImageGetHeight(inImageRef); int wOff = 0; int pixOff = 0; for(GLuint y = 0;y< h;y++)//双层循环按照长宽的像素个数迭代每个像素点 { pixOff = wOff; for (GLuint x = 0; x @interface UIImage (CS_Extensions) - (UIImage *)imageAtRect:(CGRect)rect; - (UIImage *)imageByScalingProportionallyToMinimumSize:(CGSize)targetSize; - (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize; - (UIImage *)imageByScalingToSize:(CGSize)targetSize; - (UIImage *)imageRotatedByRadians:(CGFloat)radians; - (UIImage *)imageRotatedByDegrees:(CGFloat)degrees; - (UIImage *)imageFlipUpDown; - (UIImage *)combineUIImage:(UIImage *)anotherImage; - (UIImage *)addText:(UIImage *)img text:(NSString *)text1; - (UIImage *)addImage:(UIImage *)image1 toImage:(UIImage *)image2; @end; ================================================ FILE: testPasterImage/Libs/FilterImageLibs/UIImage-Extensions/.svn/pristine/74/7403967df71a9ffaa67500af6a610523742bfd53.svn-base ================================================ // // UIImage+SplitImageIntoTwoParts.h // TapRepublic // // Created by Terry Lin on 12-5-11. // Copyright (c) 2012年 __MyCompanyName__. All rights reserved. // #import @interface UIImage (SplitImageIntoTwoParts) + (NSArray*)splitImageIntoTwoParts:(UIImage*)image; @end ================================================ FILE: testPasterImage/Libs/FilterImageLibs/UIImage-Extensions/.svn/pristine/9e/9e08c4f172f233df24ad098fd5059cdaf5ad8268.svn-base ================================================ // // UIImage+SplitImageIntoTwoParts.m // TapRepublic // // Created by Terry Lin on 12-5-11. // Copyright (c) 2012年 __MyCompanyName__. All rights reserved. // #define SAWTOOTH_COUNT 10 #define SAWTOOTH_WIDTH_FACTOR 20 #import "UIImage+SplitImageIntoTwoParts.h" @implementation UIImage (SplitImageIntoTwoParts) +(NSArray *)splitImageIntoTwoParts:(UIImage *)image { CGFloat scale = [[UIScreen mainScreen] scale]; NSMutableArray *array = [NSMutableArray arrayWithCapacity:2]; CGFloat width,height,widthgap,heightgap; int piceCount = SAWTOOTH_COUNT; width = image.size.width; height = image.size.height; widthgap = width/SAWTOOTH_WIDTH_FACTOR; heightgap = height/piceCount; // CGRect rect = CGRectMake(0, 0, width, height); CGContextRef context; CGImageRef imageMasked; UIImage *leftImage,*rightImage; //part one UIGraphicsBeginImageContext(CGSizeMake(width*scale, height*scale)); context = UIGraphicsGetCurrentContext(); CGContextScaleCTM(context, scale, scale); CGContextMoveToPoint(context, 0, 0); int a=-1; for (int i=0; i oldsize.width/oldsize.height) { rect.size.width = asize.width; rect.size.height = asize.width*oldsize.height/oldsize.width; rect.origin.x = 0; rect.origin.y = (asize.height - rect.size.height)/2; } else{ rect.size.width = asize.height*oldsize.width/oldsize.height; rect.size.height = asize.height; rect.origin.x = (asize.width - rect.size.width)/2; rect.origin.y = 0; } UIGraphicsBeginImageContext(asize); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextClipToRect(context, CGRectMake(0, 0, asize.width, asize.height)); CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]); UIRectFill(CGRectMake(0, 0, asize.width, asize.height));//clear background [image drawInRect:rect]; newimage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); } return newimage; } - (UIImage *)clipImageWithScaleWithsize:(CGSize)asize roundedCornerImage:(NSInteger)roundedCornerImage borderSize:(NSInteger)borderSize { UIImage *image = [self clipImageWithScaleWithsize:asize]; return [image roundedCornerImage:roundedCornerImage borderSize:borderSize]; } @end ================================================ FILE: testPasterImage/Libs/FilterImageLibs/UIImage-Extensions/.svn/pristine/c8/c8496f35a02cbd4ef1b2a81af9b5ca802b339a3a.svn-base ================================================ // // UIImage-Extensions.m // // Created by Hardy Macia on 7/1/09. // Copyright 2009 Catamount Software. All rights reserved. // #import "UIImage-Extensions.h" CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;}; CGFloat RadiansToDegrees(CGFloat radians) {return radians * 180/M_PI;}; @implementation UIImage (CS_Extensions) -(UIImage *)imageAtRect:(CGRect)rect { CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], rect); UIImage* subImage = [UIImage imageWithCGImage:imageRef]; CGImageRelease(imageRef); return subImage; } - (UIImage *)imageByScalingProportionallyToMinimumSize:(CGSize)targetSize { UIImage *sourceImage = self; UIImage *newImage = nil; CGSize imageSize = sourceImage.size; CGFloat width = imageSize.width; CGFloat height = imageSize.height; CGFloat targetWidth = targetSize.width; CGFloat targetHeight = targetSize.height; CGFloat scaleFactor = 0.0; CGFloat scaledWidth = targetWidth; CGFloat scaledHeight = targetHeight; CGPoint thumbnailPoint = CGPointMake(0.0,0.0); if (CGSizeEqualToSize(imageSize, targetSize) == NO) { CGFloat widthFactor = targetWidth / width; CGFloat heightFactor = targetHeight / height; if (widthFactor > heightFactor) scaleFactor = widthFactor; else scaleFactor = heightFactor; scaledWidth = width * scaleFactor; scaledHeight = height * scaleFactor; // center the image if (widthFactor > heightFactor) { thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; } else if (widthFactor < heightFactor) { thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5; } } // this is actually the interesting part: UIGraphicsBeginImageContext(targetSize); CGRect thumbnailRect = CGRectZero; thumbnailRect.origin = thumbnailPoint; thumbnailRect.size.width = scaledWidth; thumbnailRect.size.height = scaledHeight; [sourceImage drawInRect:thumbnailRect]; newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); if(newImage == nil) DLog(@"could not scale image"); return newImage ; } - (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize { UIImage *sourceImage = self; UIImage *newImage = nil; CGSize imageSize = sourceImage.size; CGFloat width = imageSize.width; CGFloat height = imageSize.height; CGFloat targetWidth = targetSize.width; CGFloat targetHeight = targetSize.height; CGFloat scaleFactor = 0.0; CGFloat scaledWidth = targetWidth; CGFloat scaledHeight = targetHeight; CGPoint thumbnailPoint = CGPointMake(0.0,0.0); if (CGSizeEqualToSize(imageSize, targetSize) == NO) { CGFloat widthFactor = targetWidth / width; CGFloat heightFactor = targetHeight / height; if (widthFactor < heightFactor) scaleFactor = widthFactor; else scaleFactor = heightFactor; scaledWidth = width * scaleFactor; scaledHeight = height * scaleFactor; // center the image if (widthFactor < heightFactor) { thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; } else if (widthFactor > heightFactor) { thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5; } } // this is actually the interesting part: UIGraphicsBeginImageContext(targetSize); CGRect thumbnailRect = CGRectZero; thumbnailRect.origin = thumbnailPoint; thumbnailRect.size.width = scaledWidth; thumbnailRect.size.height = scaledHeight; //NSLog(@"thumbmail rect: %@", NSStringFromCGRect(thumbnailRect)); [sourceImage drawInRect:thumbnailRect]; newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); if(newImage == nil) DLog(@"could not scale image"); return newImage ; } - (UIImage *)imageByScalingToSize:(CGSize)targetSize { UIImage *sourceImage = self; UIImage *newImage = nil; // CGSize imageSize = sourceImage.size; // CGFloat width = imageSize.width; // CGFloat height = imageSize.height; CGFloat targetWidth = targetSize.width; CGFloat targetHeight = targetSize.height; // CGFloat scaleFactor = 0.0; CGFloat scaledWidth = targetWidth; CGFloat scaledHeight = targetHeight; CGPoint thumbnailPoint = CGPointMake(0.0,0.0); // this is actually the interesting part: UIGraphicsBeginImageContext(targetSize); CGRect thumbnailRect = CGRectZero; thumbnailRect.origin = thumbnailPoint; thumbnailRect.size.width = scaledWidth; thumbnailRect.size.height = scaledHeight; [sourceImage drawInRect:thumbnailRect]; newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); if(newImage == nil) DLog(@"could not scale image"); return newImage ; } - (UIImage *)imageRotatedByRadians:(CGFloat)radians { return [self imageRotatedByDegrees:RadiansToDegrees(radians)]; } - (UIImage *)imageRotatedByDegrees:(CGFloat)degrees { // calculate the size of the rotated view's containing box for our drawing space UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.size.width, self.size.height)]; CGAffineTransform t = CGAffineTransformMakeRotation(DegreesToRadians(degrees)); rotatedViewBox.transform = t; CGSize rotatedSize = rotatedViewBox.frame.size; [rotatedViewBox release]; // Create the bitmap context UIGraphicsBeginImageContext(rotatedSize); CGContextRef bitmap = UIGraphicsGetCurrentContext(); // Move the origin to the middle of the image so we will rotate and scale around the center. CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2); // // Rotate the image context CGContextRotateCTM(bitmap, DegreesToRadians(degrees)); // Now, draw the rotated/scaled image into the context CGContextScaleCTM(bitmap, 1.0, -1.0); CGContextDrawImage(bitmap, CGRectMake(-self.size.width / 2, -self.size.height / 2, self.size.width, self.size.height), [self CGImage]); UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; } -(UIImage *)imageFlipUpDown { UIGraphicsBeginImageContext(self.size); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextDrawImage(context, CGRectMake(0, 0, self.size.width, self.size.height), self.CGImage); CGAffineTransform transform = CGAffineTransformIdentity; transform = CGAffineTransformMakeTranslation(0.0, self.size.height); transform = CGAffineTransformScale(transform, 1.0, -1.0); CGContextConcatCTM(context, transform); UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return imageCopy; } -(UIImage *)combineUIImage:(UIImage *)anotherImage { NSInteger width = self.size.width + anotherImage.size.width; NSInteger height = self.size.height < anotherImage.size.height ? anotherImage.size.height : self.size.height; UIGraphicsBeginImageContext(CGSizeMake(width, height)); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetFillColorWithColor(context, [[UIColor lightGrayColor] CGColor]); CGContextFillRect(context, CGRectMake(0, 0, width, height)); NSInteger xPos = 0; NSInteger yPos = 0; if (self.size.height < height) { yPos = (height - self.size.height) / 2; } CGContextDrawImage(context, CGRectMake(xPos, yPos, self.size.width, self.size.height), self.CGImage); xPos = self.size.width; yPos = 0; if (anotherImage.size.height < height) { yPos = (height - anotherImage.size.height) / 2; } CGContextDrawImage(context, CGRectMake(xPos, yPos, anotherImage.size.width, anotherImage.size.height), anotherImage.CGImage); UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return [imageCopy imageFlipUpDown]; } -(UIImage *)addText:(UIImage *)img text:(NSString *)text1 { int w = img.size.width; int h = img.size.height; //lon = h - lon; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst); CGContextDrawImage(context, CGRectMake(0, 0, w, h), img.CGImage); CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1); char* text = (char *)[text1 cStringUsingEncoding:NSASCIIStringEncoding];// "05/05/09"; CGContextSelectFont(context, "Arial", 12, kCGEncodingMacRoman); CGContextSetTextDrawingMode(context, kCGTextFill); CGContextSetRGBFillColor(context, 255, 255, 255, 1); //rotate text /* CGContextSetTextMatrix(context, CGAffineTransformMakeRotation( -M_PI/4 )); */ CGContextShowTextAtPoint(context, 4, 4, text, strlen(text)); CGImageRef imageMasked = CGBitmapContextCreateImage(context); CGContextRelease(context); CGColorSpaceRelease(colorSpace); UIImage *newImage = [UIImage imageWithCGImage:imageMasked]; CGImageRelease(imageMasked); return newImage; } - (UIImage *)addImage:(UIImage *)image1 toImage:(UIImage *)image2 { UIGraphicsBeginImageContext(image1.size); // Draw image1 [image1 drawInRect:CGRectMake(0, 0, image1.size.width, image1.size.height)]; // Draw image2 [image2 drawInRect:CGRectMake(0, 0, image2.size.width, image2.size.height)]; UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return resultingImage; } @end; ================================================ FILE: testPasterImage/Libs/FilterImageLibs/UIImage-Extensions/.svn/pristine/d8/d878290233a5ccddb800ee8a4f409b373e187859.svn-base ================================================ // // UIImage+Cut.h // MeiJiaLove // // Created by Wu.weibin on 13-5-17. // Copyright (c) 2013年 Wu.weibin. All rights reserved. // #import @interface UIImage (Cut) - (UIImage *)clipImageWithScaleWithsize:(CGSize)asize; - (UIImage *)clipImageWithScaleWithsize:(CGSize)asize roundedCornerImage:(NSInteger)roundedCornerImage borderSize:(NSInteger)borderSize; @end ================================================ FILE: testPasterImage/Libs/FilterImageLibs/UIImage-Extensions/.svn/pristine/dc/dc06ddf7d7a2ad296ab0a741fcc7c3bc6d34b0e3.svn-base ================================================ // UIImage+Resize.m // Created by Trevor Harmon on 8/5/09. // Free for personal or commercial use, with or without modification. // No warranty is expressed or implied. #import "UIImage+Resize.h" #import "UIImage+RoundedCorner.h" #import "UIImage+Alpha.h" @implementation UIImage (Resize) // Returns a copy of this image that is cropped to the given bounds. // The bounds will be adjusted using CGRectIntegral. // This method ignores the image's imageOrientation setting. - (UIImage *)croppedImage:(CGRect)bounds { CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], bounds); UIImage *croppedImage = [UIImage imageWithCGImage:imageRef]; CGImageRelease(imageRef); return croppedImage; } // Returns a copy of this image that is squared to the thumbnail size. // If transparentBorder is non-zero, a transparent border of the given size will be added around the edges of the thumbnail. (Adding a transparent border of at least one pixel in size has the side-effect of antialiasing the edges of the image when rotating it using Core Animation.) - (UIImage *)thumbnailImage:(NSInteger)thumbnailSize transparentBorder:(NSUInteger)borderSize cornerRadius:(NSUInteger)cornerRadius interpolationQuality:(CGInterpolationQuality)quality { UIImage *resizedImage = [self resizedImageWithContentMode:UIViewContentModeScaleAspectFill bounds:CGSizeMake(thumbnailSize, thumbnailSize) interpolationQuality:quality]; // Crop out any part of the image that's larger than the thumbnail size // The cropped rect must be centered on the resized image // Round the origin points so that the size isn't altered when CGRectIntegral is later invoked CGRect cropRect = CGRectMake(round((resizedImage.size.width - thumbnailSize) / 2), round((resizedImage.size.height - thumbnailSize) / 2), thumbnailSize, thumbnailSize); UIImage *croppedImage = [resizedImage croppedImage:cropRect]; UIImage *transparentBorderImage = borderSize ? [croppedImage transparentBorderImage:borderSize] : croppedImage; return [transparentBorderImage roundedCornerImage:cornerRadius borderSize:borderSize]; } // Returns a rescaled copy of the image, taking into account its orientation // The image will be scaled disproportionately if necessary to fit the bounds specified by the parameter - (UIImage *)resizedImage:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)quality { BOOL drawTransposed; switch (self.imageOrientation) { case UIImageOrientationLeft: case UIImageOrientationLeftMirrored: case UIImageOrientationRight: case UIImageOrientationRightMirrored: drawTransposed = YES; break; default: drawTransposed = NO; } return [self resizedImage:newSize transform:[self transformForOrientation:newSize] drawTransposed:drawTransposed interpolationQuality:quality]; } // Resizes the image according to the given content mode, taking into account the image's orientation - (UIImage *)resizedImageWithContentMode:(UIViewContentMode)contentMode bounds:(CGSize)bounds interpolationQuality:(CGInterpolationQuality)quality { CGFloat horizontalRatio = bounds.width / self.size.width; CGFloat verticalRatio = bounds.height / self.size.height; CGFloat ratio; switch (contentMode) { case UIViewContentModeScaleAspectFill: ratio = MAX(horizontalRatio, verticalRatio); break; case UIViewContentModeScaleAspectFit: ratio = MIN(horizontalRatio, verticalRatio); break; default: [NSException raise:NSInvalidArgumentException format:@"Unsupported content mode: %d", contentMode]; } CGSize newSize = CGSizeMake(self.size.width * ratio, self.size.height * ratio); return [self resizedImage:newSize interpolationQuality:quality]; } #pragma mark - #pragma mark Private helper methods // Returns a copy of the image that has been transformed using the given affine transform and scaled to the new size // The new image's orientation will be UIImageOrientationUp, regardless of the current image's orientation // If the new size is not integral, it will be rounded up - (UIImage *)resizedImage:(CGSize)newSize transform:(CGAffineTransform)transform drawTransposed:(BOOL)transpose interpolationQuality:(CGInterpolationQuality)quality { CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height)); CGRect transposedRect = CGRectMake(0, 0, newRect.size.height, newRect.size.width); CGImageRef imageRef = self.CGImage; // Build a context that's the same dimensions as the new size CGContextRef bitmap = CGBitmapContextCreate(NULL, newRect.size.width, newRect.size.height, CGImageGetBitsPerComponent(imageRef), 0, CGImageGetColorSpace(imageRef), CGImageGetBitmapInfo(imageRef)); // Rotate and/or flip the image if required by its orientation CGContextConcatCTM(bitmap, transform); // Set the quality level to use when rescaling CGContextSetInterpolationQuality(bitmap, quality); // Draw into the context; this scales the image CGContextDrawImage(bitmap, transpose ? transposedRect : newRect, imageRef); // Get the resized image from the context and a UIImage CGImageRef newImageRef = CGBitmapContextCreateImage(bitmap); UIImage *newImage = [UIImage imageWithCGImage:newImageRef]; // Clean up CGContextRelease(bitmap); CGImageRelease(newImageRef); return newImage; } // Returns an affine transform that takes into account the image orientation when drawing a scaled image - (CGAffineTransform)transformForOrientation:(CGSize)newSize { CGAffineTransform transform = CGAffineTransformIdentity; switch (self.imageOrientation) { case UIImageOrientationDown: // EXIF = 3 case UIImageOrientationDownMirrored: // EXIF = 4 transform = CGAffineTransformTranslate(transform, newSize.width, newSize.height); transform = CGAffineTransformRotate(transform, M_PI); break; case UIImageOrientationLeft: // EXIF = 6 case UIImageOrientationLeftMirrored: // EXIF = 5 transform = CGAffineTransformTranslate(transform, newSize.width, 0); transform = CGAffineTransformRotate(transform, M_PI_2); break; case UIImageOrientationRight: // EXIF = 8 case UIImageOrientationRightMirrored: // EXIF = 7 transform = CGAffineTransformTranslate(transform, 0, newSize.height); transform = CGAffineTransformRotate(transform, -M_PI_2); break; default: break; } switch (self.imageOrientation) { case UIImageOrientationUpMirrored: // EXIF = 2 case UIImageOrientationDownMirrored: // EXIF = 4 transform = CGAffineTransformTranslate(transform, newSize.width, 0); transform = CGAffineTransformScale(transform, -1, 1); break; case UIImageOrientationLeftMirrored: // EXIF = 5 case UIImageOrientationRightMirrored: // EXIF = 7 transform = CGAffineTransformTranslate(transform, newSize.height, 0); transform = CGAffineTransformScale(transform, -1, 1); break; default: break; } return transform; } @end ================================================ FILE: testPasterImage/Libs/FilterImageLibs/UIImage-Extensions/.svn/pristine/ee/ee255ad5f9f4f575fb733f734606d7eb9e0efeac.svn-base ================================================ // UIImage+Alpha.m // Created by Trevor Harmon on 9/20/09. // Free for personal or commercial use, with or without modification. // No warranty is expressed or implied. #import "UIImage+Alpha.h" @implementation UIImage (Alpha) // Returns true if the image has an alpha layer - (BOOL)hasAlpha { CGImageAlphaInfo alpha = CGImageGetAlphaInfo(self.CGImage); return (alpha == kCGImageAlphaFirst || alpha == kCGImageAlphaLast || alpha == kCGImageAlphaPremultipliedFirst || alpha == kCGImageAlphaPremultipliedLast); } // Returns a copy of the given image, adding an alpha channel if it doesn't already have one - (UIImage *)imageWithAlpha { if ([self hasAlpha]) { return self; } CGImageRef imageRef = self.CGImage; size_t width = CGImageGetWidth(imageRef); size_t height = CGImageGetHeight(imageRef); // The bitsPerComponent and bitmapInfo values are hard-coded to prevent an "unsupported parameter combination" error CGContextRef offscreenContext = CGBitmapContextCreate(NULL, width, height, 8, 0, CGImageGetColorSpace(imageRef), kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst); // Draw the image into the context and retrieve the new image, which will now have an alpha layer CGContextDrawImage(offscreenContext, CGRectMake(0, 0, width, height), imageRef); CGImageRef imageRefWithAlpha = CGBitmapContextCreateImage(offscreenContext); UIImage *imageWithAlpha = [UIImage imageWithCGImage:imageRefWithAlpha]; // Clean up CGContextRelease(offscreenContext); CGImageRelease(imageRefWithAlpha); return imageWithAlpha; } // Returns a copy of the image with a transparent border of the given size added around its edges. // If the image has no alpha layer, one will be added to it. - (UIImage *)transparentBorderImage:(NSUInteger)borderSize { // If the image does not have an alpha layer, add one UIImage *image = [self imageWithAlpha]; CGRect newRect = CGRectMake(0, 0, image.size.width + borderSize * 2, image.size.height + borderSize * 2); // Build a context that's the same dimensions as the new size CGContextRef bitmap = CGBitmapContextCreate(NULL, newRect.size.width, newRect.size.height, CGImageGetBitsPerComponent(self.CGImage), 0, CGImageGetColorSpace(self.CGImage), CGImageGetBitmapInfo(self.CGImage)); // Draw the image in the center of the context, leaving a gap around the edges CGRect imageLocation = CGRectMake(borderSize, borderSize, image.size.width, image.size.height); CGContextDrawImage(bitmap, imageLocation, self.CGImage); CGImageRef borderImageRef = CGBitmapContextCreateImage(bitmap); // Create a mask to make the border transparent, and combine it with the image CGImageRef maskImageRef = [self newBorderMask:borderSize size:newRect.size]; CGImageRef transparentBorderImageRef = CGImageCreateWithMask(borderImageRef, maskImageRef); UIImage *transparentBorderImage = [UIImage imageWithCGImage:transparentBorderImageRef]; // Clean up CGContextRelease(bitmap); CGImageRelease(borderImageRef); CGImageRelease(maskImageRef); CGImageRelease(transparentBorderImageRef); return transparentBorderImage; } #pragma mark - #pragma mark Private helper methods // Creates a mask that makes the outer edges transparent and everything else opaque // The size must include the entire mask (opaque part + transparent border) // The caller is responsible for releasing the returned reference by calling CGImageRelease - (CGImageRef)newBorderMask:(NSUInteger)borderSize size:(CGSize)size { CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); // Build a context that's the same dimensions as the new size CGContextRef maskContext = CGBitmapContextCreate(NULL, size.width, size.height, 8, // 8-bit grayscale 0, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaNone); // Start with a mask that's entirely transparent CGContextSetFillColorWithColor(maskContext, [UIColor blackColor].CGColor); CGContextFillRect(maskContext, CGRectMake(0, 0, size.width, size.height)); // Make the inner part (within the border) opaque CGContextSetFillColorWithColor(maskContext, [UIColor whiteColor].CGColor); CGContextFillRect(maskContext, CGRectMake(borderSize, borderSize, size.width - borderSize * 2, size.height - borderSize * 2)); // Get an image of the context CGImageRef maskImageRef = CGBitmapContextCreateImage(maskContext); // Clean up CGContextRelease(maskContext); CGColorSpaceRelease(colorSpace); return maskImageRef; } @end ================================================ FILE: testPasterImage/Libs/FilterImageLibs/UIImage-Extensions/UIImage+Alpha.h ================================================ // UIImage+Alpha.h // Created by Trevor Harmon on 9/20/09. // Free for personal or commercial use, with or without modification. // No warranty is expressed or implied. // Helper methods for adding an alpha layer to an image #import @interface UIImage (Alpha) - (BOOL)hasAlpha; - (UIImage *)imageWithAlpha; - (UIImage *)transparentBorderImage:(NSUInteger)borderSize; - (CGImageRef)newBorderMask:(NSUInteger)borderSize size:(CGSize)size; @end ================================================ FILE: testPasterImage/Libs/FilterImageLibs/UIImage-Extensions/UIImage+Alpha.m ================================================ // UIImage+Alpha.m // Created by Trevor Harmon on 9/20/09. // Free for personal or commercial use, with or without modification. // No warranty is expressed or implied. #import "UIImage+Alpha.h" @implementation UIImage (Alpha) // Returns true if the image has an alpha layer - (BOOL)hasAlpha { CGImageAlphaInfo alpha = CGImageGetAlphaInfo(self.CGImage); return (alpha == kCGImageAlphaFirst || alpha == kCGImageAlphaLast || alpha == kCGImageAlphaPremultipliedFirst || alpha == kCGImageAlphaPremultipliedLast); } // Returns a copy of the given image, adding an alpha channel if it doesn't already have one - (UIImage *)imageWithAlpha { if ([self hasAlpha]) { return self; } CGImageRef imageRef = self.CGImage; size_t width = CGImageGetWidth(imageRef); size_t height = CGImageGetHeight(imageRef); // The bitsPerComponent and bitmapInfo values are hard-coded to prevent an "unsupported parameter combination" error CGContextRef offscreenContext = CGBitmapContextCreate(NULL, width, height, 8, 0, CGImageGetColorSpace(imageRef), kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst); // Draw the image into the context and retrieve the new image, which will now have an alpha layer CGContextDrawImage(offscreenContext, CGRectMake(0, 0, width, height), imageRef); CGImageRef imageRefWithAlpha = CGBitmapContextCreateImage(offscreenContext); UIImage *imageWithAlpha = [UIImage imageWithCGImage:imageRefWithAlpha]; // Clean up CGContextRelease(offscreenContext); CGImageRelease(imageRefWithAlpha); return imageWithAlpha; } // Returns a copy of the image with a transparent border of the given size added around its edges. // If the image has no alpha layer, one will be added to it. - (UIImage *)transparentBorderImage:(NSUInteger)borderSize { // If the image does not have an alpha layer, add one UIImage *image = [self imageWithAlpha]; CGRect newRect = CGRectMake(0, 0, image.size.width + borderSize * 2, image.size.height + borderSize * 2); // Build a context that's the same dimensions as the new size CGContextRef bitmap = CGBitmapContextCreate(NULL, newRect.size.width, newRect.size.height, CGImageGetBitsPerComponent(self.CGImage), 0, CGImageGetColorSpace(self.CGImage), CGImageGetBitmapInfo(self.CGImage)); // Draw the image in the center of the context, leaving a gap around the edges CGRect imageLocation = CGRectMake(borderSize, borderSize, image.size.width, image.size.height); CGContextDrawImage(bitmap, imageLocation, self.CGImage); CGImageRef borderImageRef = CGBitmapContextCreateImage(bitmap); // Create a mask to make the border transparent, and combine it with the image CGImageRef maskImageRef = [self newBorderMask:borderSize size:newRect.size]; CGImageRef transparentBorderImageRef = CGImageCreateWithMask(borderImageRef, maskImageRef); UIImage *transparentBorderImage = [UIImage imageWithCGImage:transparentBorderImageRef]; // Clean up CGContextRelease(bitmap); CGImageRelease(borderImageRef); CGImageRelease(maskImageRef); CGImageRelease(transparentBorderImageRef); return transparentBorderImage; } #pragma mark - #pragma mark Private helper methods // Creates a mask that makes the outer edges transparent and everything else opaque // The size must include the entire mask (opaque part + transparent border) // The caller is responsible for releasing the returned reference by calling CGImageRelease - (CGImageRef)newBorderMask:(NSUInteger)borderSize size:(CGSize)size { CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); // Build a context that's the same dimensions as the new size CGContextRef maskContext = CGBitmapContextCreate(NULL, size.width, size.height, 8, // 8-bit grayscale 0, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaNone); // Start with a mask that's entirely transparent CGContextSetFillColorWithColor(maskContext, [UIColor blackColor].CGColor); CGContextFillRect(maskContext, CGRectMake(0, 0, size.width, size.height)); // Make the inner part (within the border) opaque CGContextSetFillColorWithColor(maskContext, [UIColor whiteColor].CGColor); CGContextFillRect(maskContext, CGRectMake(borderSize, borderSize, size.width - borderSize * 2, size.height - borderSize * 2)); // Get an image of the context CGImageRef maskImageRef = CGBitmapContextCreateImage(maskContext); // Clean up CGContextRelease(maskContext); CGColorSpaceRelease(colorSpace); return maskImageRef; } @end ================================================ FILE: testPasterImage/Libs/FilterImageLibs/UIImage-Extensions/UIImage+Cut.h ================================================ // // UIImage+Cut.h // MeiJiaLove // // Created by Wu.weibin on 13-5-17. // Copyright (c) 2013年 Wu.weibin. All rights reserved. // #import #import @interface UIImage (Cut) - (UIImage *)clipImageWithScaleWithsize:(CGSize)asize; - (UIImage *)clipImageWithScaleWithsize:(CGSize)asize roundedCornerImage:(NSInteger)roundedCornerImage borderSize:(NSInteger)borderSize; @end ================================================ FILE: testPasterImage/Libs/FilterImageLibs/UIImage-Extensions/UIImage+Cut.m ================================================ // // UIImage+Cut.m // MeiJiaLove // // Created by Wu.weibin on 13-5-17. // Copyright (c) 2013年 Wu.weibin. All rights reserved. // #import "UIImage+Cut.h" #import "UIImage+RoundedCorner.h" @implementation UIImage (Cut) - (UIImage *)clipImageWithScaleWithsize:(CGSize)asize { UIImage *newimage; UIImage *image = self; if (nil == image) { newimage = nil; } else{ CGSize oldsize = image.size; CGRect rect; if (asize.width/asize.height > oldsize.width/oldsize.height) { rect.size.width = asize.width; rect.size.height = asize.width*oldsize.height/oldsize.width; rect.origin.x = 0; rect.origin.y = (asize.height - rect.size.height)/2; } else{ rect.size.width = asize.height*oldsize.width/oldsize.height; rect.size.height = asize.height; rect.origin.x = (asize.width - rect.size.width)/2; rect.origin.y = 0; } UIGraphicsBeginImageContext(asize); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextClipToRect(context, CGRectMake(0, 0, asize.width, asize.height)); CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]); UIRectFill(CGRectMake(0, 0, asize.width, asize.height));//clear background [image drawInRect:rect]; newimage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); } return newimage; } - (UIImage *)clipImageWithScaleWithsize:(CGSize)asize roundedCornerImage:(NSInteger)roundedCornerImage borderSize:(NSInteger)borderSize { UIImage *image = [self clipImageWithScaleWithsize:asize]; return [image roundedCornerImage:roundedCornerImage borderSize:borderSize]; } @end ================================================ FILE: testPasterImage/Libs/FilterImageLibs/UIImage-Extensions/UIImage+Resize.h ================================================ // UIImage+Resize.h // Created by Trevor Harmon on 8/5/09. // Free for personal or commercial use, with or without modification. // No warranty is expressed or implied. // Extends the UIImage class to support resizing/cropping #import @interface UIImage (Resize) - (UIImage *)croppedImage:(CGRect)bounds; - (UIImage *)thumbnailImage:(NSInteger)thumbnailSize transparentBorder:(NSUInteger)borderSize cornerRadius:(NSUInteger)cornerRadius interpolationQuality:(CGInterpolationQuality)quality; - (UIImage *)resizedImage:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)quality; - (UIImage *)resizedImageWithContentMode:(UIViewContentMode)contentMode bounds:(CGSize)bounds interpolationQuality:(CGInterpolationQuality)quality; - (UIImage *)resizedImage:(CGSize)newSize transform:(CGAffineTransform)transform drawTransposed:(BOOL)transpose interpolationQuality:(CGInterpolationQuality)quality; - (CGAffineTransform)transformForOrientation:(CGSize)newSize; @end ================================================ FILE: testPasterImage/Libs/FilterImageLibs/UIImage-Extensions/UIImage+Resize.m ================================================ // UIImage+Resize.m // Created by Trevor Harmon on 8/5/09. // Free for personal or commercial use, with or without modification. // No warranty is expressed or implied. #import "UIImage+Resize.h" #import "UIImage+RoundedCorner.h" #import "UIImage+Alpha.h" @implementation UIImage (Resize) // Returns a copy of this image that is cropped to the given bounds. // The bounds will be adjusted using CGRectIntegral. // This method ignores the image's imageOrientation setting. - (UIImage *)croppedImage:(CGRect)bounds { CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], bounds); UIImage *croppedImage = [UIImage imageWithCGImage:imageRef]; CGImageRelease(imageRef); return croppedImage; } // Returns a copy of this image that is squared to the thumbnail size. // If transparentBorder is non-zero, a transparent border of the given size will be added around the edges of the thumbnail. (Adding a transparent border of at least one pixel in size has the side-effect of antialiasing the edges of the image when rotating it using Core Animation.) - (UIImage *)thumbnailImage:(NSInteger)thumbnailSize transparentBorder:(NSUInteger)borderSize cornerRadius:(NSUInteger)cornerRadius interpolationQuality:(CGInterpolationQuality)quality { UIImage *resizedImage = [self resizedImageWithContentMode:UIViewContentModeScaleAspectFill bounds:CGSizeMake(thumbnailSize, thumbnailSize) interpolationQuality:quality]; // Crop out any part of the image that's larger than the thumbnail size // The cropped rect must be centered on the resized image // Round the origin points so that the size isn't altered when CGRectIntegral is later invoked CGRect cropRect = CGRectMake(round((resizedImage.size.width - thumbnailSize) / 2), round((resizedImage.size.height - thumbnailSize) / 2), thumbnailSize, thumbnailSize); UIImage *croppedImage = [resizedImage croppedImage:cropRect]; UIImage *transparentBorderImage = borderSize ? [croppedImage transparentBorderImage:borderSize] : croppedImage; return [transparentBorderImage roundedCornerImage:cornerRadius borderSize:borderSize]; } // Returns a rescaled copy of the image, taking into account its orientation // The image will be scaled disproportionately if necessary to fit the bounds specified by the parameter - (UIImage *)resizedImage:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)quality { BOOL drawTransposed; switch (self.imageOrientation) { case UIImageOrientationLeft: case UIImageOrientationLeftMirrored: case UIImageOrientationRight: case UIImageOrientationRightMirrored: drawTransposed = YES; break; default: drawTransposed = NO; } return [self resizedImage:newSize transform:[self transformForOrientation:newSize] drawTransposed:drawTransposed interpolationQuality:quality]; } // Resizes the image according to the given content mode, taking into account the image's orientation - (UIImage *)resizedImageWithContentMode:(UIViewContentMode)contentMode bounds:(CGSize)bounds interpolationQuality:(CGInterpolationQuality)quality { CGFloat horizontalRatio = bounds.width / self.size.width; CGFloat verticalRatio = bounds.height / self.size.height; CGFloat ratio; switch (contentMode) { case UIViewContentModeScaleAspectFill: ratio = MAX(horizontalRatio, verticalRatio); break; case UIViewContentModeScaleAspectFit: ratio = MIN(horizontalRatio, verticalRatio); break; default: [NSException raise:NSInvalidArgumentException format:@"Unsupported content mode: %ld", (long)contentMode]; } CGSize newSize = CGSizeMake(self.size.width * ratio, self.size.height * ratio); return [self resizedImage:newSize interpolationQuality:quality]; } #pragma mark - #pragma mark Private helper methods // Returns a copy of the image that has been transformed using the given affine transform and scaled to the new size // The new image's orientation will be UIImageOrientationUp, regardless of the current image's orientation // If the new size is not integral, it will be rounded up - (UIImage *)resizedImage:(CGSize)newSize transform:(CGAffineTransform)transform drawTransposed:(BOOL)transpose interpolationQuality:(CGInterpolationQuality)quality { CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height)); CGRect transposedRect = CGRectMake(0, 0, newRect.size.height, newRect.size.width); CGImageRef imageRef = self.CGImage; // Build a context that's the same dimensions as the new size CGContextRef bitmap = CGBitmapContextCreate(NULL, newRect.size.width, newRect.size.height, CGImageGetBitsPerComponent(imageRef), 0, CGImageGetColorSpace(imageRef), CGImageGetBitmapInfo(imageRef)); // Rotate and/or flip the image if required by its orientation CGContextConcatCTM(bitmap, transform); // Set the quality level to use when rescaling CGContextSetInterpolationQuality(bitmap, quality); // Draw into the context; this scales the image CGContextDrawImage(bitmap, transpose ? transposedRect : newRect, imageRef); // Get the resized image from the context and a UIImage CGImageRef newImageRef = CGBitmapContextCreateImage(bitmap); UIImage *newImage = [UIImage imageWithCGImage:newImageRef]; // Clean up CGContextRelease(bitmap); CGImageRelease(newImageRef); return newImage; } // Returns an affine transform that takes into account the image orientation when drawing a scaled image - (CGAffineTransform)transformForOrientation:(CGSize)newSize { CGAffineTransform transform = CGAffineTransformIdentity; switch (self.imageOrientation) { case UIImageOrientationDown: // EXIF = 3 case UIImageOrientationDownMirrored: // EXIF = 4 transform = CGAffineTransformTranslate(transform, newSize.width, newSize.height); transform = CGAffineTransformRotate(transform, M_PI); break; case UIImageOrientationLeft: // EXIF = 6 case UIImageOrientationLeftMirrored: // EXIF = 5 transform = CGAffineTransformTranslate(transform, newSize.width, 0); transform = CGAffineTransformRotate(transform, M_PI_2); break; case UIImageOrientationRight: // EXIF = 8 case UIImageOrientationRightMirrored: // EXIF = 7 transform = CGAffineTransformTranslate(transform, 0, newSize.height); transform = CGAffineTransformRotate(transform, -M_PI_2); break; default: break; } switch (self.imageOrientation) { case UIImageOrientationUpMirrored: // EXIF = 2 case UIImageOrientationDownMirrored: // EXIF = 4 transform = CGAffineTransformTranslate(transform, newSize.width, 0); transform = CGAffineTransformScale(transform, -1, 1); break; case UIImageOrientationLeftMirrored: // EXIF = 5 case UIImageOrientationRightMirrored: // EXIF = 7 transform = CGAffineTransformTranslate(transform, newSize.height, 0); transform = CGAffineTransformScale(transform, -1, 1); break; default: break; } return transform; } @end ================================================ FILE: testPasterImage/Libs/FilterImageLibs/UIImage-Extensions/UIImage+RoundedCorner.h ================================================ // UIImage+RoundedCorner.h // Created by Trevor Harmon on 9/20/09. // Free for personal or commercial use, with or without modification. // No warranty is expressed or implied. // Extends the UIImage class to support making rounded corners #import @interface UIImage (RoundedCorner) - (UIImage *)roundedCornerImage:(NSInteger)cornerSize borderSize:(NSInteger)borderSize; - (void)addRoundedRectToPath:(CGRect)rect context:(CGContextRef)context ovalWidth:(CGFloat)ovalWidth ovalHeight:(CGFloat)ovalHeight; @end ================================================ FILE: testPasterImage/Libs/FilterImageLibs/UIImage-Extensions/UIImage+RoundedCorner.m ================================================ // UIImage+RoundedCorner.m // Created by Trevor Harmon on 9/20/09. // Free for personal or commercial use, with or without modification. // No warranty is expressed or implied. #import "UIImage+RoundedCorner.h" #import "UIImage+Alpha.h" @implementation UIImage (RoundedCorner) // Creates a copy of this image with rounded corners // If borderSize is non-zero, a transparent border of the given size will also be added // Original author: Björn Sållarp. Used with permission. See: http://blog.sallarp.com/iphone-uiimage-round-corners/ - (UIImage *)roundedCornerImage:(NSInteger)cornerSize borderSize:(NSInteger)borderSize { // If the image does not have an alpha layer, add one UIImage *image = [self imageWithAlpha]; // Build a context that's the same dimensions as the new size CGContextRef context = CGBitmapContextCreate(NULL, image.size.width, image.size.height, CGImageGetBitsPerComponent(image.CGImage), 0, CGImageGetColorSpace(image.CGImage), CGImageGetBitmapInfo(image.CGImage)); // Create a clipping path with rounded corners CGContextBeginPath(context); [self addRoundedRectToPath:CGRectMake(borderSize, borderSize, image.size.width - borderSize * 2, image.size.height - borderSize * 2) context:context ovalWidth:cornerSize ovalHeight:cornerSize]; CGContextClosePath(context); CGContextClip(context); // Draw the image to the context; the clipping path will make anything outside the rounded rect transparent CGContextDrawImage(context, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage); // Create a CGImage from the context CGImageRef clippedImage = CGBitmapContextCreateImage(context); CGContextRelease(context); // Create a UIImage from the CGImage UIImage *roundedImage = [UIImage imageWithCGImage:clippedImage]; CGImageRelease(clippedImage); return roundedImage; } #pragma mark - #pragma mark Private helper methods // Adds a rectangular path to the given context and rounds its corners by the given extents // Original author: Björn Sållarp. Used with permission. See: http://blog.sallarp.com/iphone-uiimage-round-corners/ - (void)addRoundedRectToPath:(CGRect)rect context:(CGContextRef)context ovalWidth:(CGFloat)ovalWidth ovalHeight:(CGFloat)ovalHeight { if (ovalWidth == 0 || ovalHeight == 0) { CGContextAddRect(context, rect); return; } CGContextSaveGState(context); CGContextTranslateCTM(context, CGRectGetMinX(rect), CGRectGetMinY(rect)); CGContextScaleCTM(context, ovalWidth, ovalHeight); CGFloat fw = CGRectGetWidth(rect) / ovalWidth; CGFloat fh = CGRectGetHeight(rect) / ovalHeight; CGContextMoveToPoint(context, fw, fh/2); CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1); CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1); CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1); CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); CGContextClosePath(context); CGContextRestoreGState(context); } @end ================================================ FILE: testPasterImage/Libs/FilterImageLibs/UIImage-Extensions/UIImage+SplitImageIntoTwoParts.h ================================================ // // UIImage+SplitImageIntoTwoParts.h // TapRepublic // // Created by Terry Lin on 12-5-11. // Copyright (c) 2012年 __MyCompanyName__. All rights reserved. // #import @interface UIImage (SplitImageIntoTwoParts) + (NSArray*)splitImageIntoTwoParts:(UIImage*)image; @end ================================================ FILE: testPasterImage/Libs/FilterImageLibs/UIImage-Extensions/UIImage+SplitImageIntoTwoParts.m ================================================ // // UIImage+SplitImageIntoTwoParts.m // TapRepublic // // Created by Terry Lin on 12-5-11. // Copyright (c) 2012年 __MyCompanyName__. All rights reserved. // #define SAWTOOTH_COUNT 10 #define SAWTOOTH_WIDTH_FACTOR 20 #import "UIImage+SplitImageIntoTwoParts.h" @implementation UIImage (SplitImageIntoTwoParts) +(NSArray *)splitImageIntoTwoParts:(UIImage *)image { CGFloat scale = [[UIScreen mainScreen] scale]; NSMutableArray *array = [NSMutableArray arrayWithCapacity:2]; CGFloat width,height,widthgap,heightgap; int piceCount = SAWTOOTH_COUNT; width = image.size.width; height = image.size.height; widthgap = width/SAWTOOTH_WIDTH_FACTOR; heightgap = height/piceCount; // CGRect rect = CGRectMake(0, 0, width, height); CGContextRef context; CGImageRef imageMasked; UIImage *leftImage,*rightImage; //part one UIGraphicsBeginImageContext(CGSizeMake(width*scale, height*scale)); context = UIGraphicsGetCurrentContext(); CGContextScaleCTM(context, scale, scale); CGContextMoveToPoint(context, 0, 0); int a=-1; for (int i=0; i @interface YBCustomButton : UIButton @property (nonatomic, assign) NSInteger buttonTag; @property (nonatomic, assign) BOOL isCurrentIndex; @end ================================================ FILE: testPasterImage/Views/YBCustomViews/YBCustomButton.m ================================================ // // YBCustomButton.m // testPasterImage // // Created by 王迎博 on 16/9/27. // Copyright © 2016年 王迎博. All rights reserved. // #import "YBCustomButton.h" @implementation YBCustomButton @end ================================================ FILE: testPasterImage/Views/YBFilterImage/YBFilterScrollView.h ================================================ // // YBFilterScrollView.h // testPasterImage // // Created by 王迎博 on 16/9/27. // Copyright © 2016年 王迎博. All rights reserved. // #import @protocol YBFilterScrollViewDelegate @required; - (void)filterImage:(UIImage *)editedImage; @optional; // 测试有返回值的代理 - (NSString *)deliverStr:(NSString *)originalStr; @end @interface YBFilterScrollView : UIScrollView /**滤镜scrollView的高*/ @property (nonatomic, assign) CGFloat filterScrollViewW; /**内切间距*/ @property (nonatomic, assign) CGFloat insert_space; /**名字数组*/ @property (nonatomic, copy) NSArray *titleArray; /**label的高*/ @property (nonatomic, assign) CGFloat labelH; /**每个小方图的宽和高*/ @property (nonatomic, assign) CGFloat perButtonW_H; /**原始图片*/ @property (nonatomic, strong) UIImage *originImage; /**YBFilterScrollViewDelegate*/ @property (nonatomic,weak) id filterDelegate; /** * 开始加载滤镜的scrollView */ - (void)loadScrollView; @end ================================================ FILE: testPasterImage/Views/YBFilterImage/YBFilterScrollView.m ================================================ // // YBFilterScrollView.m // testPasterImage // // Created by 王迎博 on 16/9/27. // Copyright © 2016年 王迎博. All rights reserved. // #import "YBFilterScrollView.h" #import "ImageUtil.h" #import "ColorMatrix.h" @interface YBFilterScrollView () /**被编辑过的图片*/ @property (nonatomic, strong) UIImage *editedImage; /**默认选中的*/ @property (nonatomic, strong) UIButton *defaultButton; @end @implementation YBFilterScrollView @synthesize insert_space; - (void)loadScrollView { // 初始化内部控件 [self initViews]; } /** * 初始化内部控件 */ - (void)initViews { for (int i = 0; i < self.titleArray.count; i ++) { CGFloat filterBtnW_H = self.perButtonW_H; UIButton *filterBtn = [[UIButton alloc]init]; filterBtn.frame = CGRectMake((i+1)*insert_space + filterBtnW_H*i, insert_space, filterBtnW_H, filterBtnW_H); filterBtn.layer.borderColor = [UIColor clearColor].CGColor; filterBtn.layer.borderWidth = 1.; filterBtn.tag = 1000 + i; [filterBtn setBackgroundImage:[self buttonSetImageWithButton:filterBtn] forState:UIControlStateNormal]; [filterBtn addTarget:self action:@selector(filterClick:) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:filterBtn]; if (i == 0) { filterBtn.selected = YES; self.defaultButton = filterBtn; [self filterClick:filterBtn]; } CGFloat labelX = filterBtn.frame.origin.x; CGFloat labelY = CGRectGetMaxY(filterBtn.frame) + 5; CGFloat labelW = filterBtn.frame.size.width; CGFloat labelH = self.labelH - 5; UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(labelX, labelY, labelW, labelH)]; label.text = [self.titleArray objectAtIndex:i]; label.textColor = [UIColor grayColor]; label.textAlignment = NSTextAlignmentCenter; label.font = [UIFont systemFontOfSize:12.]; [self addSubview:label]; } } /** * 设置button的预览图 */ - (UIImage *)buttonSetImageWithButton:(UIButton *)button { NSInteger currentIndex = button.tag - 1000; UIImage *buttonImage; switch (currentIndex) { case 0: { buttonImage = self.originImage; } break; case 1: { buttonImage = [ImageUtil imageWithImage:self.originImage withColorMatrix:colormatrix_lomo]; } break; case 2: { buttonImage = [ImageUtil imageWithImage:self.originImage withColorMatrix:colormatrix_heibai]; } break; case 3: { buttonImage = [ImageUtil imageWithImage:self.originImage withColorMatrix:colormatrix_huajiu]; } break; case 4: { buttonImage = [ImageUtil imageWithImage:self.originImage withColorMatrix:colormatrix_gete]; } break; case 5: { buttonImage = [ImageUtil imageWithImage:self.originImage withColorMatrix:colormatrix_ruise]; } break; case 6: { buttonImage = [ImageUtil imageWithImage:self.originImage withColorMatrix:colormatrix_danya]; } break; case 7: { buttonImage = [ImageUtil imageWithImage:self.originImage withColorMatrix:colormatrix_jiuhong]; } break; case 8: { buttonImage = [ImageUtil imageWithImage:self.originImage withColorMatrix:colormatrix_qingning]; } break; case 9: { buttonImage = [ImageUtil imageWithImage:self.originImage withColorMatrix:colormatrix_langman]; } break; case 10: { buttonImage = [ImageUtil imageWithImage:self.originImage withColorMatrix:colormatrix_guangyun]; } break; case 11: { buttonImage = [ImageUtil imageWithImage:self.originImage withColorMatrix:colormatrix_landiao]; } break; case 12: { buttonImage = [ImageUtil imageWithImage:self.originImage withColorMatrix:colormatrix_menghuan]; } break; case 13: { buttonImage = [ImageUtil imageWithImage:self.originImage withColorMatrix:colormatrix_yese]; } break; default: break; } return buttonImage; } /** * 点击方法 */ - (void)filterClick:(UIButton *)button { //按钮选中状态切换的逻辑 self.defaultButton.selected = NO; if (!self.defaultButton.selected) { [UIView animateWithDuration:.5 animations:^{ self.defaultButton.layer.borderColor = [UIColor clearColor].CGColor; self.defaultButton.layer.borderWidth = 0.1; }]; } button.selected = YES; self.defaultButton = button; if (self.defaultButton.selected) { [UIView animateWithDuration:.5 animations:^{ self.defaultButton.layer.borderColor = [UIColor redColor].CGColor; self.defaultButton.layer.borderWidth = 2; }]; } self.editedImage = button.currentBackgroundImage; if (self.editedImage == nil) { self.editedImage = self.originImage; } //调用代理,把编辑过的当前按钮的图片传给控制器 if (_filterDelegate && [_filterDelegate respondsToSelector:@selector(filterImage:)]) { [_filterDelegate filterImage:button.currentBackgroundImage]; NSString *string = [_filterDelegate deliverStr:[NSString stringWithFormat:@"%@-%@",[self class],[self.titleArray objectAtIndex:button.tag - 1000]]]; NSLog(@"%@",string); } } @end ================================================ FILE: testPasterImage/Views/YBPasterImage/YBPasterScrollView.h ================================================ // // YBPasterScrollView.h // testPasterImage // // Created by 王迎博 on 16/9/5. // Copyright © 2016年 王迎博. All rights reserved. // #import //代理方法 @protocol YBPasterScrollViewDelegate @required; - (void)pasterTag:(NSInteger)pasterTag pasterImage:(UIImage *)pasterImage; @optional; @end @interface YBPasterScrollView : UIScrollView /**贴纸名字数组*/ @property (nonatomic, copy) NSArray *pasterNameArray; /**贴纸图片数组*/ @property (nonatomic, copy) NSArray *pasterImageArray; /**贴纸的高和宽*/ @property (nonatomic, assign) CGFloat pasterImage_W_H; /**YBPasterScrollViewDelegate*/ @property (nonatomic,weak) id pasterDelegate; /**默认选中的*/ @property (nonatomic, strong) UIButton *defaultButton; /** * 创建添加贴纸页底部的scrollView * * @param pasterImageArray 穿过来的图片名字数组 * * @return 返回创建的自定义scrollView */ - (instancetype)initScrollViewWithPasterImageArray:(NSArray *)pasterImageArray; @end ================================================ FILE: testPasterImage/Views/YBPasterImage/YBPasterScrollView.m ================================================ // // YBPasterScrollView.m // testPasterImage // // Created by 王迎博 on 16/9/5. // Copyright © 2016年 王迎博. All rights reserved. // #import "YBPasterScrollView.h" #define defaultPasterImageW_H pasterScrollView_H - 2 * inset_space /**底部scrollView的高*/ extern CGFloat pasterScrollView_H; /**贴纸直接间隔距离*/ const CGFloat inset_space = 15; @interface YBPasterScrollView () @end @implementation YBPasterScrollView /** * 重新自定义scrollView * * @param pasterImageArray 底部贴纸的图片 * * @return 返回一个scrollView */ - (instancetype)initScrollViewWithPasterImageArray:(NSArray *)pasterImageArray { if (self = [super init]) { self.pasterImageArray = pasterImageArray; self.pasterImage_W_H = pasterScrollView_H - inset_space * 2; [self setupUI]; } return self; } /** * 设置UI */ - (void)setupUI { for (int i = 0; i < self.pasterImageArray.count; i ++) { CGFloat pasterBtnW_H = self.pasterImage_W_H; UIButton *pasterBtn = [[UIButton alloc]init]; pasterBtn.frame = CGRectMake((i+1)*inset_space + pasterBtnW_H*i, inset_space, pasterBtnW_H, pasterBtnW_H); [pasterBtn setImage:self.pasterImageArray[i] forState:UIControlStateNormal]; //pasterBtn.layer.borderColor = [UIColor whiteColor].CGColor; //pasterBtn.layer.borderWidth = 0.5; pasterBtn.tag = 1000 + i; [pasterBtn addTarget:self action:@selector(pasterClick:) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:pasterBtn]; } } /** * 点击选取贴纸 */ - (void)pasterClick:(UIButton *)sender { //按钮选中状态切换的逻辑 self.defaultButton.selected = NO; if (!self.defaultButton.selected) { [UIView animateWithDuration:.5 animations:^{ self.defaultButton.layer.borderColor = [UIColor clearColor].CGColor; self.defaultButton.layer.borderWidth = 0.1; }]; } sender.selected = YES; self.defaultButton = sender; if (self.defaultButton.selected) { [UIView animateWithDuration:.5 animations:^{ self.defaultButton.layer.borderColor = [UIColor redColor].CGColor; self.defaultButton.layer.borderWidth = 2; }]; } if (_pasterDelegate && [_pasterDelegate respondsToSelector:@selector(pasterTag:pasterImage:)]) { [_pasterDelegate pasterTag:sender.tag - 1000 pasterImage:[self.pasterImageArray objectAtIndex:sender.tag - 1000]]; } } - (void)layoutSubviews { [super layoutSubviews]; } @end ================================================ FILE: testPasterImage/Views/YBPasterImage/YBPasterView.h ================================================ // // YBPasterView.h // testPasterImage // // Created by 王迎博 on 16/9/6. // Copyright © 2016年 王迎博. All rights reserved. // #import @protocol YBPasterViewDelegate @required; @optional; - (void)deleteThePaster; @end @interface YBPasterView : UIView /**YBPasterViewDelegate*/ @property (nonatomic,weak) id delegate; /**图片,所要加成贴纸的图片*/ @property (nonatomic, strong) UIImage *pasterImage; /**隐藏“删除”和“缩放”按钮*/ - (void)hiddenBtn; /**显示“删除”和“缩放”按钮*/ - (void)showBtn; @end ================================================ FILE: testPasterImage/Views/YBPasterImage/YBPasterView.m ================================================ // // YBPasterView.m // testPasterImage // // Created by 王迎博 on 16/9/6. // Copyright © 2016年 王迎博. All rights reserved. // #import "YBPasterView.h" /**默认删除和缩放按钮的大小*/ #define btnW_H 24.0 /**默认的图片宽高*/ #define defaultImageViewW_H self.frame.size.width - btnW_H /**缩放和删除按钮与图片的间隔距离*/ #define paster_insert_space btnW_H/2 /**总高度*/ #define PASTER_SLIDE 120 /**安全边框*/ #define SECURITY_LENGTH PASTER_SLIDE/2 @interface YBPasterView () { CGFloat minWidth; CGFloat minHeight; CGFloat deltaAngle; CGPoint prevPoint; CGPoint touchStart; CGRect bgRect ; } /**删除按钮*/ @property (nonatomic, strong) UIImageView *delegateImageView; /**缩放和旋转按钮*/ @property (nonatomic, strong) UIImageView *scaleImageView; /**贴纸图片*/ @property (nonatomic, strong) UIImageView *pasterImageView; @end @implementation YBPasterView - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { //设置UI [self setupUI]; } return self; } /** * 隐藏“删除”和“缩放”按钮 */ - (void)hiddenBtn { [UIView animateWithDuration:.5 animations:^{ self.delegateImageView.alpha = 0.0; self.delegateImageView.hidden = YES; self.scaleImageView.alpha = 0.0; self.scaleImageView.hidden = YES; }]; } /** * 显示“删除”和“缩放”按钮 */ - (void)showBtn { [UIView animateWithDuration:.5 animations:^{ self.delegateImageView.alpha = 1.0; self.scaleImageView.alpha = 1.0; self.delegateImageView.hidden = NO; self.scaleImageView.hidden = NO; }]; } /** * 设置UI */ - (void)setupUI { self.backgroundColor = [UIColor lightGrayColor]; minWidth = self.bounds.size.width * 0.5; minHeight = self.bounds.size.height * 0.5; deltaAngle = atan2(self.frame.origin.y+self.frame.size.height - self.center.y, self.frame.origin.x+self.frame.size.width - self.center.x); #warning clang - 用自有的touchMove方法移动,直接加拖拽手势效果不好 //UIPanGestureRecognizer *dragResizeGestrue = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(dragPasterView:)]; //[self addGestureRecognizer:dragResizeGestrue]; #warning clang - 用拖拽按钮控制父控件旋转 //UIRotationGestureRecognizer *rotateGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotation:)] ; //[self addGestureRecognizer:rotateGesture] ; UIImageView *pasterImageView = [[UIImageView alloc]init]; pasterImageView.backgroundColor = [UIColor lightGrayColor]; pasterImageView.layer.borderColor = [UIColor redColor].CGColor; pasterImageView.layer.borderWidth = 0.5; pasterImageView.userInteractionEnabled = YES; [self addSubview:pasterImageView]; self.pasterImageView = pasterImageView; UIImageView *delegateImageView = [[UIImageView alloc]init]; [delegateImageView setImage:[UIImage imageNamed:@"bt_paster_delete"]]; UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(btDeletePressed:)]; delegateImageView.userInteractionEnabled = YES; [delegateImageView addGestureRecognizer:tap]; [self addSubview:delegateImageView]; self.delegateImageView = delegateImageView; UIImageView *scaleImageView = [[UIImageView alloc]init]; [scaleImageView setImage:[UIImage imageNamed:@"bt_paster_transform"]]; UIPanGestureRecognizer *panResizeGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(resizeTranslate:)] ; scaleImageView.userInteractionEnabled = YES; [scaleImageView addGestureRecognizer:panResizeGesture] ; [self addSubview:scaleImageView]; self.scaleImageView = scaleImageView; self.pasterImageView.frame = CGRectMake(paster_insert_space, paster_insert_space, defaultImageViewW_H, defaultImageViewW_H); self.delegateImageView.frame = CGRectMake(0, 0, btnW_H, btnW_H); self.scaleImageView.frame = CGRectMake(CGRectGetMaxX(self.pasterImageView.frame) - btnW_H/2, CGRectGetMaxY(self.pasterImageView.frame) - btnW_H/2, btnW_H, btnW_H); } /** * 旋转手势 */ - (void)handleRotation:(UIRotationGestureRecognizer *)rotateGesture { self.transform = CGAffineTransformRotate(self.transform, rotateGesture.rotation) ; rotateGesture.rotation = 0 ; } /** * 拖动手势 */ - (void)dragPasterView:(UIPanGestureRecognizer *)dragPasterView { CGPoint point = [dragPasterView translationInView:dragPasterView.view]; self.center = CGPointMake(self.center.x + point.x, self.center.y + point.y); [dragPasterView setTranslation:CGPointZero inView:dragPasterView.view]; [self checkIsOut]; } /** * 右下角的缩放和旋转手势 */ - (void)resizeTranslate:(UIPanGestureRecognizer *)recognizer { if ([recognizer state] == UIGestureRecognizerStateBegan) { prevPoint = [recognizer locationInView:self]; [self setNeedsDisplay]; } else if ([recognizer state] == UIGestureRecognizerStateChanged) { if (self.bounds.size.width < minWidth || self.bounds.size.height < minHeight) { self.bounds = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, minWidth + 1 , minHeight + 1); self.scaleImageView.frame =CGRectMake(self.bounds.size.width-btnW_H,self.bounds.size.height-btnW_H,btnW_H,btnW_H); prevPoint = [recognizer locationInView:self]; } else { CGPoint point = [recognizer locationInView:self]; float wChange = 0.0, hChange = 0.0; wChange = (point.x - prevPoint.x); float wRatioChange = (wChange/(float)self.bounds.size.width); hChange = wRatioChange * self.bounds.size.height; if (ABS(wChange) > 50.0f || ABS(hChange) > 50.0f) { prevPoint = [recognizer locationOfTouch:0 inView:self]; return; } CGFloat finalWidth = self.bounds.size.width + (wChange) ; CGFloat finalHeight = self.bounds.size.height + (wChange) ; if (finalWidth > PASTER_SLIDE*(1+0.5)) { finalWidth = PASTER_SLIDE*(1+0.5); } if (finalWidth < PASTER_SLIDE*(1-0.5)) { finalWidth = PASTER_SLIDE*(1-0.5) ; } if (finalHeight > PASTER_SLIDE*(1+0.5)) { finalHeight = PASTER_SLIDE*(1+0.5) ; } if (finalHeight < PASTER_SLIDE*(1-0.5)) { finalHeight = PASTER_SLIDE*(1-0.5) ; } self.bounds = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, finalWidth, finalHeight); self.scaleImageView.frame = CGRectMake(self.bounds.size.width-btnW_H, self.bounds.size.height-btnW_H, btnW_H, btnW_H); self.pasterImageView.frame = CGRectMake(paster_insert_space, paster_insert_space, self.bounds.size.width - paster_insert_space*2, self.bounds.size.height - paster_insert_space*2); prevPoint = [recognizer locationOfTouch:0 inView:self]; } /* 旋转 */ float ang = atan2([recognizer locationInView:self.superview].y - self.center.y, [recognizer locationInView:self.superview].x - self.center.x) ; float angleDiff = deltaAngle - ang ; self.transform = CGAffineTransformMakeRotation(-angleDiff); [self setNeedsDisplay]; } else if ([recognizer state] == UIGestureRecognizerStateEnded) { prevPoint = [recognizer locationInView:self]; [self setNeedsDisplay]; } //检查旋转和缩放是否出界 [self checkIsOut]; } /** * 左上角的删除点击手势 */ - (void)btDeletePressed:(UITapGestureRecognizer *)recognizer { if (self.delegate && [self.delegate respondsToSelector:@selector(deleteThePaster)]) { [self.delegate deleteThePaster]; } [self removeFromSuperview]; } /** * 重写pasterImage的set方法 */ - (void)setPasterImage:(UIImage *)pasterImage { _pasterImage = pasterImage; if (pasterImage) { self.pasterImageView.image = pasterImage; } } - (void)layoutSubviews { [super layoutSubviews]; } /** * 检查在添加tag的时候是否超出了显示范围,如果超出,移动进显示范围内 */ - (void)checkIsOut { CGPoint point = self.center; CGFloat top; CGFloat left; CGFloat bottom; CGFloat right; top = point.y - self.frame.size.height/2; bottom = (self.superview.frame.size.height - point.y) - self.frame.size.height/2; if (point.y < self.superview.frame.size.height/2)//顶部超出范围时 { if (top < 0) { point.y += ABS(top); } } else//底部超出范围时 { if (bottom < 0) { point.y -= ABS(bottom); } } left = point.x - self.frame.size.width/2; right =(self.superview.frame.size.width - point.x) - self.frame.size.width/2; if (point.x < self.superview.frame.size.width/2)//左边超出范围时 { if (left < 0) { point.x += ABS(left); } } else//右边超出范围时 { if (right < 0) { point.x -= ABS(right); } } if (point.x == self.center.x && point.y == self.center.y) { }else{ [UIView animateWithDuration:0.2 animations:^{ self.center = point; }]; } } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject] ; touchStart = [touch locationInView:self.superview] ; } /** * 移动 */ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { CGPoint touchLocation = [[touches anyObject] locationInView:self]; if (CGRectContainsPoint(self.scaleImageView.frame, touchLocation)) { return; } CGPoint touch = [[touches anyObject] locationInView:self.superview]; [self translateUsingTouchLocation:touch]; [self checkIsOut]; touchStart = touch; } /** * 确保移动时不超出屏幕 */ - (void)translateUsingTouchLocation:(CGPoint)touchPoint { CGPoint newCenter = CGPointMake(self.center.x + touchPoint.x - touchStart.x, self.center.y + touchPoint.y - touchStart.y) ; // Ensure the translation won't cause the view to move offscreen. BEGIN CGFloat midPointX = CGRectGetMidX(self.bounds) ; if (newCenter.x > self.superview.bounds.size.width - midPointX + SECURITY_LENGTH) { newCenter.x = self.superview.bounds.size.width - midPointX + SECURITY_LENGTH; } if (newCenter.x < midPointX - SECURITY_LENGTH) { newCenter.x = midPointX - SECURITY_LENGTH; } CGFloat midPointY = CGRectGetMidY(self.bounds); if (newCenter.y > self.superview.bounds.size.height - midPointY + SECURITY_LENGTH) { newCenter.y = self.superview.bounds.size.height - midPointY + SECURITY_LENGTH; } if (newCenter.y < midPointY - SECURITY_LENGTH) { newCenter.y = midPointY - SECURITY_LENGTH; } // Ensure the translation won't cause the view to move offscreen. END self.center = newCenter; } #pragma mark - UIGestureRecognizerDelegate - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES; } @end ================================================ FILE: testPasterImage/main.m ================================================ // // main.m // testPasterImage // // Created by 王迎博 on 16/9/5. // Copyright © 2016年 王迎博. All rights reserved. // #import #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } ================================================ FILE: testPasterImage.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 6828CE0E1DB76A1B00369A7F /* YBBaseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6828CE0D1DB76A1B00369A7F /* YBBaseViewController.m */; }; 6828CE111DB76A6300369A7F /* UIViewController+Swizzling.m in Sources */ = {isa = PBXBuildFile; fileRef = 6828CE101DB76A6300369A7F /* UIViewController+Swizzling.m */; }; 68A7FE8F1D7D602E00F3488D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 68A7FE8E1D7D602E00F3488D /* main.m */; }; 68A7FE921D7D602E00F3488D /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 68A7FE911D7D602E00F3488D /* AppDelegate.m */; }; 68A7FE981D7D602E00F3488D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 68A7FE961D7D602E00F3488D /* Main.storyboard */; }; 68A7FE9A1D7D602E00F3488D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 68A7FE991D7D602E00F3488D /* Assets.xcassets */; }; 68A7FE9D1D7D602E00F3488D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 68A7FE9B1D7D602E00F3488D /* LaunchScreen.storyboard */; }; 68A7FEA81D7D602E00F3488D /* testPasterImageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 68A7FEA71D7D602E00F3488D /* testPasterImageTests.m */; }; 68A7FEB31D7D602F00F3488D /* testPasterImageUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 68A7FEB21D7D602F00F3488D /* testPasterImageUITests.m */; }; 68BA63C01D9E178B007EF318 /* UIViewController+Example.m in Sources */ = {isa = PBXBuildFile; fileRef = 68BA63BF1D9E178B007EF318 /* UIViewController+Example.m */; }; 68E54F791D9A13130003BF63 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 68E54F761D9A13130003BF63 /* ViewController.m */; }; 68E54F7A1D9A13130003BF63 /* YBPasterImageVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 68E54F781D9A13130003BF63 /* YBPasterImageVC.m */; }; 68E54F881D9A13540003BF63 /* UIImage+AddFunction.m in Sources */ = {isa = PBXBuildFile; fileRef = 68E54F851D9A13540003BF63 /* UIImage+AddFunction.m */; }; 68E54F891D9A13540003BF63 /* UIViewController+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 68E54F871D9A13540003BF63 /* UIViewController+Extension.m */; }; 68E54F901D9A13D10003BF63 /* YBPasterScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = 68E54F8D1D9A13D10003BF63 /* YBPasterScrollView.m */; }; 68E54F911D9A13D10003BF63 /* YBPasterView.m in Sources */ = {isa = PBXBuildFile; fileRef = 68E54F8F1D9A13D10003BF63 /* YBPasterView.m */; }; 68E54F961D9A20B00003BF63 /* YBCustomButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 68E54F951D9A20B00003BF63 /* YBCustomButton.m */; }; 68E54FE11D9A584B0003BF63 /* YBFilterScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = 68E54FE01D9A584B0003BF63 /* YBFilterScrollView.m */; }; 68E54FF31D9A6C140003BF63 /* ImageUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 68E54FE71D9A6C140003BF63 /* ImageUtil.m */; }; 68E54FF41D9A6C140003BF63 /* UIImage+Alpha.m in Sources */ = {isa = PBXBuildFile; fileRef = 68E54FEA1D9A6C140003BF63 /* UIImage+Alpha.m */; }; 68E54FF51D9A6C140003BF63 /* UIImage+Cut.m in Sources */ = {isa = PBXBuildFile; fileRef = 68E54FEC1D9A6C140003BF63 /* UIImage+Cut.m */; }; 68E54FF61D9A6C140003BF63 /* UIImage+Resize.m in Sources */ = {isa = PBXBuildFile; fileRef = 68E54FEE1D9A6C140003BF63 /* UIImage+Resize.m */; }; 68E54FF71D9A6C140003BF63 /* UIImage+RoundedCorner.m in Sources */ = {isa = PBXBuildFile; fileRef = 68E54FF01D9A6C140003BF63 /* UIImage+RoundedCorner.m */; }; 68E54FF81D9A6C140003BF63 /* UIImage+SplitImageIntoTwoParts.m in Sources */ = {isa = PBXBuildFile; fileRef = 68E54FF21D9A6C140003BF63 /* UIImage+SplitImageIntoTwoParts.m */; }; E675C631B2BC66F8F7D1FDA0 /* libPods-testPasterImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE1DD9585D80CEC7302FDE3 /* libPods-testPasterImage.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 68A7FEA41D7D602E00F3488D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 68A7FE821D7D602E00F3488D /* Project object */; proxyType = 1; remoteGlobalIDString = 68A7FE891D7D602E00F3488D; remoteInfo = testPasterImage; }; 68A7FEAF1D7D602F00F3488D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 68A7FE821D7D602E00F3488D /* Project object */; proxyType = 1; remoteGlobalIDString = 68A7FE891D7D602E00F3488D; remoteInfo = testPasterImage; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 0E1D0ACD3D2EAF07D3741914 /* Pods-testPasterImage.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-testPasterImage.debug.xcconfig"; path = "Pods/Target Support Files/Pods-testPasterImage/Pods-testPasterImage.debug.xcconfig"; sourceTree = ""; }; 3AE1DD9585D80CEC7302FDE3 /* libPods-testPasterImage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-testPasterImage.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 6828CE0C1DB76A1B00369A7F /* YBBaseViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YBBaseViewController.h; sourceTree = ""; }; 6828CE0D1DB76A1B00369A7F /* YBBaseViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YBBaseViewController.m; sourceTree = ""; }; 6828CE0F1DB76A6300369A7F /* UIViewController+Swizzling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+Swizzling.h"; sourceTree = ""; }; 6828CE101DB76A6300369A7F /* UIViewController+Swizzling.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+Swizzling.m"; sourceTree = ""; }; 68A7FE8A1D7D602E00F3488D /* testPasterImage.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testPasterImage.app; sourceTree = BUILT_PRODUCTS_DIR; }; 68A7FE8E1D7D602E00F3488D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 68A7FE901D7D602E00F3488D /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 68A7FE911D7D602E00F3488D /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 68A7FE971D7D602E00F3488D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 68A7FE991D7D602E00F3488D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 68A7FE9C1D7D602E00F3488D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 68A7FE9E1D7D602E00F3488D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 68A7FEA31D7D602E00F3488D /* testPasterImageTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = testPasterImageTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 68A7FEA71D7D602E00F3488D /* testPasterImageTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = testPasterImageTests.m; sourceTree = ""; }; 68A7FEA91D7D602E00F3488D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 68A7FEAE1D7D602F00F3488D /* testPasterImageUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = testPasterImageUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 68A7FEB21D7D602F00F3488D /* testPasterImageUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = testPasterImageUITests.m; sourceTree = ""; }; 68A7FEB41D7D602F00F3488D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 68BA63BE1D9E178B007EF318 /* UIViewController+Example.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+Example.h"; sourceTree = ""; }; 68BA63BF1D9E178B007EF318 /* UIViewController+Example.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+Example.m"; sourceTree = ""; }; 68E54F751D9A13130003BF63 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 68E54F761D9A13130003BF63 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 68E54F771D9A13130003BF63 /* YBPasterImageVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YBPasterImageVC.h; sourceTree = ""; }; 68E54F781D9A13130003BF63 /* YBPasterImageVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YBPasterImageVC.m; sourceTree = ""; }; 68E54F841D9A13540003BF63 /* UIImage+AddFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+AddFunction.h"; sourceTree = ""; }; 68E54F851D9A13540003BF63 /* UIImage+AddFunction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+AddFunction.m"; sourceTree = ""; }; 68E54F861D9A13540003BF63 /* UIViewController+Extension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+Extension.h"; sourceTree = ""; }; 68E54F871D9A13540003BF63 /* UIViewController+Extension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+Extension.m"; sourceTree = ""; }; 68E54F8C1D9A13D10003BF63 /* YBPasterScrollView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YBPasterScrollView.h; sourceTree = ""; }; 68E54F8D1D9A13D10003BF63 /* YBPasterScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YBPasterScrollView.m; sourceTree = ""; }; 68E54F8E1D9A13D10003BF63 /* YBPasterView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YBPasterView.h; sourceTree = ""; }; 68E54F8F1D9A13D10003BF63 /* YBPasterView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YBPasterView.m; sourceTree = ""; }; 68E54F941D9A20B00003BF63 /* YBCustomButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YBCustomButton.h; sourceTree = ""; }; 68E54F951D9A20B00003BF63 /* YBCustomButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YBCustomButton.m; sourceTree = ""; }; 68E54FDF1D9A584B0003BF63 /* YBFilterScrollView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YBFilterScrollView.h; sourceTree = ""; }; 68E54FE01D9A584B0003BF63 /* YBFilterScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YBFilterScrollView.m; sourceTree = ""; }; 68E54FE51D9A6C140003BF63 /* ColorMatrix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ColorMatrix.h; sourceTree = ""; }; 68E54FE61D9A6C140003BF63 /* ImageUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageUtil.h; sourceTree = ""; }; 68E54FE71D9A6C140003BF63 /* ImageUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImageUtil.m; sourceTree = ""; }; 68E54FE91D9A6C140003BF63 /* UIImage+Alpha.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+Alpha.h"; sourceTree = ""; }; 68E54FEA1D9A6C140003BF63 /* UIImage+Alpha.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+Alpha.m"; sourceTree = ""; }; 68E54FEB1D9A6C140003BF63 /* UIImage+Cut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+Cut.h"; sourceTree = ""; }; 68E54FEC1D9A6C140003BF63 /* UIImage+Cut.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+Cut.m"; sourceTree = ""; }; 68E54FED1D9A6C140003BF63 /* UIImage+Resize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+Resize.h"; sourceTree = ""; }; 68E54FEE1D9A6C140003BF63 /* UIImage+Resize.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+Resize.m"; sourceTree = ""; }; 68E54FEF1D9A6C140003BF63 /* UIImage+RoundedCorner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+RoundedCorner.h"; sourceTree = ""; }; 68E54FF01D9A6C140003BF63 /* UIImage+RoundedCorner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+RoundedCorner.m"; sourceTree = ""; }; 68E54FF11D9A6C140003BF63 /* UIImage+SplitImageIntoTwoParts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+SplitImageIntoTwoParts.h"; sourceTree = ""; }; 68E54FF21D9A6C140003BF63 /* UIImage+SplitImageIntoTwoParts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+SplitImageIntoTwoParts.m"; sourceTree = ""; }; E2D87E7F14BF62318BD7B391 /* Pods-testPasterImage.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-testPasterImage.release.xcconfig"; path = "Pods/Target Support Files/Pods-testPasterImage/Pods-testPasterImage.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 68A7FE871D7D602E00F3488D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( E675C631B2BC66F8F7D1FDA0 /* libPods-testPasterImage.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 68A7FEA01D7D602E00F3488D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 68A7FEAB1D7D602F00F3488D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 68A7FE811D7D602E00F3488D = { isa = PBXGroup; children = ( 68A7FE8C1D7D602E00F3488D /* testPasterImage */, 68A7FEA61D7D602E00F3488D /* testPasterImageTests */, 68A7FEB11D7D602F00F3488D /* testPasterImageUITests */, 68A7FE8B1D7D602E00F3488D /* Products */, D37AF9F23C8DBC836EB27BD0 /* Pods */, B81B40EFE9215CE75818B88A /* Frameworks */, ); sourceTree = ""; }; 68A7FE8B1D7D602E00F3488D /* Products */ = { isa = PBXGroup; children = ( 68A7FE8A1D7D602E00F3488D /* testPasterImage.app */, 68A7FEA31D7D602E00F3488D /* testPasterImageTests.xctest */, 68A7FEAE1D7D602F00F3488D /* testPasterImageUITests.xctest */, ); name = Products; sourceTree = ""; }; 68A7FE8C1D7D602E00F3488D /* testPasterImage */ = { isa = PBXGroup; children = ( 68A7FE901D7D602E00F3488D /* AppDelegate.h */, 68A7FE911D7D602E00F3488D /* AppDelegate.m */, 68E54F741D9A12F30003BF63 /* Controllers */, 68E54F8A1D9A13D10003BF63 /* Views */, 68E54F831D9A13540003BF63 /* Categories */, 68E54FE31D9A6C140003BF63 /* Libs */, 68A7FE961D7D602E00F3488D /* Main.storyboard */, 68A7FE8D1D7D602E00F3488D /* Supporting Files */, ); path = testPasterImage; sourceTree = ""; }; 68A7FE8D1D7D602E00F3488D /* Supporting Files */ = { isa = PBXGroup; children = ( 68A7FE991D7D602E00F3488D /* Assets.xcassets */, 68A7FE9B1D7D602E00F3488D /* LaunchScreen.storyboard */, 68A7FE9E1D7D602E00F3488D /* Info.plist */, 68A7FE8E1D7D602E00F3488D /* main.m */, ); name = "Supporting Files"; sourceTree = ""; }; 68A7FEA61D7D602E00F3488D /* testPasterImageTests */ = { isa = PBXGroup; children = ( 68A7FEA71D7D602E00F3488D /* testPasterImageTests.m */, 68A7FEA91D7D602E00F3488D /* Info.plist */, ); path = testPasterImageTests; sourceTree = ""; }; 68A7FEB11D7D602F00F3488D /* testPasterImageUITests */ = { isa = PBXGroup; children = ( 68A7FEB21D7D602F00F3488D /* testPasterImageUITests.m */, 68A7FEB41D7D602F00F3488D /* Info.plist */, ); path = testPasterImageUITests; sourceTree = ""; }; 68E54F741D9A12F30003BF63 /* Controllers */ = { isa = PBXGroup; children = ( 68E54F751D9A13130003BF63 /* ViewController.h */, 68E54F761D9A13130003BF63 /* ViewController.m */, 68E54F771D9A13130003BF63 /* YBPasterImageVC.h */, 68E54F781D9A13130003BF63 /* YBPasterImageVC.m */, 6828CE0C1DB76A1B00369A7F /* YBBaseViewController.h */, 6828CE0D1DB76A1B00369A7F /* YBBaseViewController.m */, ); path = Controllers; sourceTree = ""; }; 68E54F831D9A13540003BF63 /* Categories */ = { isa = PBXGroup; children = ( 68E54F841D9A13540003BF63 /* UIImage+AddFunction.h */, 68E54F851D9A13540003BF63 /* UIImage+AddFunction.m */, 68BA63BE1D9E178B007EF318 /* UIViewController+Example.h */, 68BA63BF1D9E178B007EF318 /* UIViewController+Example.m */, 6828CE0F1DB76A6300369A7F /* UIViewController+Swizzling.h */, 6828CE101DB76A6300369A7F /* UIViewController+Swizzling.m */, 68E54F861D9A13540003BF63 /* UIViewController+Extension.h */, 68E54F871D9A13540003BF63 /* UIViewController+Extension.m */, ); path = Categories; sourceTree = ""; }; 68E54F8A1D9A13D10003BF63 /* Views */ = { isa = PBXGroup; children = ( 68E54F931D9A20910003BF63 /* YBCustomViews */, 68E54F921D9A14010003BF63 /* YBFilterImage */, 68E54F8B1D9A13D10003BF63 /* YBPasterImage */, ); path = Views; sourceTree = ""; }; 68E54F8B1D9A13D10003BF63 /* YBPasterImage */ = { isa = PBXGroup; children = ( 68E54F8C1D9A13D10003BF63 /* YBPasterScrollView.h */, 68E54F8D1D9A13D10003BF63 /* YBPasterScrollView.m */, 68E54F8E1D9A13D10003BF63 /* YBPasterView.h */, 68E54F8F1D9A13D10003BF63 /* YBPasterView.m */, ); path = YBPasterImage; sourceTree = ""; }; 68E54F921D9A14010003BF63 /* YBFilterImage */ = { isa = PBXGroup; children = ( 68E54FDF1D9A584B0003BF63 /* YBFilterScrollView.h */, 68E54FE01D9A584B0003BF63 /* YBFilterScrollView.m */, ); path = YBFilterImage; sourceTree = ""; }; 68E54F931D9A20910003BF63 /* YBCustomViews */ = { isa = PBXGroup; children = ( 68E54F941D9A20B00003BF63 /* YBCustomButton.h */, 68E54F951D9A20B00003BF63 /* YBCustomButton.m */, ); path = YBCustomViews; sourceTree = ""; }; 68E54FE31D9A6C140003BF63 /* Libs */ = { isa = PBXGroup; children = ( 68E54FE41D9A6C140003BF63 /* FilterImageLibs */, ); path = Libs; sourceTree = ""; }; 68E54FE41D9A6C140003BF63 /* FilterImageLibs */ = { isa = PBXGroup; children = ( 68E54FE51D9A6C140003BF63 /* ColorMatrix.h */, 68E54FE61D9A6C140003BF63 /* ImageUtil.h */, 68E54FE71D9A6C140003BF63 /* ImageUtil.m */, 68E54FE81D9A6C140003BF63 /* UIImage-Extensions */, ); path = FilterImageLibs; sourceTree = ""; }; 68E54FE81D9A6C140003BF63 /* UIImage-Extensions */ = { isa = PBXGroup; children = ( 68E54FE91D9A6C140003BF63 /* UIImage+Alpha.h */, 68E54FEA1D9A6C140003BF63 /* UIImage+Alpha.m */, 68E54FEB1D9A6C140003BF63 /* UIImage+Cut.h */, 68E54FEC1D9A6C140003BF63 /* UIImage+Cut.m */, 68E54FED1D9A6C140003BF63 /* UIImage+Resize.h */, 68E54FEE1D9A6C140003BF63 /* UIImage+Resize.m */, 68E54FEF1D9A6C140003BF63 /* UIImage+RoundedCorner.h */, 68E54FF01D9A6C140003BF63 /* UIImage+RoundedCorner.m */, 68E54FF11D9A6C140003BF63 /* UIImage+SplitImageIntoTwoParts.h */, 68E54FF21D9A6C140003BF63 /* UIImage+SplitImageIntoTwoParts.m */, ); path = "UIImage-Extensions"; sourceTree = ""; }; B81B40EFE9215CE75818B88A /* Frameworks */ = { isa = PBXGroup; children = ( 3AE1DD9585D80CEC7302FDE3 /* libPods-testPasterImage.a */, ); name = Frameworks; sourceTree = ""; }; D37AF9F23C8DBC836EB27BD0 /* Pods */ = { isa = PBXGroup; children = ( 0E1D0ACD3D2EAF07D3741914 /* Pods-testPasterImage.debug.xcconfig */, E2D87E7F14BF62318BD7B391 /* Pods-testPasterImage.release.xcconfig */, ); name = Pods; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 68A7FE891D7D602E00F3488D /* testPasterImage */ = { isa = PBXNativeTarget; buildConfigurationList = 68A7FEB71D7D602F00F3488D /* Build configuration list for PBXNativeTarget "testPasterImage" */; buildPhases = ( F775385417FC25057086136C /* [CP] Check Pods Manifest.lock */, 68A7FE861D7D602E00F3488D /* Sources */, 68A7FE871D7D602E00F3488D /* Frameworks */, 68A7FE881D7D602E00F3488D /* Resources */, B294BE38D838F5CCD14593EA /* [CP] Embed Pods Frameworks */, E89784E5118341200B2A00D4 /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( ); name = testPasterImage; productName = testPasterImage; productReference = 68A7FE8A1D7D602E00F3488D /* testPasterImage.app */; productType = "com.apple.product-type.application"; }; 68A7FEA21D7D602E00F3488D /* testPasterImageTests */ = { isa = PBXNativeTarget; buildConfigurationList = 68A7FEBA1D7D602F00F3488D /* Build configuration list for PBXNativeTarget "testPasterImageTests" */; buildPhases = ( 68A7FE9F1D7D602E00F3488D /* Sources */, 68A7FEA01D7D602E00F3488D /* Frameworks */, 68A7FEA11D7D602E00F3488D /* Resources */, ); buildRules = ( ); dependencies = ( 68A7FEA51D7D602E00F3488D /* PBXTargetDependency */, ); name = testPasterImageTests; productName = testPasterImageTests; productReference = 68A7FEA31D7D602E00F3488D /* testPasterImageTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; 68A7FEAD1D7D602F00F3488D /* testPasterImageUITests */ = { isa = PBXNativeTarget; buildConfigurationList = 68A7FEBD1D7D602F00F3488D /* Build configuration list for PBXNativeTarget "testPasterImageUITests" */; buildPhases = ( 68A7FEAA1D7D602F00F3488D /* Sources */, 68A7FEAB1D7D602F00F3488D /* Frameworks */, 68A7FEAC1D7D602F00F3488D /* Resources */, ); buildRules = ( ); dependencies = ( 68A7FEB01D7D602F00F3488D /* PBXTargetDependency */, ); name = testPasterImageUITests; productName = testPasterImageUITests; productReference = 68A7FEAE1D7D602F00F3488D /* testPasterImageUITests.xctest */; productType = "com.apple.product-type.bundle.ui-testing"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 68A7FE821D7D602E00F3488D /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0730; ORGANIZATIONNAME = "王迎博"; TargetAttributes = { 68A7FE891D7D602E00F3488D = { CreatedOnToolsVersion = 7.3; DevelopmentTeam = MA34265KQ7; }; 68A7FEA21D7D602E00F3488D = { CreatedOnToolsVersion = 7.3; TestTargetID = 68A7FE891D7D602E00F3488D; }; 68A7FEAD1D7D602F00F3488D = { CreatedOnToolsVersion = 7.3; TestTargetID = 68A7FE891D7D602E00F3488D; }; }; }; buildConfigurationList = 68A7FE851D7D602E00F3488D /* Build configuration list for PBXProject "testPasterImage" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 68A7FE811D7D602E00F3488D; productRefGroup = 68A7FE8B1D7D602E00F3488D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 68A7FE891D7D602E00F3488D /* testPasterImage */, 68A7FEA21D7D602E00F3488D /* testPasterImageTests */, 68A7FEAD1D7D602F00F3488D /* testPasterImageUITests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 68A7FE881D7D602E00F3488D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 68A7FE9D1D7D602E00F3488D /* LaunchScreen.storyboard in Resources */, 68A7FE9A1D7D602E00F3488D /* Assets.xcassets in Resources */, 68A7FE981D7D602E00F3488D /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; 68A7FEA11D7D602E00F3488D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 68A7FEAC1D7D602F00F3488D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ B294BE38D838F5CCD14593EA /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-testPasterImage/Pods-testPasterImage-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; E89784E5118341200B2A00D4 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-testPasterImage/Pods-testPasterImage-resources.sh\"\n"; showEnvVarsInLog = 0; }; F775385417FC25057086136C /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 68A7FE861D7D602E00F3488D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 68E54FF31D9A6C140003BF63 /* ImageUtil.m in Sources */, 68BA63C01D9E178B007EF318 /* UIViewController+Example.m in Sources */, 68E54FF71D9A6C140003BF63 /* UIImage+RoundedCorner.m in Sources */, 6828CE111DB76A6300369A7F /* UIViewController+Swizzling.m in Sources */, 68E54F791D9A13130003BF63 /* ViewController.m in Sources */, 68E54F7A1D9A13130003BF63 /* YBPasterImageVC.m in Sources */, 68E54FE11D9A584B0003BF63 /* YBFilterScrollView.m in Sources */, 6828CE0E1DB76A1B00369A7F /* YBBaseViewController.m in Sources */, 68E54F881D9A13540003BF63 /* UIImage+AddFunction.m in Sources */, 68A7FE921D7D602E00F3488D /* AppDelegate.m in Sources */, 68E54F901D9A13D10003BF63 /* YBPasterScrollView.m in Sources */, 68E54FF81D9A6C140003BF63 /* UIImage+SplitImageIntoTwoParts.m in Sources */, 68E54F891D9A13540003BF63 /* UIViewController+Extension.m in Sources */, 68E54FF51D9A6C140003BF63 /* UIImage+Cut.m in Sources */, 68E54FF41D9A6C140003BF63 /* UIImage+Alpha.m in Sources */, 68E54F911D9A13D10003BF63 /* YBPasterView.m in Sources */, 68A7FE8F1D7D602E00F3488D /* main.m in Sources */, 68E54F961D9A20B00003BF63 /* YBCustomButton.m in Sources */, 68E54FF61D9A6C140003BF63 /* UIImage+Resize.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 68A7FE9F1D7D602E00F3488D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 68A7FEA81D7D602E00F3488D /* testPasterImageTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 68A7FEAA1D7D602F00F3488D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 68A7FEB31D7D602F00F3488D /* testPasterImageUITests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 68A7FEA51D7D602E00F3488D /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 68A7FE891D7D602E00F3488D /* testPasterImage */; targetProxy = 68A7FEA41D7D602E00F3488D /* PBXContainerItemProxy */; }; 68A7FEB01D7D602F00F3488D /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 68A7FE891D7D602E00F3488D /* testPasterImage */; targetProxy = 68A7FEAF1D7D602F00F3488D /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ 68A7FE961D7D602E00F3488D /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 68A7FE971D7D602E00F3488D /* Base */, ); name = Main.storyboard; sourceTree = ""; }; 68A7FE9B1D7D602E00F3488D /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( 68A7FE9C1D7D602E00F3488D /* Base */, ); name = LaunchScreen.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 68A7FEB51D7D602F00F3488D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.3; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; name = Debug; }; 68A7FEB61D7D602F00F3488D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.3; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; name = Release; }; 68A7FEB81D7D602F00F3488D /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 0E1D0ACD3D2EAF07D3741914 /* Pods-testPasterImage.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; INFOPLIST_FILE = testPasterImage/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.jiapin.www.testPasterImage; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; }; name = Debug; }; 68A7FEB91D7D602F00F3488D /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = E2D87E7F14BF62318BD7B391 /* Pods-testPasterImage.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; INFOPLIST_FILE = testPasterImage/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.jiapin.www.testPasterImage; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; }; name = Release; }; 68A7FEBB1D7D602F00F3488D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; INFOPLIST_FILE = testPasterImageTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.jiapin.www.testPasterImageTests; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/testPasterImage.app/testPasterImage"; }; name = Debug; }; 68A7FEBC1D7D602F00F3488D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; INFOPLIST_FILE = testPasterImageTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.jiapin.www.testPasterImageTests; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/testPasterImage.app/testPasterImage"; }; name = Release; }; 68A7FEBE1D7D602F00F3488D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { INFOPLIST_FILE = testPasterImageUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.jiapin.www.testPasterImageUITests; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_TARGET_NAME = testPasterImage; }; name = Debug; }; 68A7FEBF1D7D602F00F3488D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { INFOPLIST_FILE = testPasterImageUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.jiapin.www.testPasterImageUITests; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_TARGET_NAME = testPasterImage; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 68A7FE851D7D602E00F3488D /* Build configuration list for PBXProject "testPasterImage" */ = { isa = XCConfigurationList; buildConfigurations = ( 68A7FEB51D7D602F00F3488D /* Debug */, 68A7FEB61D7D602F00F3488D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 68A7FEB71D7D602F00F3488D /* Build configuration list for PBXNativeTarget "testPasterImage" */ = { isa = XCConfigurationList; buildConfigurations = ( 68A7FEB81D7D602F00F3488D /* Debug */, 68A7FEB91D7D602F00F3488D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 68A7FEBA1D7D602F00F3488D /* Build configuration list for PBXNativeTarget "testPasterImageTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 68A7FEBB1D7D602F00F3488D /* Debug */, 68A7FEBC1D7D602F00F3488D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 68A7FEBD1D7D602F00F3488D /* Build configuration list for PBXNativeTarget "testPasterImageUITests" */ = { isa = XCConfigurationList; buildConfigurations = ( 68A7FEBE1D7D602F00F3488D /* Debug */, 68A7FEBF1D7D602F00F3488D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 68A7FE821D7D602E00F3488D /* Project object */; } ================================================ FILE: testPasterImage.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: testPasterImage.xcodeproj/xcuserdata/vipstore.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist ================================================ ================================================ FILE: testPasterImage.xcodeproj/xcuserdata/vipstore.xcuserdatad/xcschemes/testPasterImage.xcscheme ================================================ ================================================ FILE: testPasterImage.xcodeproj/xcuserdata/vipstore.xcuserdatad/xcschemes/xcschememanagement.plist ================================================ SchemeUserState testPasterImage.xcscheme orderHint 0 SuppressBuildableAutocreation 68A7FE891D7D602E00F3488D primary 68A7FEA21D7D602E00F3488D primary 68A7FEAD1D7D602F00F3488D primary ================================================ FILE: testPasterImage.xcodeproj/xcuserdata/wangyingbo.xcuserdatad/xcschemes/testPasterImage.xcscheme ================================================ ================================================ FILE: testPasterImage.xcodeproj/xcuserdata/wangyingbo.xcuserdatad/xcschemes/xcschememanagement.plist ================================================ SchemeUserState testPasterImage.xcscheme orderHint 0 SuppressBuildableAutocreation 68A7FE891D7D602E00F3488D primary 68A7FEA21D7D602E00F3488D primary 68A7FEAD1D7D602F00F3488D primary ================================================ FILE: testPasterImage.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: testPasterImage.xcworkspace/xcshareddata/testPasterImage.xcscmblueprint ================================================ { "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "537B6586F05AEB9F89F52A1E940931332B028804", "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { "1a0beb16-39a9-491a-8432-0dfbb1476d54++7897" : { } }, "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { "537B6586F05AEB9F89F52A1E940931332B028804" : 0, "1a0beb16-39a9-491a-8432-0dfbb1476d54++7897" : 0 }, "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "F1E10107-A592-40B8-B4E3-05CD8A7A80E6", "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { "537B6586F05AEB9F89F52A1E940931332B028804" : "testPasterImage\/", "1a0beb16-39a9-491a-8432-0dfbb1476d54++7897" : "testPasterImage\/testPasterImage\/Libs\/FilterImageLibs\/UIImage-Extensions\/" }, "DVTSourceControlWorkspaceBlueprintNameKey" : "testPasterImage", "DVTSourceControlWorkspaceBlueprintVersion" : 204, "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "testPasterImage.xcworkspace", "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ { "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/svn.duapp.com\/appid9kgedf0yca", "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Subversion", "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "1a0beb16-39a9-491a-8432-0dfbb1476d54++7897" }, { "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/wangyingbo\/YBPasterImage.git", "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "537B6586F05AEB9F89F52A1E940931332B028804" } ] } ================================================ FILE: testPasterImage.xcworkspace/xcuserdata/vipstore.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist ================================================ ================================================ FILE: testPasterImageTests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: testPasterImageTests/testPasterImageTests.m ================================================ // // testPasterImageTests.m // testPasterImageTests // // Created by 王迎博 on 16/9/5. // Copyright © 2016年 王迎博. All rights reserved. // #import @interface testPasterImageTests : XCTestCase @end @implementation testPasterImageTests - (void)setUp { [super setUp]; // Put setup code here. This method is called before the invocation of each test method in the class. } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. [super tearDown]; } - (void)testExample { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct results. } - (void)testPerformanceExample { // This is an example of a performance test case. [self measureBlock:^{ // Put the code you want to measure the time of here. }]; } @end ================================================ FILE: testPasterImageUITests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: testPasterImageUITests/testPasterImageUITests.m ================================================ // // testPasterImageUITests.m // testPasterImageUITests // // Created by 王迎博 on 16/9/5. // Copyright © 2016年 王迎博. All rights reserved. // #import @interface testPasterImageUITests : XCTestCase @end @implementation testPasterImageUITests - (void)setUp { [super setUp]; // Put setup code here. This method is called before the invocation of each test method in the class. // In UI tests it is usually best to stop immediately when a failure occurs. self.continueAfterFailure = NO; // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. [[[XCUIApplication alloc] init] launch]; // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. [super tearDown]; } - (void)testExample { // Use recording to get started writing UI tests. // Use XCTAssert and related functions to verify your tests produce the correct results. } @end