├── LICENSE ├── README.md ├── WCBlock-ObjC.podspec ├── WCBlock.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── zhaoweicheng.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── zhaoweicheng.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── WCBlock ├── NSNotificationCenter+WCBlock.h ├── NSNotificationCenter+WCBlock.m ├── NSObject+WCKVOBlock.h ├── NSObject+WCKVOBlock.m ├── UIAlertView+WCBlock.h ├── UIAlertView+WCBlock.m ├── UIControl+WCBlock.h ├── UIControl+WCBlock.m ├── UIGestureRecognizer+WCBlock.h ├── UIGestureRecognizer+WCBlock.m ├── UISearchBar+WCBlock.h ├── UISearchBar+WCBlock.m ├── UISegmentedControl+WCBlock.h ├── UISegmentedControl+WCBlock.m ├── UISlider+WCBlock.h ├── UISlider+WCBlock.m ├── UISwitch+WCBlock.h ├── UISwitch+WCBlock.m ├── UITextField+WCBlock.h ├── UITextField+WCBlock.m ├── UITextView+WCBlock.h ├── UITextView+WCBlock.m ├── UIView+WCBlock.h ├── UIView+WCBlock.m ├── WCBlock.h ├── WCViewGesture.h └── WCViewGesture.m ├── WCBlockDemo ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── ViewController.h ├── ViewController.m └── main.m ├── WCBlockTests ├── Info.plist └── WCBlockTests.m └── WCBlockUITests ├── Info.plist └── WCBlockUITests.m /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 W.C.Z 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## WCBlock 2 | 3 | * A lightweight event listener library of UIKit , It is non-invasive and make your code simple and easy . It provides friendly event listener callback support for event response to NotificationCenter、KVO、Target-action、GestureRecognizer、UIView、UIButton、UITextField and so on . As a result, it improve the cohesion degree of code, make coding easier and improve development efficiency for you. 4 | ## How To Get Started 5 | 6 | ## Manual import 7 | 8 | * Drag the folder "WCBlock" to your project 9 | * Import the main file:`#import "WCBlock.h"` 10 | 11 | ## Installation with CocoaPods 12 | 13 | ```ruby 14 | source 'https://github.com/manakiaHk/WCBlock.git' 15 | platform :ios, '7.0' 16 | 17 | target 'TargetName' do 18 | pod 'WCBlock-ObjC' 19 | end 20 | ``` 21 | 22 | Then, run the following command: 23 | 24 | ```bash 25 | $ pod install 26 | ``` 27 | Import the main file: 28 | 29 | ```objective-c 30 | #import "WCBlock.h" 31 | 32 | ``` 33 | 34 | ## Usage 35 | 36 | 37 | Bind block callback for view 38 | 39 | ```objective-c 40 |     41 |   [view wc_bindViewTapBlockNext:^(UIView *view, WCViewTap *tap) { 42 |        // your code... 43 |    }]; 44 | 45 |   [imageView wc_bindViewTapBlockNext:^(UIView *view, WCViewTap *tap) { 46 | // your code... 47 | }]; 48 |    imageView.userInteractionEnabled = YES;//for imageView, the proprty userInteractionEnabled defualt value is NO,this is same as Apple API. 49 |     50 |    ///You can set it's properties and delegate through the return value. 51 |    WCViewTap *tap = [view wc_bindViewTapBlockNext:^(UIView *view, WCViewTap *tap) { 52 | // your code... 53 | }]; 54 |   tap.numberOfTapsRequired = 2; 55 |    tap.delegate = self; 56 | 57 |    ///You can also bind other gestures block callback,e.g: 58 |    [view wc_bindViewPanBlockNext:^(UIView *view, WCViewPan *pan) { 59 |        // your code... 60 | }]; 61 |   [view wc_bindViewLongPressBlockNext:^(UIView *view, WCViewLongPress *longPress) { 62 |        // your code... 63 | }]; 64 | [view wc_bindViewRotationBlockNext:^(UIView *view, WCViewRotation *rotation) { 65 | // your code... 66 |        //NSLog(@"%0.2f",rotation.rotation);//旋转角度 67 |        //NSLog(@"%0.2f",rotation.velocity);//旋转速度 68 | }]; 69 | 70 | ``` 71 | 72 | Bind block callback for gestureRecognizer 73 | 74 | ```objective-c 75 | UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]init]; 76 | [tapGes wc_bindGestureBlockNext:^(UIGestureRecognizer *sender) { 77 | // your code... 78 | }]; 79 | UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc]init]; 80 | [swipeGesture wc_bindGestureBlockNext:^(UIGestureRecognizer *sender) { 81 | // your code... 82 | }]; 83 | UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc]init]; 84 | [rotationGesture wc_bindGestureBlockNext:^(UIGestureRecognizer *sender) { 85 | // your code... 86 | }]; 87 | UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc]init]; 88 | [panGesture wc_bindGestureBlockNext:^(UIGestureRecognizer *sender) { 89 | // your code... 90 | }]; 91 |   /// And so on ... 92 | ``` 93 |     94 | You can bind block callback for button、segmentedControl、 slider  and so on. e.g: 95 | 96 | ```objective-c 97 |    UIButton *button = [[UIButton alloc]initWithFrame:btnFrame]; 98 | [button wc_bindForControlEvents:UIControlEventTouchUpInside blockNext:^(id sender) { 99 |       // your code... 100 |    }]; 101 | 102 | UISegmentedControl *segment = [[UISegmentedControl alloc]initWithItems:@[@"title0",@"title1",@"title2"]]; 103 | [segment wc_bindSegmentControlValueChangedBlockNext:^(NSInteger selectedIndex) { 104 |        // your code... 105 | }]; 106 | 107 |    //Tip: As in the past, wcblock will capture external variables, which may lead to circular references. You need to use __weak to avoid such a situation.   108 | 109 |    UISlider *slider = [[UISlider alloc]initWithFrame:sliderFrame]; 110 | __weak typeof(self) weakSelf = self; 111 | [slider wc_bindSliderValueChangedBlockNext:^(CGFloat value) { 112 | __strong typeof(weakSelf) self = weakSelf; 113 |      [self sendAMesseage]; 114 |    }]; 115 | 116 |    UIAlertView *alerView = [[UIAlertView alloc]initWithTitle:@"title" message:@"message" delegate:nil     cancelButtonTitle:@"cancle" otherButtonTitles:@"ok", nil]; 117 | [alerView wc_bindAlertButtonClickedBlockNext:^(NSInteger index) { 118 |       // your code... 119 | }]; 120 | [alerView show]; 121 | ``` 122 | You can bind block callback for textfiled 、searchBar、textView 123 | 124 | ```objective-c 125 | UITextField *textfiled = [[UITextField alloc]initWithFrame:textFieldframe]; 126 | [textfiled wc_bindTextFieldEditingChangedBlockNext:^(UITextField *textField, NSString *value) { 127 | // your code... 128 |        //NSLog(@"textfiled text:%@",value); 129 | }]; 130 | [textfiled wc_bindTextFieldShouldChangeCharactersHandlerBlock:^BOOL(UITextField *textField, NSRange shouldChangeCharactersInRange, NSString *replacementString) { 131 |       // your code... 132 | return YES; 133 | }]; 134 | [textfiled wc_bindTextFieldEditingDidBeginBlockNext:^(UITextField *textField) { 135 |       // your code... 136 |       //textfiled did begin editing... 137 |     }]; 138 | [textfiled wc_bindTextFieldEditingDidEndBlockNext:^(UITextField *textField) { 139 | // your code... 140 |        //textfiled did end editing... 141 | }]; 142 | 143 | UISearchBar *searchBar = [[UISearchBar alloc]init]; 144 | [searchBar wc_bindSearchBarTextDidBeginEditingBlockNext:^(UISearchBar *searchBar) { 145 | // your code... 146 | }]; 147 | [searchBar wc_bindSearchBarTextDidChangeBlockNext:^(UISearchBar *searchBar, NSString *searchText) { 148 | // your code... 149 | }]; 150 | [searchBar wc_bindSearchBarTextDidEndEditingBlockNext:^(UISearchBar *searchBar) { 151 | // your code... 152 | }]; 153 | [searchBar wc_bindSearchBarCancelButtonClickedBlockNext:^(UISearchBar *searchBar) { 154 | // your code... 155 | }]; 156 | [searchBar wc_bindSearchBarShouldChangeCharactersHandlerBlock:^BOOL(UISearchBar *searchBar, NSRange inRange, NSString *replacementString) { 157 | //your code... 158 | return YES; 159 | }]; 160 | /// and so on ... 161 | 162 | UITextView *textView = [[UITextView alloc]init]; 163 | [textView wc_bindTextViewEditingChangedBlockNext:^(UITextView *textView, NSString *value) { 164 | //your code... 165 | }]; 166 | [textView wc_bindTextViewShouldChangeTextWithHandlerBlock:^BOOL(UITextView *textView, NSRange inRange, NSString *replacementText) { 167 | //your code... 168 | return YES; 169 | }]; 170 | if (@available(iOS 10.0, *)) { 171 | [textView wc_bindTextViewShouldInteractWithUrlHandlerBlock:^BOOL(UITextView *textView, NSURL *url, NSRange inRange, UITextItemInteraction interaction) { 172 | //your code... 173 | return YES; 174 | }]; 175 | }; 176 | /// And so on ... 177 | 178 | ``` 179 | 180 | Bind block callback for notificationCenter ,and observer objects will be automatically managed for you to 181 |  be removed 182 | 183 | ```objective-c 184 | 185 |    [WCNotificationCenter wc_addObserverForName:@"wc_note_demo" object:nil contextObj:self blockNext:^(NSNotification * _Nullable note) { 186 |       // your code... 187 |       //NSLog(@"%@",note.userInfo[@"note_demo"]); 188 | }]; 189 | 190 |     ///Bind block callback for asynchronous notificationCenter 191 |    [WCNotificationCenter wc_addObserverForName:@"wc_note_demo" object:nil contextObj:self queue:[NSOperationQueue mainQueue] blockNext:^(NSNotification * _Nullable note) { 192 | // your code... 193 | }]; 194 | 195 | ///notification test demo 196 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 197 | [WCNotificationCenter postNotificationName:@"wc_note_demo" object:nil userInfo:@{@"note_demo":@"observer objects will be automatically managed for you to be removed"}]; 198 | // your code... 199 | }); 200 | 201 | ``` 202 | Bind block callback for KVO. 203 | 204 | ```objective-c 205 |   [_anObject wc_addObserverForKeyPath:@"keypath0" valueBlockNext:^(NSString *keypath, id ofObj, id oldValue, id newValue) { 206 | //your code... 207 | }]; 208 | [_anObject wc_addObserverForKeyPaths:@[@"keypath1",@"keypath2"] valueBlockNext:^(NSString *keypath, id ofObj, id oldValue, id newValue) { 209 | if ([keypath isEqualToString:@"keypath1"]) { 210 | //your code... 211 | }else if([keypath isEqualToString:@"keypath2"]){ 212 | //your code... 213 | }else; 214 | }]; 215 | [_anObject wc_addObserverForKeyPath:@"keypath3" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld changeBlockNext:^(NSString *keypath, id ofObj, NSDictionary *change) { 216 | //your code... 217 | }]; 218 | ``` 219 |  Same as to Apple API, you need to remove key value observers for your objects , like this. 220 | 221 | ```objective-c 222 | 223 |   - (void)dealloc { 224 |     [_anObject wc_removeObserverForKeyPath:@"keypath0"]; 225 |     [_anObject wc_removeObserverForKeyPath:@"keypath1"]; 226 |     //also 227 |     [_anObject wc_removeObserverForKeyPaths:@[@"keypath2",@"keypath3"]]; 228 | } 229 | 230 | ``` 231 | Tip: you can bind more than one same type of blocks for an object of yours, and each blocks will be called, because you may use them in different places at the same time. so, you know that WCBlock can do this ,but except the block of handler. For handler block, it can be bound only one same type handler block, because you dont hope to operate an object in many places simultaneously. so when an object is bound more than one same type handler block , it only the last one is valid. E.g: 232 | 233 | Blocks as the follow will be called every one. 234 | 235 | ```objective-c 236 | 237 | [view wc_bindViewTapBlockNext:^(UIView *view, WCViewTap *tap) { 238 | // your code... 239 |       // NSLog(@"0--view taped"); 240 | }]; 241 | [view wc_bindViewTapBlockNext:^(UIView *view, WCViewTap *tap) { 242 |       // NSLog(@"1--view taped"); 243 | }]; 244 | [view wc_bindViewTapBlockNext:^(UIView *view, WCViewTap *tap) { 245 |       // NSLog(@"2--view taped"); 246 | }]; 247 | [textfiled wc_bindTextFieldEditingChangedBlockNext:^(UITextField *textField, NSString *value) { 248 |       //  NSLog(@"0--textfiled text:%@",value); 249 | }]; 250 | [textfiled wc_bindTextFieldEditingChangedBlockNext:^(UITextField *textField, NSString *value) { 251 |        // NSLog(@"1--textfiled text:%@",value); 252 | }]; 253 | [textfiled wc_bindTextFieldEditingChangedBlockNext:^(UITextField *textField, NSString *value) { 254 |        // NSLog(@"2--textfiled text:%@",value); 255 | }]; 256 | 257 | ``` 258 | These handler blocks as follow ,only last one will be effective(becuse they are handler block , you need be knowed for this) 259 | 260 | ```objective-c 261 | 262 | [textfiled wc_bindTextFieldShouldChangeCharactersHandlerBlock:^BOOL(UITextField *textField, NSRange shouldChangeCharactersInRange, NSString *replacementString) { 263 | if ([replacementString containsString:@"a"]) { 264 | return NO; 265 | } 266 | return YES; 267 | }]; 268 | [textfiled wc_bindTextFieldShouldChangeCharactersHandlerBlock:^BOOL(UITextField *textField, NSRange shouldChangeCharactersInRange, NSString *replacementString) { 269 | if ([replacementString containsString:@"b"]) { 270 | return NO; 271 | } 272 | return YES; 273 | }]; 274 | [textfiled wc_bindTextFieldShouldChangeCharactersHandlerBlock:^BOOL(UITextField *textField, NSRange shouldChangeCharactersInRange, NSString *replacementString) { 275 | if ([replacementString containsString:@"c"]) { 276 | return NO; 277 | } 278 | return YES; 279 | }]; 280 | 281 | ``` 282 | 283 | ### thanks for your reading,and welcome your advice. 284 | ### Regards. 285 | 286 | ## end 287 | 288 | 289 | -------------------------------------------------------------------------------- /WCBlock-ObjC.podspec: -------------------------------------------------------------------------------- 1 | 2 | Pod::Spec.new do |s| 3 | s.name = "WCBlock-ObjC" 4 | s.version = "1.0.4" 5 | s.summary = "a lightweight block library of UIKit extension" 6 | s.description = <<-DESC 7 | the library will make your code more simple , and you will love it for ever 8 | DESC 9 | s.homepage = "https://github.com/manakiaHk/WCBlock" 10 | s.license = "MIT" 11 | s.author = { "manakiaHk" => "1085415288@qq.com" } 12 | s.platform = :ios 13 | s.platform = :ios, "9.0" 14 | s.source = { :git => "https://github.com/manakiaHk/WCBlock.git", :tag => s.version } 15 | s.source_files = "WCBlock/**/*.{h,m}" 16 | 17 | # s.public_header_files = "Classes/**/*.h" 18 | s.requires_arc = true 19 | end -------------------------------------------------------------------------------- /WCBlock.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 35CAF9A2208F410800163DED /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 35CAF9A1208F410800163DED /* AppDelegate.m */; }; 11 | 35CAF9A5208F410800163DED /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 35CAF9A4208F410800163DED /* ViewController.m */; }; 12 | 35CAF9A8208F410800163DED /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 35CAF9A6208F410800163DED /* Main.storyboard */; }; 13 | 35CAF9AA208F410800163DED /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 35CAF9A9208F410800163DED /* Assets.xcassets */; }; 14 | 35CAF9AD208F410800163DED /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 35CAF9AB208F410800163DED /* LaunchScreen.storyboard */; }; 15 | 35CAF9B0208F410800163DED /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 35CAF9AF208F410800163DED /* main.m */; }; 16 | 35CAF9BA208F410900163DED /* WCBlockTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 35CAF9B9208F410900163DED /* WCBlockTests.m */; }; 17 | 35CAF9C5208F410900163DED /* WCBlockUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 35CAF9C4208F410900163DED /* WCBlockUITests.m */; }; 18 | 35CAFD8C2094000700163DED /* UIControl+WCBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 35CAFD792094000500163DED /* UIControl+WCBlock.m */; }; 19 | 35CAFD8D2094000700163DED /* UISegmentedControl+WCBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 35CAFD7C2094000500163DED /* UISegmentedControl+WCBlock.m */; }; 20 | 35CAFD8E2094000700163DED /* UITextView+WCBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 35CAFD802094000600163DED /* UITextView+WCBlock.m */; }; 21 | 35CAFD8F2094000700163DED /* UISlider+WCBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 35CAFD822094000600163DED /* UISlider+WCBlock.m */; }; 22 | 35CAFD902094000700163DED /* UITextField+WCBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 35CAFD832094000600163DED /* UITextField+WCBlock.m */; }; 23 | 35CAFD912094000700163DED /* UIGestureRecognizer+WCBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 35CAFD852094000600163DED /* UIGestureRecognizer+WCBlock.m */; }; 24 | 35CAFD922094000700163DED /* UISwitch+WCBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 35CAFD882094000600163DED /* UISwitch+WCBlock.m */; }; 25 | 35CAFD932094000700163DED /* UIAlertView+WCBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 35CAFD892094000600163DED /* UIAlertView+WCBlock.m */; }; 26 | 35CAFD942094000700163DED /* UIView+WCBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 35CAFD8A2094000600163DED /* UIView+WCBlock.m */; }; 27 | 35CAFD952094000700163DED /* NSObject+WCKVOBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 35CAFD8B2094000700163DED /* NSObject+WCKVOBlock.m */; }; 28 | 35CAFD982094003400163DED /* NSNotificationCenter+WCBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 35CAFD972094003400163DED /* NSNotificationCenter+WCBlock.m */; }; 29 | 35CAFDA820957D9E00163DED /* WCViewGesture.m in Sources */ = {isa = PBXBuildFile; fileRef = 35CAFDA720957D9E00163DED /* WCViewGesture.m */; }; 30 | 35CAFDAB2095AC2600163DED /* UISearchBar+WCBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 35CAFDAA2095AC2600163DED /* UISearchBar+WCBlock.m */; }; 31 | /* End PBXBuildFile section */ 32 | 33 | /* Begin PBXContainerItemProxy section */ 34 | 35CAF9B6208F410900163DED /* PBXContainerItemProxy */ = { 35 | isa = PBXContainerItemProxy; 36 | containerPortal = 35CAF995208F410800163DED /* Project object */; 37 | proxyType = 1; 38 | remoteGlobalIDString = 35CAF99C208F410800163DED; 39 | remoteInfo = WCBlock; 40 | }; 41 | 35CAF9C1208F410900163DED /* PBXContainerItemProxy */ = { 42 | isa = PBXContainerItemProxy; 43 | containerPortal = 35CAF995208F410800163DED /* Project object */; 44 | proxyType = 1; 45 | remoteGlobalIDString = 35CAF99C208F410800163DED; 46 | remoteInfo = WCBlock; 47 | }; 48 | /* End PBXContainerItemProxy section */ 49 | 50 | /* Begin PBXFileReference section */ 51 | 35CAF99D208F410800163DED /* WCBlock.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WCBlock.app; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 35CAF9A0208F410800163DED /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 53 | 35CAF9A1208F410800163DED /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 54 | 35CAF9A3208F410800163DED /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 55 | 35CAF9A4208F410800163DED /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 56 | 35CAF9A7208F410800163DED /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 57 | 35CAF9A9208F410800163DED /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 58 | 35CAF9AC208F410800163DED /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 59 | 35CAF9AE208F410800163DED /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 60 | 35CAF9AF208F410800163DED /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 61 | 35CAF9B5208F410900163DED /* WCBlockTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = WCBlockTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 62 | 35CAF9B9208F410900163DED /* WCBlockTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WCBlockTests.m; sourceTree = ""; }; 63 | 35CAF9BB208F410900163DED /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 64 | 35CAF9C0208F410900163DED /* WCBlockUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = WCBlockUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 65 | 35CAF9C4208F410900163DED /* WCBlockUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WCBlockUITests.m; sourceTree = ""; }; 66 | 35CAF9C6208F410900163DED /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 67 | 35CAFD772094000500163DED /* UISegmentedControl+WCBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UISegmentedControl+WCBlock.h"; sourceTree = ""; }; 68 | 35CAFD782094000500163DED /* UITextView+WCBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UITextView+WCBlock.h"; sourceTree = ""; }; 69 | 35CAFD792094000500163DED /* UIControl+WCBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIControl+WCBlock.m"; sourceTree = ""; }; 70 | 35CAFD7A2094000500163DED /* UITextField+WCBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UITextField+WCBlock.h"; sourceTree = ""; }; 71 | 35CAFD7B2094000500163DED /* UIGestureRecognizer+WCBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIGestureRecognizer+WCBlock.h"; sourceTree = ""; }; 72 | 35CAFD7C2094000500163DED /* UISegmentedControl+WCBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UISegmentedControl+WCBlock.m"; sourceTree = ""; }; 73 | 35CAFD7D2094000500163DED /* NSObject+WCKVOBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+WCKVOBlock.h"; sourceTree = ""; }; 74 | 35CAFD7E2094000500163DED /* WCBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WCBlock.h; sourceTree = ""; }; 75 | 35CAFD7F2094000600163DED /* UISlider+WCBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UISlider+WCBlock.h"; sourceTree = ""; }; 76 | 35CAFD802094000600163DED /* UITextView+WCBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UITextView+WCBlock.m"; sourceTree = ""; }; 77 | 35CAFD812094000600163DED /* UIControl+WCBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIControl+WCBlock.h"; sourceTree = ""; }; 78 | 35CAFD822094000600163DED /* UISlider+WCBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UISlider+WCBlock.m"; sourceTree = ""; }; 79 | 35CAFD832094000600163DED /* UITextField+WCBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UITextField+WCBlock.m"; sourceTree = ""; }; 80 | 35CAFD842094000600163DED /* UIAlertView+WCBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIAlertView+WCBlock.h"; sourceTree = ""; }; 81 | 35CAFD852094000600163DED /* UIGestureRecognizer+WCBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIGestureRecognizer+WCBlock.m"; sourceTree = ""; }; 82 | 35CAFD862094000600163DED /* UIView+WCBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+WCBlock.h"; sourceTree = ""; }; 83 | 35CAFD872094000600163DED /* UISwitch+WCBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UISwitch+WCBlock.h"; sourceTree = ""; }; 84 | 35CAFD882094000600163DED /* UISwitch+WCBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UISwitch+WCBlock.m"; sourceTree = ""; }; 85 | 35CAFD892094000600163DED /* UIAlertView+WCBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIAlertView+WCBlock.m"; sourceTree = ""; }; 86 | 35CAFD8A2094000600163DED /* UIView+WCBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+WCBlock.m"; sourceTree = ""; }; 87 | 35CAFD8B2094000700163DED /* NSObject+WCKVOBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+WCKVOBlock.m"; sourceTree = ""; }; 88 | 35CAFD962094003400163DED /* NSNotificationCenter+WCBlock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSNotificationCenter+WCBlock.h"; sourceTree = ""; }; 89 | 35CAFD972094003400163DED /* NSNotificationCenter+WCBlock.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSNotificationCenter+WCBlock.m"; sourceTree = ""; }; 90 | 35CAFDA620957D9E00163DED /* WCViewGesture.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WCViewGesture.h; sourceTree = ""; }; 91 | 35CAFDA720957D9E00163DED /* WCViewGesture.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WCViewGesture.m; sourceTree = ""; }; 92 | 35CAFDA92095AC2600163DED /* UISearchBar+WCBlock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UISearchBar+WCBlock.h"; sourceTree = ""; }; 93 | 35CAFDAA2095AC2600163DED /* UISearchBar+WCBlock.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UISearchBar+WCBlock.m"; sourceTree = ""; }; 94 | /* End PBXFileReference section */ 95 | 96 | /* Begin PBXFrameworksBuildPhase section */ 97 | 35CAF99A208F410800163DED /* Frameworks */ = { 98 | isa = PBXFrameworksBuildPhase; 99 | buildActionMask = 2147483647; 100 | files = ( 101 | ); 102 | runOnlyForDeploymentPostprocessing = 0; 103 | }; 104 | 35CAF9B2208F410900163DED /* Frameworks */ = { 105 | isa = PBXFrameworksBuildPhase; 106 | buildActionMask = 2147483647; 107 | files = ( 108 | ); 109 | runOnlyForDeploymentPostprocessing = 0; 110 | }; 111 | 35CAF9BD208F410900163DED /* Frameworks */ = { 112 | isa = PBXFrameworksBuildPhase; 113 | buildActionMask = 2147483647; 114 | files = ( 115 | ); 116 | runOnlyForDeploymentPostprocessing = 0; 117 | }; 118 | /* End PBXFrameworksBuildPhase section */ 119 | 120 | /* Begin PBXGroup section */ 121 | 35CAF994208F410800163DED = { 122 | isa = PBXGroup; 123 | children = ( 124 | 35CAF9D2208F420A00163DED /* WCBlock */, 125 | 35CAF99F208F410800163DED /* WCBlockDemo */, 126 | 35CAF9B8208F410900163DED /* WCBlockTests */, 127 | 35CAF9C3208F410900163DED /* WCBlockUITests */, 128 | 35CAF99E208F410800163DED /* Products */, 129 | ); 130 | sourceTree = ""; 131 | }; 132 | 35CAF99E208F410800163DED /* Products */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | 35CAF99D208F410800163DED /* WCBlock.app */, 136 | 35CAF9B5208F410900163DED /* WCBlockTests.xctest */, 137 | 35CAF9C0208F410900163DED /* WCBlockUITests.xctest */, 138 | ); 139 | name = Products; 140 | sourceTree = ""; 141 | }; 142 | 35CAF99F208F410800163DED /* WCBlockDemo */ = { 143 | isa = PBXGroup; 144 | children = ( 145 | 35CAF9A0208F410800163DED /* AppDelegate.h */, 146 | 35CAF9A1208F410800163DED /* AppDelegate.m */, 147 | 35CAF9A3208F410800163DED /* ViewController.h */, 148 | 35CAF9A4208F410800163DED /* ViewController.m */, 149 | 35CAF9A6208F410800163DED /* Main.storyboard */, 150 | 35CAF9A9208F410800163DED /* Assets.xcassets */, 151 | 35CAF9AB208F410800163DED /* LaunchScreen.storyboard */, 152 | 35CAF9AE208F410800163DED /* Info.plist */, 153 | 35CAF9AF208F410800163DED /* main.m */, 154 | ); 155 | path = WCBlockDemo; 156 | sourceTree = ""; 157 | }; 158 | 35CAF9B8208F410900163DED /* WCBlockTests */ = { 159 | isa = PBXGroup; 160 | children = ( 161 | 35CAF9B9208F410900163DED /* WCBlockTests.m */, 162 | 35CAF9BB208F410900163DED /* Info.plist */, 163 | ); 164 | path = WCBlockTests; 165 | sourceTree = ""; 166 | }; 167 | 35CAF9C3208F410900163DED /* WCBlockUITests */ = { 168 | isa = PBXGroup; 169 | children = ( 170 | 35CAF9C4208F410900163DED /* WCBlockUITests.m */, 171 | 35CAF9C6208F410900163DED /* Info.plist */, 172 | ); 173 | path = WCBlockUITests; 174 | sourceTree = ""; 175 | }; 176 | 35CAF9D2208F420A00163DED /* WCBlock */ = { 177 | isa = PBXGroup; 178 | children = ( 179 | 35CAFD7E2094000500163DED /* WCBlock.h */, 180 | 35CAFD962094003400163DED /* NSNotificationCenter+WCBlock.h */, 181 | 35CAFD972094003400163DED /* NSNotificationCenter+WCBlock.m */, 182 | 35CAFD862094000600163DED /* UIView+WCBlock.h */, 183 | 35CAFD8A2094000600163DED /* UIView+WCBlock.m */, 184 | 35CAFD842094000600163DED /* UIAlertView+WCBlock.h */, 185 | 35CAFD892094000600163DED /* UIAlertView+WCBlock.m */, 186 | 35CAFD812094000600163DED /* UIControl+WCBlock.h */, 187 | 35CAFD792094000500163DED /* UIControl+WCBlock.m */, 188 | 35CAFD7D2094000500163DED /* NSObject+WCKVOBlock.h */, 189 | 35CAFD8B2094000700163DED /* NSObject+WCKVOBlock.m */, 190 | 35CAFD7B2094000500163DED /* UIGestureRecognizer+WCBlock.h */, 191 | 35CAFD852094000600163DED /* UIGestureRecognizer+WCBlock.m */, 192 | 35CAFD772094000500163DED /* UISegmentedControl+WCBlock.h */, 193 | 35CAFD7C2094000500163DED /* UISegmentedControl+WCBlock.m */, 194 | 35CAFD7F2094000600163DED /* UISlider+WCBlock.h */, 195 | 35CAFD822094000600163DED /* UISlider+WCBlock.m */, 196 | 35CAFD872094000600163DED /* UISwitch+WCBlock.h */, 197 | 35CAFD882094000600163DED /* UISwitch+WCBlock.m */, 198 | 35CAFD7A2094000500163DED /* UITextField+WCBlock.h */, 199 | 35CAFD832094000600163DED /* UITextField+WCBlock.m */, 200 | 35CAFD782094000500163DED /* UITextView+WCBlock.h */, 201 | 35CAFD802094000600163DED /* UITextView+WCBlock.m */, 202 | 35CAFDA92095AC2600163DED /* UISearchBar+WCBlock.h */, 203 | 35CAFDAA2095AC2600163DED /* UISearchBar+WCBlock.m */, 204 | 35CAFDA620957D9E00163DED /* WCViewGesture.h */, 205 | 35CAFDA720957D9E00163DED /* WCViewGesture.m */, 206 | ); 207 | path = WCBlock; 208 | sourceTree = ""; 209 | }; 210 | /* End PBXGroup section */ 211 | 212 | /* Begin PBXNativeTarget section */ 213 | 35CAF99C208F410800163DED /* WCBlock */ = { 214 | isa = PBXNativeTarget; 215 | buildConfigurationList = 35CAF9C9208F410900163DED /* Build configuration list for PBXNativeTarget "WCBlock" */; 216 | buildPhases = ( 217 | 35CAF999208F410800163DED /* Sources */, 218 | 35CAF99A208F410800163DED /* Frameworks */, 219 | 35CAF99B208F410800163DED /* Resources */, 220 | ); 221 | buildRules = ( 222 | ); 223 | dependencies = ( 224 | ); 225 | name = WCBlock; 226 | productName = WCBlock; 227 | productReference = 35CAF99D208F410800163DED /* WCBlock.app */; 228 | productType = "com.apple.product-type.application"; 229 | }; 230 | 35CAF9B4208F410900163DED /* WCBlockTests */ = { 231 | isa = PBXNativeTarget; 232 | buildConfigurationList = 35CAF9CC208F410900163DED /* Build configuration list for PBXNativeTarget "WCBlockTests" */; 233 | buildPhases = ( 234 | 35CAF9B1208F410900163DED /* Sources */, 235 | 35CAF9B2208F410900163DED /* Frameworks */, 236 | 35CAF9B3208F410900163DED /* Resources */, 237 | ); 238 | buildRules = ( 239 | ); 240 | dependencies = ( 241 | 35CAF9B7208F410900163DED /* PBXTargetDependency */, 242 | ); 243 | name = WCBlockTests; 244 | productName = WCBlockTests; 245 | productReference = 35CAF9B5208F410900163DED /* WCBlockTests.xctest */; 246 | productType = "com.apple.product-type.bundle.unit-test"; 247 | }; 248 | 35CAF9BF208F410900163DED /* WCBlockUITests */ = { 249 | isa = PBXNativeTarget; 250 | buildConfigurationList = 35CAF9CF208F410900163DED /* Build configuration list for PBXNativeTarget "WCBlockUITests" */; 251 | buildPhases = ( 252 | 35CAF9BC208F410900163DED /* Sources */, 253 | 35CAF9BD208F410900163DED /* Frameworks */, 254 | 35CAF9BE208F410900163DED /* Resources */, 255 | ); 256 | buildRules = ( 257 | ); 258 | dependencies = ( 259 | 35CAF9C2208F410900163DED /* PBXTargetDependency */, 260 | ); 261 | name = WCBlockUITests; 262 | productName = WCBlockUITests; 263 | productReference = 35CAF9C0208F410900163DED /* WCBlockUITests.xctest */; 264 | productType = "com.apple.product-type.bundle.ui-testing"; 265 | }; 266 | /* End PBXNativeTarget section */ 267 | 268 | /* Begin PBXProject section */ 269 | 35CAF995208F410800163DED /* Project object */ = { 270 | isa = PBXProject; 271 | attributes = { 272 | LastUpgradeCheck = 0920; 273 | ORGANIZATIONNAME = weichengz; 274 | TargetAttributes = { 275 | 35CAF99C208F410800163DED = { 276 | CreatedOnToolsVersion = 9.2; 277 | ProvisioningStyle = Automatic; 278 | }; 279 | 35CAF9B4208F410900163DED = { 280 | CreatedOnToolsVersion = 9.2; 281 | ProvisioningStyle = Automatic; 282 | TestTargetID = 35CAF99C208F410800163DED; 283 | }; 284 | 35CAF9BF208F410900163DED = { 285 | CreatedOnToolsVersion = 9.2; 286 | ProvisioningStyle = Automatic; 287 | TestTargetID = 35CAF99C208F410800163DED; 288 | }; 289 | }; 290 | }; 291 | buildConfigurationList = 35CAF998208F410800163DED /* Build configuration list for PBXProject "WCBlock" */; 292 | compatibilityVersion = "Xcode 8.0"; 293 | developmentRegion = en; 294 | hasScannedForEncodings = 0; 295 | knownRegions = ( 296 | en, 297 | Base, 298 | ); 299 | mainGroup = 35CAF994208F410800163DED; 300 | productRefGroup = 35CAF99E208F410800163DED /* Products */; 301 | projectDirPath = ""; 302 | projectRoot = ""; 303 | targets = ( 304 | 35CAF99C208F410800163DED /* WCBlock */, 305 | 35CAF9B4208F410900163DED /* WCBlockTests */, 306 | 35CAF9BF208F410900163DED /* WCBlockUITests */, 307 | ); 308 | }; 309 | /* End PBXProject section */ 310 | 311 | /* Begin PBXResourcesBuildPhase section */ 312 | 35CAF99B208F410800163DED /* Resources */ = { 313 | isa = PBXResourcesBuildPhase; 314 | buildActionMask = 2147483647; 315 | files = ( 316 | 35CAF9AD208F410800163DED /* LaunchScreen.storyboard in Resources */, 317 | 35CAF9AA208F410800163DED /* Assets.xcassets in Resources */, 318 | 35CAF9A8208F410800163DED /* Main.storyboard in Resources */, 319 | ); 320 | runOnlyForDeploymentPostprocessing = 0; 321 | }; 322 | 35CAF9B3208F410900163DED /* Resources */ = { 323 | isa = PBXResourcesBuildPhase; 324 | buildActionMask = 2147483647; 325 | files = ( 326 | ); 327 | runOnlyForDeploymentPostprocessing = 0; 328 | }; 329 | 35CAF9BE208F410900163DED /* Resources */ = { 330 | isa = PBXResourcesBuildPhase; 331 | buildActionMask = 2147483647; 332 | files = ( 333 | ); 334 | runOnlyForDeploymentPostprocessing = 0; 335 | }; 336 | /* End PBXResourcesBuildPhase section */ 337 | 338 | /* Begin PBXSourcesBuildPhase section */ 339 | 35CAF999208F410800163DED /* Sources */ = { 340 | isa = PBXSourcesBuildPhase; 341 | buildActionMask = 2147483647; 342 | files = ( 343 | 35CAFD982094003400163DED /* NSNotificationCenter+WCBlock.m in Sources */, 344 | 35CAFD942094000700163DED /* UIView+WCBlock.m in Sources */, 345 | 35CAFD932094000700163DED /* UIAlertView+WCBlock.m in Sources */, 346 | 35CAFD912094000700163DED /* UIGestureRecognizer+WCBlock.m in Sources */, 347 | 35CAF9A5208F410800163DED /* ViewController.m in Sources */, 348 | 35CAFD8D2094000700163DED /* UISegmentedControl+WCBlock.m in Sources */, 349 | 35CAFD8C2094000700163DED /* UIControl+WCBlock.m in Sources */, 350 | 35CAF9B0208F410800163DED /* main.m in Sources */, 351 | 35CAFD922094000700163DED /* UISwitch+WCBlock.m in Sources */, 352 | 35CAFDAB2095AC2600163DED /* UISearchBar+WCBlock.m in Sources */, 353 | 35CAF9A2208F410800163DED /* AppDelegate.m in Sources */, 354 | 35CAFD8F2094000700163DED /* UISlider+WCBlock.m in Sources */, 355 | 35CAFD8E2094000700163DED /* UITextView+WCBlock.m in Sources */, 356 | 35CAFD902094000700163DED /* UITextField+WCBlock.m in Sources */, 357 | 35CAFDA820957D9E00163DED /* WCViewGesture.m in Sources */, 358 | 35CAFD952094000700163DED /* NSObject+WCKVOBlock.m in Sources */, 359 | ); 360 | runOnlyForDeploymentPostprocessing = 0; 361 | }; 362 | 35CAF9B1208F410900163DED /* Sources */ = { 363 | isa = PBXSourcesBuildPhase; 364 | buildActionMask = 2147483647; 365 | files = ( 366 | 35CAF9BA208F410900163DED /* WCBlockTests.m in Sources */, 367 | ); 368 | runOnlyForDeploymentPostprocessing = 0; 369 | }; 370 | 35CAF9BC208F410900163DED /* Sources */ = { 371 | isa = PBXSourcesBuildPhase; 372 | buildActionMask = 2147483647; 373 | files = ( 374 | 35CAF9C5208F410900163DED /* WCBlockUITests.m in Sources */, 375 | ); 376 | runOnlyForDeploymentPostprocessing = 0; 377 | }; 378 | /* End PBXSourcesBuildPhase section */ 379 | 380 | /* Begin PBXTargetDependency section */ 381 | 35CAF9B7208F410900163DED /* PBXTargetDependency */ = { 382 | isa = PBXTargetDependency; 383 | target = 35CAF99C208F410800163DED /* WCBlock */; 384 | targetProxy = 35CAF9B6208F410900163DED /* PBXContainerItemProxy */; 385 | }; 386 | 35CAF9C2208F410900163DED /* PBXTargetDependency */ = { 387 | isa = PBXTargetDependency; 388 | target = 35CAF99C208F410800163DED /* WCBlock */; 389 | targetProxy = 35CAF9C1208F410900163DED /* PBXContainerItemProxy */; 390 | }; 391 | /* End PBXTargetDependency section */ 392 | 393 | /* Begin PBXVariantGroup section */ 394 | 35CAF9A6208F410800163DED /* Main.storyboard */ = { 395 | isa = PBXVariantGroup; 396 | children = ( 397 | 35CAF9A7208F410800163DED /* Base */, 398 | ); 399 | name = Main.storyboard; 400 | sourceTree = ""; 401 | }; 402 | 35CAF9AB208F410800163DED /* LaunchScreen.storyboard */ = { 403 | isa = PBXVariantGroup; 404 | children = ( 405 | 35CAF9AC208F410800163DED /* Base */, 406 | ); 407 | name = LaunchScreen.storyboard; 408 | sourceTree = ""; 409 | }; 410 | /* End PBXVariantGroup section */ 411 | 412 | /* Begin XCBuildConfiguration section */ 413 | 35CAF9C7208F410900163DED /* Debug */ = { 414 | isa = XCBuildConfiguration; 415 | buildSettings = { 416 | ALWAYS_SEARCH_USER_PATHS = NO; 417 | CLANG_ANALYZER_NONNULL = YES; 418 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 419 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 420 | CLANG_CXX_LIBRARY = "libc++"; 421 | CLANG_ENABLE_MODULES = YES; 422 | CLANG_ENABLE_OBJC_ARC = YES; 423 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 424 | CLANG_WARN_BOOL_CONVERSION = YES; 425 | CLANG_WARN_COMMA = YES; 426 | CLANG_WARN_CONSTANT_CONVERSION = YES; 427 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 428 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 429 | CLANG_WARN_EMPTY_BODY = YES; 430 | CLANG_WARN_ENUM_CONVERSION = YES; 431 | CLANG_WARN_INFINITE_RECURSION = YES; 432 | CLANG_WARN_INT_CONVERSION = YES; 433 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 434 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 435 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 436 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 437 | CLANG_WARN_STRICT_PROTOTYPES = YES; 438 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 439 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 440 | CLANG_WARN_UNREACHABLE_CODE = YES; 441 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 442 | CODE_SIGN_IDENTITY = "iPhone Developer"; 443 | COPY_PHASE_STRIP = NO; 444 | DEBUG_INFORMATION_FORMAT = dwarf; 445 | ENABLE_STRICT_OBJC_MSGSEND = YES; 446 | ENABLE_TESTABILITY = YES; 447 | GCC_C_LANGUAGE_STANDARD = gnu11; 448 | GCC_DYNAMIC_NO_PIC = NO; 449 | GCC_NO_COMMON_BLOCKS = YES; 450 | GCC_OPTIMIZATION_LEVEL = 0; 451 | GCC_PREPROCESSOR_DEFINITIONS = ( 452 | "DEBUG=1", 453 | "$(inherited)", 454 | ); 455 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 456 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 457 | GCC_WARN_UNDECLARED_SELECTOR = YES; 458 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 459 | GCC_WARN_UNUSED_FUNCTION = YES; 460 | GCC_WARN_UNUSED_VARIABLE = YES; 461 | IPHONEOS_DEPLOYMENT_TARGET = 11.2; 462 | MTL_ENABLE_DEBUG_INFO = YES; 463 | ONLY_ACTIVE_ARCH = YES; 464 | SDKROOT = iphoneos; 465 | }; 466 | name = Debug; 467 | }; 468 | 35CAF9C8208F410900163DED /* Release */ = { 469 | isa = XCBuildConfiguration; 470 | buildSettings = { 471 | ALWAYS_SEARCH_USER_PATHS = NO; 472 | CLANG_ANALYZER_NONNULL = YES; 473 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 474 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 475 | CLANG_CXX_LIBRARY = "libc++"; 476 | CLANG_ENABLE_MODULES = YES; 477 | CLANG_ENABLE_OBJC_ARC = YES; 478 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 479 | CLANG_WARN_BOOL_CONVERSION = YES; 480 | CLANG_WARN_COMMA = YES; 481 | CLANG_WARN_CONSTANT_CONVERSION = YES; 482 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 483 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 484 | CLANG_WARN_EMPTY_BODY = YES; 485 | CLANG_WARN_ENUM_CONVERSION = YES; 486 | CLANG_WARN_INFINITE_RECURSION = YES; 487 | CLANG_WARN_INT_CONVERSION = YES; 488 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 489 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 490 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 491 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 492 | CLANG_WARN_STRICT_PROTOTYPES = YES; 493 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 494 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 495 | CLANG_WARN_UNREACHABLE_CODE = YES; 496 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 497 | CODE_SIGN_IDENTITY = "iPhone Developer"; 498 | COPY_PHASE_STRIP = NO; 499 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 500 | ENABLE_NS_ASSERTIONS = NO; 501 | ENABLE_STRICT_OBJC_MSGSEND = YES; 502 | GCC_C_LANGUAGE_STANDARD = gnu11; 503 | GCC_NO_COMMON_BLOCKS = YES; 504 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 505 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 506 | GCC_WARN_UNDECLARED_SELECTOR = YES; 507 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 508 | GCC_WARN_UNUSED_FUNCTION = YES; 509 | GCC_WARN_UNUSED_VARIABLE = YES; 510 | IPHONEOS_DEPLOYMENT_TARGET = 11.2; 511 | MTL_ENABLE_DEBUG_INFO = NO; 512 | SDKROOT = iphoneos; 513 | VALIDATE_PRODUCT = YES; 514 | }; 515 | name = Release; 516 | }; 517 | 35CAF9CA208F410900163DED /* Debug */ = { 518 | isa = XCBuildConfiguration; 519 | buildSettings = { 520 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 521 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 522 | CODE_SIGN_STYLE = Automatic; 523 | DEVELOPMENT_TEAM = D448D4BJ77; 524 | INFOPLIST_FILE = "$(SRCROOT)/WCBlockDemo/Info.plist"; 525 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 526 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 527 | PRODUCT_BUNDLE_IDENTIFIER = "-163.weicheng0-0.WCBlock"; 528 | PRODUCT_NAME = "$(TARGET_NAME)"; 529 | PROVISIONING_PROFILE_SPECIFIER = ""; 530 | TARGETED_DEVICE_FAMILY = "1,2"; 531 | }; 532 | name = Debug; 533 | }; 534 | 35CAF9CB208F410900163DED /* Release */ = { 535 | isa = XCBuildConfiguration; 536 | buildSettings = { 537 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 538 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 539 | CODE_SIGN_STYLE = Automatic; 540 | DEVELOPMENT_TEAM = D448D4BJ77; 541 | INFOPLIST_FILE = "$(SRCROOT)/WCBlockDemo/Info.plist"; 542 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 543 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 544 | PRODUCT_BUNDLE_IDENTIFIER = "-163.weicheng0-0.WCBlock"; 545 | PRODUCT_NAME = "$(TARGET_NAME)"; 546 | PROVISIONING_PROFILE_SPECIFIER = ""; 547 | TARGETED_DEVICE_FAMILY = "1,2"; 548 | }; 549 | name = Release; 550 | }; 551 | 35CAF9CD208F410900163DED /* Debug */ = { 552 | isa = XCBuildConfiguration; 553 | buildSettings = { 554 | BUNDLE_LOADER = "$(TEST_HOST)"; 555 | CODE_SIGN_STYLE = Automatic; 556 | DEVELOPMENT_TEAM = D448D4BJ77; 557 | INFOPLIST_FILE = WCBlockTests/Info.plist; 558 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 559 | PRODUCT_BUNDLE_IDENTIFIER = "-163.weicheng0-0.WCBlockTests"; 560 | PRODUCT_NAME = "$(TARGET_NAME)"; 561 | TARGETED_DEVICE_FAMILY = "1,2"; 562 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/WCBlock.app/WCBlock"; 563 | }; 564 | name = Debug; 565 | }; 566 | 35CAF9CE208F410900163DED /* Release */ = { 567 | isa = XCBuildConfiguration; 568 | buildSettings = { 569 | BUNDLE_LOADER = "$(TEST_HOST)"; 570 | CODE_SIGN_STYLE = Automatic; 571 | DEVELOPMENT_TEAM = D448D4BJ77; 572 | INFOPLIST_FILE = WCBlockTests/Info.plist; 573 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 574 | PRODUCT_BUNDLE_IDENTIFIER = "-163.weicheng0-0.WCBlockTests"; 575 | PRODUCT_NAME = "$(TARGET_NAME)"; 576 | TARGETED_DEVICE_FAMILY = "1,2"; 577 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/WCBlock.app/WCBlock"; 578 | }; 579 | name = Release; 580 | }; 581 | 35CAF9D0208F410900163DED /* Debug */ = { 582 | isa = XCBuildConfiguration; 583 | buildSettings = { 584 | CODE_SIGN_STYLE = Automatic; 585 | DEVELOPMENT_TEAM = D448D4BJ77; 586 | INFOPLIST_FILE = WCBlockUITests/Info.plist; 587 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 588 | PRODUCT_BUNDLE_IDENTIFIER = "-163.weicheng0-0.WCBlockUITests"; 589 | PRODUCT_NAME = "$(TARGET_NAME)"; 590 | TARGETED_DEVICE_FAMILY = "1,2"; 591 | TEST_TARGET_NAME = WCBlock; 592 | }; 593 | name = Debug; 594 | }; 595 | 35CAF9D1208F410900163DED /* Release */ = { 596 | isa = XCBuildConfiguration; 597 | buildSettings = { 598 | CODE_SIGN_STYLE = Automatic; 599 | DEVELOPMENT_TEAM = D448D4BJ77; 600 | INFOPLIST_FILE = WCBlockUITests/Info.plist; 601 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 602 | PRODUCT_BUNDLE_IDENTIFIER = "-163.weicheng0-0.WCBlockUITests"; 603 | PRODUCT_NAME = "$(TARGET_NAME)"; 604 | TARGETED_DEVICE_FAMILY = "1,2"; 605 | TEST_TARGET_NAME = WCBlock; 606 | }; 607 | name = Release; 608 | }; 609 | /* End XCBuildConfiguration section */ 610 | 611 | /* Begin XCConfigurationList section */ 612 | 35CAF998208F410800163DED /* Build configuration list for PBXProject "WCBlock" */ = { 613 | isa = XCConfigurationList; 614 | buildConfigurations = ( 615 | 35CAF9C7208F410900163DED /* Debug */, 616 | 35CAF9C8208F410900163DED /* Release */, 617 | ); 618 | defaultConfigurationIsVisible = 0; 619 | defaultConfigurationName = Release; 620 | }; 621 | 35CAF9C9208F410900163DED /* Build configuration list for PBXNativeTarget "WCBlock" */ = { 622 | isa = XCConfigurationList; 623 | buildConfigurations = ( 624 | 35CAF9CA208F410900163DED /* Debug */, 625 | 35CAF9CB208F410900163DED /* Release */, 626 | ); 627 | defaultConfigurationIsVisible = 0; 628 | defaultConfigurationName = Release; 629 | }; 630 | 35CAF9CC208F410900163DED /* Build configuration list for PBXNativeTarget "WCBlockTests" */ = { 631 | isa = XCConfigurationList; 632 | buildConfigurations = ( 633 | 35CAF9CD208F410900163DED /* Debug */, 634 | 35CAF9CE208F410900163DED /* Release */, 635 | ); 636 | defaultConfigurationIsVisible = 0; 637 | defaultConfigurationName = Release; 638 | }; 639 | 35CAF9CF208F410900163DED /* Build configuration list for PBXNativeTarget "WCBlockUITests" */ = { 640 | isa = XCConfigurationList; 641 | buildConfigurations = ( 642 | 35CAF9D0208F410900163DED /* Debug */, 643 | 35CAF9D1208F410900163DED /* Release */, 644 | ); 645 | defaultConfigurationIsVisible = 0; 646 | defaultConfigurationName = Release; 647 | }; 648 | /* End XCConfigurationList section */ 649 | }; 650 | rootObject = 35CAF995208F410800163DED /* Project object */; 651 | } 652 | -------------------------------------------------------------------------------- /WCBlock.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WCBlock.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /WCBlock.xcodeproj/project.xcworkspace/xcuserdata/zhaoweicheng.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manakiaHk/WCBlock/4d16d4273b29f113235d12047ce0fc053632ee14/WCBlock.xcodeproj/project.xcworkspace/xcuserdata/zhaoweicheng.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /WCBlock.xcodeproj/xcuserdata/zhaoweicheng.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | WCBlock.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | WCBlock.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /WCBlock/NSNotificationCenter+WCBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSNotificationCenter+WCBlock.h 3 | // WCBlock 4 | // 5 | // Created by zhao weicheng on 2018/4/28. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #define WCNotificationCenter [NSNotificationCenter defaultCenter] 12 | 13 | @interface NSNotificationCenter (WCBlock) 14 | /**@!brief 通知中心添加监听者(内部自动管理移除observer) 15 | * @param name 通知名 16 | * @param contextObj 调用的上下文对象(一般是self) ***毕传** 17 | * @param queue block执行队列 18 | * @param block 接收到通知的回调 19 | */ 20 | -(void)wc_addObserverForName:(nonnull NSString*)name 21 | object:(id _Nullable)obj 22 | contextObj:(nonnull id)contextObj 23 | queue:(NSOperationQueue *_Nullable)queue 24 | blockNext:(void (^_Nullable)(NSNotification * _Nullable note))block; 25 | /**@!brief 通知中心添加监听者(内部自动管理移除observer) 26 | * @param name 通知名 27 | * @param contextObj 调用的上下文对象(一般是self) ***毕传** 28 | * @param block 接收到通知的回调 29 | */ 30 | -(void)wc_addObserverForName:(nonnull NSString*)name 31 | object:(id _Nullable)obj 32 | contextObj:(nonnull id)contextObj 33 | blockNext:(void (^_Nullable)(NSNotification * _Nullable note))block; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /WCBlock/NSNotificationCenter+WCBlock.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSNotificationCenter+WCBlock.m 3 | // WCBlock 4 | // 5 | // Created by zhao weicheng on 2018/4/28. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import "NSNotificationCenter+WCBlock.h" 10 | #import 11 | 12 | @interface WCNotifObserverTarget:NSObject 13 | @property (nonatomic,weak) id notifObserver; 14 | @property (nonatomic,weak) id notifName; 15 | @property (nonatomic,weak) id notifObj; 16 | @property (nonatomic,copy) void (^notifBlock)(NSNotification *note); 17 | @end 18 | @implementation WCNotifObserverTarget 19 | - (void)dealloc { 20 | NSLog(@"%@",[WCNotifObserverTarget description]); 21 | [WCNotificationCenter removeObserver:self.notifObserver name:self.notifName object:self.notifObj]; 22 | } 23 | 24 | - (void)notifReceived:(NSNotification*)note { 25 | if (self.notifBlock) { 26 | self.notifBlock(note); 27 | } 28 | } 29 | @end 30 | static const int wc_notification_observer_target_set_key; 31 | @implementation NSNotificationCenter (WCBlock) 32 | -(void)wc_addObserverForName:(NSString*)name 33 | object:(id)obj 34 | contextObj:(id)contextObj 35 | queue:(NSOperationQueue *)queue 36 | blockNext:(void (^)(NSNotification *note))block { 37 | 38 | WCNotifObserverTarget *target = [WCNotifObserverTarget new]; 39 | [[self wc_observerTargetSetOfContextObj:contextObj]addObject:target]; 40 | target.notifObj = obj; 41 | target.notifName = name; 42 | target.notifBlock = block; 43 | __weak typeof(target) weakTarget = target; 44 | target.notifObserver = [WCNotificationCenter addObserverForName:name object:obj queue:queue usingBlock:^(NSNotification * _Nonnull note) { 45 | __strong typeof(weakTarget) strongTarget = weakTarget; 46 | if (strongTarget.notifBlock) strongTarget.notifBlock(note); 47 | }]; 48 | } 49 | -(void)wc_addObserverForName:(nonnull NSString*)name 50 | object:(id _Nullable)obj 51 | contextObj:(nonnull id)contextObj 52 | blockNext:(void (^_Nullable)(NSNotification * _Nullable note))block { 53 | 54 | WCNotifObserverTarget *target = [WCNotifObserverTarget new]; 55 | [[self wc_observerTargetSetOfContextObj:contextObj]addObject:target]; 56 | target.notifObj = obj; 57 | target.notifName = name; 58 | target.notifBlock = block; 59 | [WCNotificationCenter addObserver:target selector:@selector(notifReceived:) name:name object:obj]; 60 | } 61 | -(NSMutableSet*)wc_observerTargetSetOfContextObj:(id)obj{ 62 | NSMutableSet *_set = objc_getAssociatedObject(obj, &wc_notification_observer_target_set_key); 63 | if (!_set) { 64 | _set = [NSMutableSet new]; 65 | objc_setAssociatedObject(obj,&wc_notification_observer_target_set_key,_set, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 66 | } 67 | return _set; 68 | } 69 | @end 70 | -------------------------------------------------------------------------------- /WCBlock/NSObject+WCKVOBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+WCKVOBlock.h 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/17. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import 10 | @interface NSObject (WCKVOBlock) 11 | // EN: method "wc_addObserver.." will produce observers for your keypaths,and they will be delloced after the object observered delloced, but they will not remove theirs observers. so, as usual,theirs observers(add by method "wc_addObserver..") need to be removed by yourself through methods such as ”wc_removeObserver...“ . 12 | // zh-CN: 调用“wc_addObserver..” 添加keyPath监听将自动生成他们的观察者对象,并会随着被观察者的销毁而自动销毁,但是并不会为你自动注销他们的键值观察,和以往一样,需要你调用如“wc_removeObserver...”方法移除注销对应的(wc_addObserver..所添加的)键值观察。 13 | 14 | /**@!brief add an object keypath observer. 15 | * @param keyPath the object keyPath by observered. 16 | * @param block , will call this block when value changed. 17 | * @blockNext's ofObj, the object by observered. 18 | * @blockNext's oldValue, value before changed. 19 | * @blockNext's newValue, value after changed. 20 | */ 21 | - (void)wc_addObserverForKeyPath:(NSString*)keyPath 22 | valueBlockNext:(void(^)(NSString *keypath,id ofObj, id oldValue,id newValue))block; 23 | /**@!brief add object keyPath observer more than one. 24 | * @param keyPaths e.g:@[@"keyPath0",@"keyPath1"] 25 | */ 26 | - (void)wc_addObserverForKeyPaths:(NSArray*)keyPaths 27 | valueBlockNext:(void(^)(NSString *keypath,id ofObj, id oldValue,id newValue))block; 28 | /**@!brief add an object keyPath observer. 29 | * @param keyPath the object keyPath by observered. 30 | * @param block ,call back. 31 | * @blockNext ofObj ,the object by observered. 32 | * @blockNext change , values after changed. 33 | */ 34 | - (void)wc_addObserverForKeyPath:(NSString*)keyPath 35 | options:(NSKeyValueObservingOptions)options 36 | changeBlockNext:(void(^)(NSString *keypath,id ofObj, NSDictionary *change))block; 37 | /**@!brief add object keyPath observer more than one. 38 | * @param keyPaths ,a keyPath array e.g,@[@"keyPath0",@"keyPath1"]. 39 | */ 40 | - (void)wc_addObserverForKeyPaths:(NSArray*)keyPaths 41 | options:(NSKeyValueObservingOptions)options 42 | changeBlockNext:(void(^)(NSString *keypath,id ofObj, NSDictionary *change))block; 43 | /**@!brief remove an object keyPath observer. 44 | * @param keyPath , the object keyPath by observered. 45 | * tip : you can call the method to remove your object keyPath observer. 46 | */ 47 | - (void)wc_removeObserverForKeyPath:(NSString*)keyPath; 48 | /**@!brief remove object keyPath observers 49 | * @param keyPaths , a keyPath array e.g:@[@"keyPath0",@"keyPath1"]. 50 | * tip :you can call the method to remove your object keyPath observer . 51 | */ 52 | - (void)wc_removeObserverForKeyPaths:(NSArray*)keyPaths; 53 | /**@!brief remove all object keyPath observers. 54 | * tip :you can call the method to remove all your object keyPath observers . 55 | */ 56 | - (void)wc_removeAllKeyValueObservers; 57 | @end 58 | -------------------------------------------------------------------------------- /WCBlock/NSObject+WCKVOBlock.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+WCKVOBlock.m 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/17. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import "NSObject+WCKVOBlock.h" 10 | #import 11 | static const int wc_observer_set_key; 12 | @interface WCKeyPathObserver: NSObject 13 | @property (nonatomic,strong)NSString *keyPath; 14 | @property (nonatomic,copy)void(^valueBlock)(NSString *keyPath,id ofObj,id oldValue,id newValue); 15 | @property (nonatomic,copy)void(^changeBlock)(NSString *keyPath,id ofObj,NSDictionary *change); 16 | @end 17 | @implementation WCKeyPathObserver 18 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 19 | id oldValue = [change objectForKey:NSKeyValueChangeOldKey]; 20 | id newValue = [change objectForKey:NSKeyValueChangeNewKey]; 21 | if (self.valueBlock&&[keyPath isEqualToString:self.keyPath]){ 22 | self.valueBlock(keyPath, object, oldValue, newValue); 23 | } 24 | if (self.changeBlock&&[keyPath isEqualToString:self.keyPath]){ 25 | self.changeBlock(keyPath, object, change); 26 | } 27 | } 28 | @end 29 | @implementation NSObject (WCKVOBlock) 30 | - (void)wc_addObserverForKeyPath:(NSString*)keyPath 31 | valueBlockNext:(void(^)(NSString *keypath,id ofObj, id oldValue,id newValue))block { 32 | if (!keyPath)return; 33 | WCKeyPathObserver *observer = [WCKeyPathObserver new]; 34 | observer.valueBlock = block; 35 | observer.keyPath = keyPath; 36 | [self addObserver:observer forKeyPath:keyPath options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil]; 37 | [[self wc_observerSet] addObject:observer]; 38 | } 39 | - (void)wc_addObserverForKeyPaths:(NSArray*)keyPaths 40 | valueBlockNext:(void(^)(NSString *keypath,id ofObj, id oldValue,id newValue))block { 41 | [keyPaths enumerateObjectsUsingBlock:^(NSString * _Nonnull keyPath, NSUInteger idx, BOOL * _Nonnull stop) { 42 | [self wc_addObserverForKeyPath:keyPath valueBlockNext:block]; 43 | }]; 44 | } 45 | - (void)wc_addObserverForKeyPath:(NSString*)keyPath 46 | options:(NSKeyValueObservingOptions)options 47 | changeBlockNext:(void(^)(NSString *keypath,id ofObj, NSDictionary *change))block{ 48 | if (!keyPath)return; 49 | WCKeyPathObserver *observer = [WCKeyPathObserver new]; 50 | observer.changeBlock = block; 51 | observer.keyPath = keyPath; 52 | [self addObserver:observer forKeyPath:keyPath options:options context:nil]; 53 | [[self wc_observerSet] addObject:observer]; 54 | } 55 | 56 | - (void)wc_addObserverForKeyPaths:(NSArray*)keyPaths 57 | options:(NSKeyValueObservingOptions)options 58 | changeBlockNext:(void(^)(NSString *keypath,id ofObj, NSDictionary *change))block{ 59 | [keyPaths enumerateObjectsUsingBlock:^(NSString * _Nonnull keyPath, NSUInteger idx, BOOL * _Nonnull stop) { 60 | [self wc_addObserverForKeyPath:keyPath options:options changeBlockNext:block]; 61 | }]; 62 | } 63 | -(NSMutableSet*)wc_observerSet{ 64 | NSMutableSet *_observerSet = objc_getAssociatedObject(self, &wc_observer_set_key); 65 | if (!_observerSet) { 66 | _observerSet = [NSMutableSet new]; 67 | objc_setAssociatedObject(self,&wc_observer_set_key,_observerSet, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 68 | } 69 | return _observerSet; 70 | } 71 | - (void)wc_removeObserverForKeyPath:(NSString*)keyPath { 72 | [[self wc_observerSet] enumerateObjectsUsingBlock:^(WCKeyPathObserver * _Nonnull obj, BOOL * _Nonnull stop) { 73 | if ([obj.keyPath isEqualToString:keyPath]){ 74 | [self removeObserver:obj forKeyPath:keyPath]; 75 | [[self wc_observerSet] removeObject:obj]; 76 | } 77 | }]; 78 | } 79 | - (void)wc_removeObserverForKeyPaths:(NSArray*)keyPaths { 80 | [keyPaths enumerateObjectsUsingBlock:^(NSString * _Nonnull keyPath, NSUInteger idx, BOOL * _Nonnull stop) { 81 | [self wc_removeObserverForKeyPath:keyPath]; 82 | }]; 83 | } 84 | - (void)wc_removeAllKeyValueObservers{ 85 | [[self wc_observerSet] enumerateObjectsUsingBlock:^(WCKeyPathObserver * _Nonnull obj, BOOL * _Nonnull stop) { 86 | [self removeObserver:obj forKeyPath:obj.keyPath]; 87 | if (stop) { 88 | [[self wc_observerSet] removeAllObjects]; 89 | } 90 | }]; 91 | } 92 | @end 93 | -------------------------------------------------------------------------------- /WCBlock/UIAlertView+WCBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIAlertView+WCBlock.h 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/16. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIAlertView (WCBlock) 12 | /**@!brief EN:alertView object call back . zh-CN:绑定alertView回调 13 | * @param block call back. zh-CN :回调 14 | * EN:for using methods as bellow you need to be knowed that if you use its delegate to listen UIAlertView object user click and also use the following block at the same time,it will be effective by only one way , this depends on your opportunity to set up delegate and block for UIAlertView object (later effective), it's important about this. 15 | * zh-CN: 如果你在使用UIAlertView用了代理监听点击,又用了此方法绑定,那么只有一种方案有效。这取决于你为UIAlertView 设置delegate的时机(后来者有效)。这点你需要知晓并希望你选者其一。 16 | */ 17 | -(void)wc_bindAlertButtonClickedBlockNext:(void (^)(NSInteger index))block; 18 | @end 19 | -------------------------------------------------------------------------------- /WCBlock/UIAlertView+WCBlock.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIAlertView+WCBlock.m 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/16. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import "UIAlertView+WCBlock.h" 10 | #import 11 | static const int wc_alertView_blockTarget_set_key; 12 | @interface WCAlertViewBlockTarget : NSObject 13 | @property (nonatomic,copy)void(^block)(NSInteger index); 14 | @end 15 | @implementation WCAlertViewBlockTarget 16 | @end 17 | @interface UIAlertView () 18 | @end 19 | @implementation UIAlertView (WCBlock) 20 | -(void)wc_bindAlertButtonClickedBlockNext:(void (^)(NSInteger index))block { 21 | WCAlertViewBlockTarget *target = [WCAlertViewBlockTarget new]; 22 | target.block = block; 23 | [[self wc_blockTargetSet] addObject:target]; 24 | self.delegate = self; 25 | } 26 | -(NSMutableSet*)wc_blockTargetSet{ 27 | NSMutableSet *_targets = objc_getAssociatedObject(self, &wc_alertView_blockTarget_set_key); 28 | if (!_targets) { 29 | _targets = [NSMutableSet new]; 30 | objc_setAssociatedObject(self,&wc_alertView_blockTarget_set_key,_targets, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 31 | } 32 | return _targets; 33 | } 34 | - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { 35 | [[self wc_blockTargetSet] enumerateObjectsUsingBlock:^(WCAlertViewBlockTarget * _Nonnull obj, BOOL * _Nonnull stop) { 36 | if (obj.block)obj.block(buttonIndex); 37 | }]; 38 | } 39 | @end 40 | -------------------------------------------------------------------------------- /WCBlock/UIControl+WCBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIControl+WCBlock.h 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/16. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIControl (WCBlock) 12 | /**@!brief: bind event callback for an UIControl object , e.g :sliders,buttons,switch, etc. 13 | * @param controlEvents , event type of UIControlEvents. 14 | * @param block , will call this block when event emited. 15 | */ 16 | -(void)wc_bindForControlEvents:(UIControlEvents)controlEvents blockNext:(void (^)(id sender))block; 17 | @end 18 | -------------------------------------------------------------------------------- /WCBlock/UIControl+WCBlock.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIControl+WCBlock.m 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/16. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import "UIControl+WCBlock.h" 10 | #import 11 | static const int wc_control_blockTarget_set_key; 12 | @interface WCControlBlockTarget : NSObject 13 | @property (nonatomic,copy)void(^block)(id sender); 14 | @end 15 | @implementation WCControlBlockTarget 16 | -(void)wc_blockEmit:(id)sender { 17 | if (self.block)self.block(sender); 18 | } 19 | @end 20 | @implementation UIControl (WCBlock) 21 | -(void)wc_bindForControlEvents:(UIControlEvents)controlEvents blockNext:(void (^)(id sender))block { 22 | WCControlBlockTarget *target = [WCControlBlockTarget new]; 23 | target.block = block; 24 | [[self wc_blockTargetSet] addObject:target]; 25 | [self addTarget:target action:@selector(wc_blockEmit:) forControlEvents:controlEvents]; 26 | } 27 | -(NSMutableSet*)wc_blockTargetSet{ 28 | NSMutableSet *_targets = objc_getAssociatedObject(self, &wc_control_blockTarget_set_key); 29 | if (!_targets) { 30 | _targets = [NSMutableSet new]; 31 | objc_setAssociatedObject(self,&wc_control_blockTarget_set_key,_targets, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 32 | } 33 | return _targets; 34 | } 35 | @end 36 | -------------------------------------------------------------------------------- /WCBlock/UIGestureRecognizer+WCBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIGestureRecognizer+WCBlock.h 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/16. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIGestureRecognizer (WCBlock) 12 | /**@!brief EN: bind gesturerecognizer object call back . ch-ZN:绑定手势回调 13 | * @param block call back. zh-CN :回调 14 | */ 15 | -(void)wc_bindGestureBlockNext:(void (^)(UIGestureRecognizer *sender))block; 16 | @end 17 | -------------------------------------------------------------------------------- /WCBlock/UIGestureRecognizer+WCBlock.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIGestureRecognizer+WCBlock.m 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/16. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import "UIGestureRecognizer+WCBlock.h" 10 | #import 11 | static const int wc_gesture_blockTarget_set_key; 12 | @interface WCGestureBlockTarget : NSObject 13 | @property (nonatomic,copy)void(^block)(id sender); 14 | @end 15 | @implementation WCGestureBlockTarget 16 | -(void)wc_blockEmit:(id)sender { 17 | if (self.block)self.block(sender); 18 | } 19 | @end 20 | @implementation UIGestureRecognizer (WCBlock) 21 | -(void)wc_bindGestureBlockNext:(void (^)(UIGestureRecognizer *sender))block{ 22 | WCGestureBlockTarget *target = [WCGestureBlockTarget new]; 23 | target.block = block; 24 | [self addTarget:target action:@selector(wc_blockEmit:)]; 25 | [[self wc_blockTargetSet] addObject:target]; 26 | } 27 | -(NSMutableSet*)wc_blockTargetSet{ 28 | NSMutableSet *_targets = objc_getAssociatedObject(self, &wc_gesture_blockTarget_set_key); 29 | if (!_targets) { 30 | _targets = [NSMutableSet new]; 31 | objc_setAssociatedObject(self,&wc_gesture_blockTarget_set_key,_targets, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 32 | } 33 | return _targets; 34 | } 35 | @end 36 | -------------------------------------------------------------------------------- /WCBlock/UISearchBar+WCBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // UISearchBar+WCBlock.h 3 | // WCBlock 4 | // 5 | // Created by zhao weicheng on 2018/4/29. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UISearchBar (WCBlock) 12 | /// zh-CN: 对于以下所有回调的使用, 如果你使用了自己代理实现的方式又使用了以下handlerBlock回调的方式,将只有一种方案有效,取决于你为searchBar设置代理delegate的时机,最终都是后来者有效。这点你需要知晓并希望你选者其一。 13 | - (void)wc_bindSearchBarTextDidBeginEditingBlockNext:(void (^)(UISearchBar *searchBar))block; 14 | - (void)wc_bindSearchBarTextDidEndEditingBlockNext:(void (^)(UISearchBar *searchBar))block; 15 | - (void)wc_bindSearchBarTextDidChangeBlockNext:(void (^)(UISearchBar *searchBar,NSString *searchText))block; 16 | - (void)wc_bindSearchBarSearchButtonClickedBlockNext:(void (^)(UISearchBar *searchBar))block; 17 | - (void)wc_bindSearchBarBookmarkButtonClickedBlockNext:(void (^)(UISearchBar *searchBar))block; 18 | - (void)wc_bindSearchBarCancelButtonClickedBlockNext:(void (^)(UISearchBar *searchBar))block; 19 | - (void)wc_bindSearchBarResultsListButtonClickedBlockNext:(void (^)(UISearchBar *searchBar))block; 20 | - (void)wc_bindSearchBarSelectedScopeButtonIndexDidChangeBlockNext:(void (^)(UISearchBar *searchBar,NSInteger selectedScope))block; 21 | 22 | - (void)wc_bindSearchBarShouldBeginEditingHandlerBlock:(BOOL (^)(UISearchBar*searchBar))block; 23 | - (void)wc_bindSearchBarShouldChangeCharactersHandlerBlock:(BOOL (^)(UISearchBar*searchBar,NSRange inRange ,NSString*replacementString))block; 24 | - (void)wc_bindSearchBarShouldEndEditingHandlerBlock:(BOOL (^)(UISearchBar*searchBar))block; 25 | @end 26 | -------------------------------------------------------------------------------- /WCBlock/UISearchBar+WCBlock.m: -------------------------------------------------------------------------------- 1 | // 2 | // UISearchBar+WCBlock.m 3 | // WCBlock 4 | // 5 | // Created by zhao weicheng on 2018/4/29. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import "UISearchBar+WCBlock.h" 10 | #import 11 | 12 | static const int wc_searchBar_blockTarget_set_key; 13 | static const int wc_searchBar_shouldChangeCharactersHandlerBlock_key; 14 | static const int wc_searchBar_shouldBeginEditingHandlerBlock_key; 15 | static const int wc_searchBar_shouldEndEditingHandlerBlock_key; 16 | 17 | @interface WCSearchBarBlockTarget : NSObject 18 | @property (nonatomic,copy)void(^editingDidBeginBlock)(UISearchBar *searchBar); 19 | @property (nonatomic,copy)void(^editingChangedBlock)(UISearchBar *searchBar,NSString *searchText); 20 | @property (nonatomic,copy)void(^editingDidEndBlock)(UISearchBar *searchBar); 21 | @property (nonatomic,copy)void(^searchButtonClickedBlock)(UISearchBar *searchBar); 22 | @property (nonatomic,copy)void(^bookmarkButtonClickedBlock)(UISearchBar *searchBar); 23 | @property (nonatomic,copy)void(^cancelButtonClickedBlock)(UISearchBar *searchBar); 24 | @property (nonatomic,copy)void(^resultsListButtonClickedBlock)(UISearchBar *searchBar); 25 | @property (nonatomic,copy)void(^selectedScopeButtonIndexDidChangeBlock)(UISearchBar *searchBar,NSInteger selectedScope); 26 | @end 27 | @implementation WCSearchBarBlockTarget 28 | 29 | @end 30 | 31 | @interface UISearchBar() 32 | @end 33 | @implementation UISearchBar (WCBlock) 34 | - (void)wc_bindSearchBarTextDidBeginEditingBlockNext:(void (^)(UISearchBar *searchBar))block { 35 | WCSearchBarBlockTarget *target = [WCSearchBarBlockTarget new]; 36 | target.editingDidBeginBlock = block; 37 | [[self wc_blockTargetSet] addObject:target]; 38 | self.delegate = self; 39 | } 40 | - (void)wc_bindSearchBarTextDidEndEditingBlockNext:(void (^)(UISearchBar *searchBar))block { 41 | WCSearchBarBlockTarget *target = [WCSearchBarBlockTarget new]; 42 | target.editingDidEndBlock = block; 43 | [[self wc_blockTargetSet] addObject:target]; 44 | self.delegate = self; 45 | } 46 | - (void)wc_bindSearchBarTextDidChangeBlockNext:(void (^)(UISearchBar *searchBar,NSString *searchText))block { 47 | 48 | WCSearchBarBlockTarget *target = [WCSearchBarBlockTarget new]; 49 | target.editingChangedBlock = block; 50 | [[self wc_blockTargetSet] addObject:target]; 51 | self.delegate = self; 52 | } 53 | - (void)wc_bindSearchBarSearchButtonClickedBlockNext:(void (^)(UISearchBar *searchBar))block { 54 | WCSearchBarBlockTarget *target = [WCSearchBarBlockTarget new]; 55 | target.searchButtonClickedBlock = block; 56 | [[self wc_blockTargetSet] addObject:target]; 57 | self.delegate = self; 58 | } 59 | - (void)wc_bindSearchBarBookmarkButtonClickedBlockNext:(void (^)(UISearchBar *searchBar))block { 60 | WCSearchBarBlockTarget *target = [WCSearchBarBlockTarget new]; 61 | target.bookmarkButtonClickedBlock = block; 62 | [[self wc_blockTargetSet] addObject:target]; 63 | self.delegate = self; 64 | } 65 | - (void)wc_bindSearchBarCancelButtonClickedBlockNext:(void (^)(UISearchBar *searchBar))block { 66 | WCSearchBarBlockTarget *target = [WCSearchBarBlockTarget new]; 67 | target.cancelButtonClickedBlock = block; 68 | [[self wc_blockTargetSet] addObject:target]; 69 | self.delegate = self; 70 | } 71 | - (void)wc_bindSearchBarResultsListButtonClickedBlockNext:(void (^)(UISearchBar *searchBar))block { 72 | WCSearchBarBlockTarget *target = [WCSearchBarBlockTarget new]; 73 | target.resultsListButtonClickedBlock = block; 74 | [[self wc_blockTargetSet] addObject:target]; 75 | self.delegate = self; 76 | } 77 | - (void)wc_bindSearchBarSelectedScopeButtonIndexDidChangeBlockNext:(void (^)(UISearchBar *searchBar,NSInteger selectedScope))block { 78 | WCSearchBarBlockTarget *target = [WCSearchBarBlockTarget new]; 79 | target.selectedScopeButtonIndexDidChangeBlock = block; 80 | [[self wc_blockTargetSet] addObject:target]; 81 | self.delegate = self; 82 | } 83 | - (void)wc_bindSearchBarShouldBeginEditingHandlerBlock:(BOOL (^)(UISearchBar*searchBar))block { 84 | objc_setAssociatedObject(self,&wc_searchBar_shouldBeginEditingHandlerBlock_key,block, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 85 | self.delegate = self; 86 | } 87 | - (void)wc_bindSearchBarShouldChangeCharactersHandlerBlock:(BOOL (^)(UISearchBar*searchBar,NSRange inRange ,NSString*replacementString))block { 88 | objc_setAssociatedObject(self,&wc_searchBar_shouldChangeCharactersHandlerBlock_key,block, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 89 | self.delegate = self; 90 | } 91 | - (void)wc_bindSearchBarShouldEndEditingHandlerBlock:(BOOL (^)(UISearchBar*searchBar))block { 92 | objc_setAssociatedObject(self,&wc_searchBar_shouldEndEditingHandlerBlock_key,block, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 93 | self.delegate = self; 94 | } 95 | 96 | /// delegate 97 | 98 | - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar { 99 | [[self wc_blockTargetSet] enumerateObjectsUsingBlock:^(WCSearchBarBlockTarget * _Nonnull obj, BOOL * _Nonnull stop) { 100 | if (obj.editingDidBeginBlock)obj.editingDidBeginBlock(searchBar); 101 | }]; 102 | } 103 | - (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar { 104 | [[self wc_blockTargetSet] enumerateObjectsUsingBlock:^(WCSearchBarBlockTarget * _Nonnull obj, BOOL * _Nonnull stop) { 105 | if (obj.editingDidEndBlock)obj.editingDidEndBlock(searchBar); 106 | }]; 107 | } 108 | - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { 109 | [[self wc_blockTargetSet] enumerateObjectsUsingBlock:^(WCSearchBarBlockTarget * _Nonnull obj, BOOL * _Nonnull stop) { 110 | if (obj.editingChangedBlock)obj.editingChangedBlock(searchBar, searchText); 111 | }]; 112 | } 113 | 114 | - (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar { 115 | [[self wc_blockTargetSet] enumerateObjectsUsingBlock:^(WCSearchBarBlockTarget * _Nonnull obj, BOOL * _Nonnull stop) { 116 | if (obj.searchButtonClickedBlock)obj.searchButtonClickedBlock(searchBar); 117 | }]; 118 | } 119 | - (void)searchBarBookmarkButtonClicked:(UISearchBar *)searchBar __TVOS_PROHIBITED { 120 | [[self wc_blockTargetSet] enumerateObjectsUsingBlock:^(WCSearchBarBlockTarget * _Nonnull obj, BOOL * _Nonnull stop) { 121 | if (obj.bookmarkButtonClickedBlock)obj.bookmarkButtonClickedBlock(searchBar); 122 | }]; 123 | } 124 | - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar __TVOS_PROHIBITED { 125 | [[self wc_blockTargetSet] enumerateObjectsUsingBlock:^(WCSearchBarBlockTarget * _Nonnull obj, BOOL * _Nonnull stop) { 126 | if (obj.cancelButtonClickedBlock)obj.cancelButtonClickedBlock(searchBar); 127 | }]; 128 | } 129 | - (void)searchBarResultsListButtonClicked:(UISearchBar *)searchBar NS_AVAILABLE_IOS(3_2) __TVOS_PROHIBITED { 130 | [[self wc_blockTargetSet] enumerateObjectsUsingBlock:^(WCSearchBarBlockTarget * _Nonnull obj, BOOL * _Nonnull stop) { 131 | if (obj.resultsListButtonClickedBlock)obj.resultsListButtonClickedBlock(searchBar); 132 | }]; 133 | } 134 | - (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope NS_AVAILABLE_IOS(3_0) { 135 | [[self wc_blockTargetSet] enumerateObjectsUsingBlock:^(WCSearchBarBlockTarget * _Nonnull obj, BOOL * _Nonnull stop) { 136 | if (obj.selectedScopeButtonIndexDidChangeBlock)obj.selectedScopeButtonIndexDidChangeBlock(searchBar, selectedScope); 137 | }]; 138 | } 139 | 140 | - (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar { 141 | BOOL(^block)(UISearchBar*) = objc_getAssociatedObject(self, &wc_searchBar_shouldEndEditingHandlerBlock_key); 142 | if (block) return block(searchBar); 143 | return YES; 144 | } 145 | - (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar { 146 | BOOL(^block)(UISearchBar*) = objc_getAssociatedObject(self, &wc_searchBar_shouldBeginEditingHandlerBlock_key); 147 | if (block) return block(searchBar); 148 | return YES; 149 | } 150 | - (BOOL)searchBar:(UISearchBar *)searchBar shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text NS_AVAILABLE_IOS(3_0){ 151 | BOOL(^block)(UISearchBar*,NSRange,NSString*) = objc_getAssociatedObject(self, &wc_searchBar_shouldChangeCharactersHandlerBlock_key); 152 | if (block) return block(searchBar,range,text); 153 | return YES; 154 | } 155 | 156 | -(NSMutableSet*)wc_blockTargetSet{ 157 | NSMutableSet *_targets = objc_getAssociatedObject(self, &wc_searchBar_blockTarget_set_key); 158 | if (!_targets) { 159 | _targets = [NSMutableSet new]; 160 | objc_setAssociatedObject(self,&wc_searchBar_blockTarget_set_key,_targets, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 161 | } 162 | return _targets; 163 | } 164 | 165 | @end 166 | -------------------------------------------------------------------------------- /WCBlock/UISegmentedControl+WCBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // UISegmentedControl+WCBlock.h 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/17. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UISegmentedControl (WCBlock) 12 | /**@!brief EN:bind segmentControl object call back. zh-CN:绑定segmentControl切换回调 13 | * @param block call back. zh-CN :回调 14 | */ 15 | -(void)wc_bindSegmentControlValueChangedBlockNext:(void (^)(NSInteger selectedIndex))block; 16 | @end 17 | -------------------------------------------------------------------------------- /WCBlock/UISegmentedControl+WCBlock.m: -------------------------------------------------------------------------------- 1 | // 2 | // UISegmentedControl+WCBlock.m 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/17. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import "UISegmentedControl+WCBlock.h" 10 | #import 11 | static const int wc_segmentControlTarget_set_key; 12 | @interface WCSegmentControlBlockTarget : NSObject 13 | @property (nonatomic,copy)void(^block)(NSInteger selectedIndex); 14 | @end 15 | @implementation WCSegmentControlBlockTarget 16 | -(void)wc_blockEmit:(UISegmentedControl*)sender { 17 | if (self.block)self.block(sender.selectedSegmentIndex); 18 | } 19 | @end 20 | @implementation UISegmentedControl (WCBlock) 21 | -(void)wc_bindSegmentControlValueChangedBlockNext:(void (^)(NSInteger selectedIndex))block { 22 | WCSegmentControlBlockTarget *target = [WCSegmentControlBlockTarget new]; 23 | target.block = block; 24 | [[self wc_blockTargetSet] addObject:target]; 25 | [self addTarget:target action:@selector(wc_blockEmit:) forControlEvents:UIControlEventValueChanged]; 26 | } 27 | -(NSMutableSet*)wc_blockTargetSet{ 28 | NSMutableSet *_targets = objc_getAssociatedObject(self, &wc_segmentControlTarget_set_key); 29 | if (!_targets) { 30 | _targets = [NSMutableSet new]; 31 | objc_setAssociatedObject(self,&wc_segmentControlTarget_set_key,_targets, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 32 | } 33 | return _targets; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /WCBlock/UISlider+WCBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // UISlider+WCBlock.h 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/17. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UISlider (WCBlock) 12 | /**@!brief EN:bind slider object call back. zh-CN: 绑定slider切换回调 13 | * @param block call back. zh-CN :回调 14 | */ 15 | -(void)wc_bindSliderValueChangedBlockNext:(void (^)(CGFloat value))block; 16 | @end 17 | -------------------------------------------------------------------------------- /WCBlock/UISlider+WCBlock.m: -------------------------------------------------------------------------------- 1 | // 2 | // UISlider+WCBlock.m 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/17. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import "UISlider+WCBlock.h" 10 | #import 11 | static const int wc_sliderTarget_set_key; 12 | @interface WCSliderBlockTarget : NSObject 13 | @property (nonatomic,copy)void(^block)(CGFloat value); 14 | @end 15 | @implementation WCSliderBlockTarget 16 | -(void)wc_blockEmit:(UISlider*)sender { 17 | if (self.block)self.block(sender.value); 18 | } 19 | @end 20 | @implementation UISlider (WCBlock) 21 | -(void)wc_bindSliderValueChangedBlockNext:(void (^)(CGFloat value))block { 22 | WCSliderBlockTarget *target = [WCSliderBlockTarget new]; 23 | target.block = block; 24 | [[self wc_blockTargetSet] addObject:target]; 25 | [self addTarget:target action:@selector(wc_blockEmit:) forControlEvents:UIControlEventValueChanged]; 26 | } 27 | -(NSMutableSet*)wc_blockTargetSet{ 28 | NSMutableSet *_targets = objc_getAssociatedObject(self, &wc_sliderTarget_set_key); 29 | if (!_targets) { 30 | _targets = [NSMutableSet new]; 31 | objc_setAssociatedObject(self,&wc_sliderTarget_set_key,_targets, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 32 | } 33 | return _targets; 34 | } 35 | @end 36 | -------------------------------------------------------------------------------- /WCBlock/UISwitch+WCBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // UISwitch+WCBlock.h 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/17. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UISwitch (WCBlock) 12 | /**@!brief EN: bind switch object call back. zh-CN:绑定switch切换回调 13 | * @param block EN: call back. zh-CN :回调 14 | */ 15 | -(void)wc_bindSwitchValueChangedBlockNext:(void (^)(BOOL isOn))block; 16 | @end 17 | -------------------------------------------------------------------------------- /WCBlock/UISwitch+WCBlock.m: -------------------------------------------------------------------------------- 1 | // 2 | // UISwitch+WCBlock.m 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/17. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import "UISwitch+WCBlock.h" 10 | #import 11 | static const int wc_switchTarget_set_key; 12 | @interface WCSwitchBlockTarget : NSObject 13 | @property (nonatomic,copy)void(^block)(BOOL isOn); 14 | @end 15 | @implementation WCSwitchBlockTarget 16 | -(void)wc_blockEmit:(UISwitch*)sender { 17 | if (self.block)self.block(sender.isOn); 18 | } 19 | @end 20 | @implementation UISwitch (WCBlock) 21 | -(void)wc_bindSwitchValueChangedBlockNext:(void (^)(BOOL isOn))block { 22 | WCSwitchBlockTarget *target = [WCSwitchBlockTarget new]; 23 | target.block = block; 24 | [[self wc_blockTargetSet] addObject:target]; 25 | [self addTarget:target action:@selector(wc_blockEmit:) forControlEvents:UIControlEventValueChanged]; 26 | } 27 | -(NSMutableSet*)wc_blockTargetSet{ 28 | NSMutableSet *_targets = objc_getAssociatedObject(self, &wc_switchTarget_set_key); 29 | if (!_targets) { 30 | _targets = [NSMutableSet new]; 31 | objc_setAssociatedObject(self,&wc_switchTarget_set_key,_targets, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 32 | } 33 | return _targets; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /WCBlock/UITextField+WCBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // UITextField+WCBlock.h 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/16. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import 10 | @interface UITextField (WCBlock) 11 | 12 | - (void)wc_bindTextFieldEditingDidBeginBlockNext:(void (^)(UITextField *textField))block; 13 | - (void)wc_bindTextFieldEditingChangedBlockNext:(void (^)(UITextField *textField,NSString *value))block; 14 | - (void)wc_bindTextFieldEditingDidEndBlockNext:(void (^)(UITextField *textField))block; 15 | - (void)wc_bindTextFieldEditingDidEndOnExitBlockNext:(void (^)(UITextField *textField))block; 16 | 17 | //>>>>>>>>>>>>>>>>>TextField hander block>>>>>>>>>>>>>>>>>>> 18 | // EN:for using methods as bellow you need to be knowed that if you use its delegate to listen UITextField object and also use the following block handler at the same time,it will be effective by only one way , this depends on your opportunity to set up delegate and block handler for UITextField object (later effective), it's important about this. 19 | // zh-CN:对于以下handler回调你需要知道, 如果你使用了自己的代理实现的方式又使用了以下handlerBlock回调的方式,将只有一种方案有效,取决于你为textField设置代理delegate的时机,最终都是后来者有效。这点你需要知晓,并希望你选者其一。 20 | 21 | - (void)wc_bindTextFieldShouldChangeCharactersHandlerBlock:(BOOL (^)(UITextField*textField,NSRange inRange ,NSString*replacementString))block;// return NO to not change text 22 | 23 | - (void)wc_bindTextFieldShouldBeginEditingHandlerBlock:(BOOL (^)(UITextField*textField))block;// return NO to disallow editing. 24 | 25 | - (void)wc_bindTextFieldShouldEndEditingHandlerBlock:(BOOL (^)(UITextField*textField))block;// return YES to allow editing to stop and to resign first responder status. NO to disallow the editing session to end 26 | 27 | - (void)wc_bindTextFieldShouldReturnHandlerBlock:(BOOL (^)(UITextField*textField))block; // when 'return' key pressed. return NO to ignore. 28 | 29 | - (void)wc_bindTextFieldShouldClearHandlerBlock:(BOOL (^)(UITextField*textField))block;// when clear button pressed. return NO to ignore (no notifications) 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /WCBlock/UITextField+WCBlock.m: -------------------------------------------------------------------------------- 1 | // 2 | // UITextField+WCBlock.m 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/16. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import "UITextField+WCBlock.h" 10 | #import "UIControl+WCBlock.h" 11 | #import 12 | 13 | static const int wc_textField_blockTarget_set_key; 14 | static const int wc_textField_shouldChangeCharactersHandlerBlock_key; 15 | static const int wc_textField_shouldBeginEditingHandlerBlock_key; 16 | static const int wc_textField_shouldEndEditingHandlerBlock_key; 17 | static const int wc_textField_shouldReturnHandlerBlock_key; 18 | static const int wc_textField_shouldClearHandlerBlock_key; 19 | 20 | @interface WCTextFieldBlockTarget : NSObject 21 | @property (nonatomic,copy)void(^editingDidBeginBlock)(UITextField *textField); 22 | @property (nonatomic,copy)void(^editingChangedBlock)(UITextField *textField,NSString *value); 23 | @property (nonatomic,copy)void(^editingDidEndBlock)(UITextField *textField); 24 | @property (nonatomic,copy)void(^editingDidEndOnExitBlock)(UITextField *textField); 25 | @end 26 | @implementation WCTextFieldBlockTarget 27 | - (void)wc_textFieldTextEditingDidBegin:(UITextField*)textField { 28 | if (self.editingDidBeginBlock)self.editingDidBeginBlock(textField); 29 | } 30 | - (void)wc_textFieldEditingChanged:(UITextField*)textField { 31 | if (self.editingChangedBlock)self.editingChangedBlock(textField,textField.text); 32 | } 33 | - (void)wc_textFieldTextEditingDidEnd:(UITextField*)textField { 34 | if (self.editingDidEndBlock)self.editingDidEndBlock(textField); 35 | } 36 | - (void)wc_textEditingDidEndOnExit:(UITextField*)textField { 37 | if (self.editingDidEndOnExitBlock)self.editingDidEndOnExitBlock(textField); 38 | } 39 | @end 40 | @interface UITextField() 41 | @end 42 | @implementation UITextField (WCBlock) 43 | - (void)wc_bindTextFieldEditingDidBeginBlockNext:(void (^)(UITextField *textField))block { 44 | WCTextFieldBlockTarget *target = [WCTextFieldBlockTarget new]; 45 | target.editingDidBeginBlock = block; 46 | [[self wc_blockTargetSet] addObject:target]; 47 | [self addTarget:target action:@selector(wc_textFieldTextEditingDidBegin:) forControlEvents:UIControlEventEditingDidBegin]; 48 | } 49 | - (void)wc_bindTextFieldEditingChangedBlockNext:(void (^)(UITextField *textField,NSString *value))block { 50 | WCTextFieldBlockTarget *target = [WCTextFieldBlockTarget new]; 51 | target.editingChangedBlock = block; 52 | [[self wc_blockTargetSet] addObject:target]; 53 | [self addTarget:target action:@selector(wc_textFieldEditingChanged:) forControlEvents:UIControlEventEditingChanged]; 54 | } 55 | - (void)wc_bindTextFieldEditingDidEndBlockNext:(void (^)(UITextField *textField))block { 56 | WCTextFieldBlockTarget *target = [WCTextFieldBlockTarget new]; 57 | target.editingDidEndBlock = block; 58 | [[self wc_blockTargetSet] addObject:target]; 59 | [self addTarget:target action:@selector(wc_textFieldTextEditingDidEnd:) forControlEvents:UIControlEventEditingDidEnd]; 60 | } 61 | - (void)wc_bindTextFieldEditingDidEndOnExitBlockNext:(void (^)(UITextField *textField))block { 62 | WCTextFieldBlockTarget *target = [WCTextFieldBlockTarget new]; 63 | target.editingDidEndOnExitBlock = block; 64 | [[self wc_blockTargetSet] addObject:target]; 65 | [self addTarget:target action:@selector(wc_textEditingDidEndOnExit:) forControlEvents:UIControlEventEditingDidEndOnExit]; 66 | } 67 | - (void)wc_bindTextFieldShouldChangeCharactersHandlerBlock:(BOOL (^)(UITextField*textField,NSRange inRange ,NSString*replacementString))block { 68 | objc_setAssociatedObject(self,&wc_textField_shouldChangeCharactersHandlerBlock_key,block, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 69 | self.delegate = self; 70 | } 71 | - (void)wc_bindTextFieldShouldClearHandlerBlock:(BOOL (^)(UITextField*textField))block { 72 | objc_setAssociatedObject(self,&wc_textField_shouldClearHandlerBlock_key,block, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 73 | self.delegate = self; 74 | } 75 | - (void)wc_bindTextFieldShouldEndEditingHandlerBlock:(BOOL (^)(UITextField*textField))block{ 76 | objc_setAssociatedObject(self,&wc_textField_shouldEndEditingHandlerBlock_key,block, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 77 | self.delegate = self; 78 | } 79 | - (void)wc_bindTextFieldShouldReturnHandlerBlock:(BOOL (^)(UITextField*textField))block{ 80 | objc_setAssociatedObject(self,&wc_textField_shouldReturnHandlerBlock_key,block, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 81 | self.delegate = self; 82 | } 83 | - (void)wc_bindTextFieldShouldBeginEditingHandlerBlock:(BOOL (^)(UITextField*textField))block { 84 | objc_setAssociatedObject(self,&wc_textField_shouldBeginEditingHandlerBlock_key,block, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 85 | self.delegate = self; 86 | } 87 | - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { 88 | BOOL(^block)(UITextField*,NSRange,NSString*) = objc_getAssociatedObject(self, &wc_textField_shouldChangeCharactersHandlerBlock_key); 89 | if (block) return block(textField,range,string); 90 | return YES; 91 | } 92 | - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { 93 | BOOL(^block)(UITextField*) = objc_getAssociatedObject(self, &wc_textField_shouldBeginEditingHandlerBlock_key); 94 | if (block) return block(textField); 95 | return YES; 96 | } 97 | - (BOOL)textFieldShouldEndEditing:(UITextField *)textField { 98 | BOOL(^block)(UITextField*) = objc_getAssociatedObject(self, &wc_textField_shouldEndEditingHandlerBlock_key); 99 | if (block) return block(textField); 100 | return YES; 101 | } 102 | - (BOOL)textFieldShouldReturn:(UITextField *)textField { 103 | BOOL(^block)(UITextField*) = objc_getAssociatedObject(self, &wc_textField_shouldReturnHandlerBlock_key); 104 | if (block) return block(textField); 105 | return YES; 106 | } 107 | - (BOOL)textFieldShouldClear:(UITextField *)textField { 108 | BOOL(^block)(UITextField*) = objc_getAssociatedObject(self, &wc_textField_shouldClearHandlerBlock_key); 109 | if (block) return block(textField); 110 | return YES; 111 | } 112 | -(NSMutableSet*)wc_blockTargetSet{ 113 | NSMutableSet *_targets = objc_getAssociatedObject(self, &wc_textField_blockTarget_set_key); 114 | if (!_targets) { 115 | _targets = [NSMutableSet new]; 116 | objc_setAssociatedObject(self,&wc_textField_blockTarget_set_key,_targets, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 117 | } 118 | return _targets; 119 | } 120 | @end 121 | 122 | -------------------------------------------------------------------------------- /WCBlock/UITextView+WCBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // UITextView+WCBlock.h 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/17. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UITextView (WCBlock) 12 | 13 | - (void)wc_bindTextViewEditingChangedBlockNext:(void (^)(UITextView *textView,NSString *value))block; 14 | - (void)wc_bindTextViewEditingDidBeginBlockNext:(void (^)(UITextView *textField))block; 15 | - (void)wc_bindTextViewEditingDidEndBlockNext:(void (^)(UITextView *textField))block; 16 | 17 | // EN:for using handler as bellow you need to be knowed that if you use its delegate to listen UITextView object and also use the following block handler at the same time,it will be effective by only one way , this depends on your opportunity to set up delegate and block handler for UITextField object (later effective), it's important about this. 18 | // zh-CN: 对于以下handler回调你需要知道, 如果你使用了自己的代理实现的方式又使用了以下handlerBlock回调的方式,将只有一种方案有效,取决于你为textView设置代理delegate的时机,最终都是后来者有效。这点你需要知晓并希望你选者其一。 19 | 20 | - (void)wc_bindTextViewShouldChangeTextWithHandlerBlock:(BOOL (^)(UITextView*textView,NSRange inRange ,NSString*replacementText))block;// return NO to not change text 21 | ///bind block handler for textView object "shouldBeginEditing" 22 | 23 | - (void)wc_bindTextViewdShouldBeginEditingHandlerBlock:(BOOL (^)(UITextView*textView))block;// return NO to disallow editing. 24 | 25 | - (void)wc_bindTextViewShouldEndEditingHandlerBlock:(BOOL (^)(UITextView*textView))block;// return YES to allow editing to stop and to resign first responder status. NO to disallow the editing session to end 26 | - (void)wc_bindTextViewShouldInteractWithUrlHandlerBlock:(BOOL (^)(UITextView*textView,NSURL *url,NSRange inRange,UITextItemInteraction interaction NS_AVAILABLE_IOS(10_0)))block; 27 | 28 | - (void)wc_bindTextViewShouldInteractWithTextAttachmentHandlerBlock:(BOOL (^)(UITextView*textView,NSTextAttachment *textAttachment,NSRange inRange,UITextItemInteraction interaction NS_AVAILABLE_IOS(10_0)))block; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /WCBlock/UITextView+WCBlock.m: -------------------------------------------------------------------------------- 1 | // 2 | // UITextView+WCBlock.m 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/17. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import "UITextView+WCBlock.h" 10 | #import 11 | 12 | static const int wc_textView_shouldEndEditingHandlerBlock_key; 13 | static const int wc_textView_shouldChangeTextHandlerBlock_key; 14 | static const int wc_textView_shouldBeginEditingHandlerBlock_key; 15 | static const int wc_textView_shouldInteractWithUrlHandlerBlock_key; 16 | static const int wc_textView_shouldInteractWithTextAttachmentHandlerBlock_key; 17 | static const int wc_textView_blockTarget_set_key; 18 | 19 | @interface WCTextViewBlockTarget : NSObject 20 | @property (nonatomic,weak)UITextView *textView; 21 | @property (nonatomic,copy)void(^editingDidBeginBlock)(UITextView *textView); 22 | @property (nonatomic,copy)void(^editingChangedBlock)(UITextView *textView,NSString *value); 23 | @property (nonatomic,copy)void(^editingDidEndBlock)(UITextView *textView); 24 | @end 25 | @implementation WCTextViewBlockTarget 26 | -(void)setTextView:(UITextView *)textView { 27 | _textView = textView; 28 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textViewTextDidBeginEditing) name:UITextViewTextDidBeginEditingNotification object:textView]; 29 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textViewTextDidChange) name:UITextViewTextDidChangeNotification object:textView]; 30 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textViewTextDidEndEditing) name:UITextViewTextDidEndEditingNotification object:textView]; 31 | } 32 | - (void)textViewTextDidBeginEditing { 33 | if (self.editingDidBeginBlock)self.editingDidBeginBlock(self.textView); 34 | } 35 | - (void)textViewTextDidChange { 36 | if (self.editingChangedBlock) self.editingChangedBlock(self.textView,self.textView.text); 37 | } 38 | - (void)textViewTextDidEndEditing { 39 | if (self.editingDidEndBlock)self.editingDidEndBlock(self.textView); 40 | } 41 | - (void)removeObserver { 42 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextViewTextDidBeginEditingNotification object:self.textView]; 43 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextViewTextDidEndEditingNotification object:self.textView]; 44 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextViewTextDidChangeNotification object:self.textView]; 45 | } 46 | - (void)dealloc { 47 | [self removeObserver]; 48 | } 49 | @end 50 | @interface UITextView() 51 | @end 52 | @implementation UITextView (WCBlock) 53 | -(NSMutableSet*)wc_blockTargetSet{ 54 | NSMutableSet *_targets = objc_getAssociatedObject(self, &wc_textView_blockTarget_set_key); 55 | if (!_targets) { 56 | _targets = [NSMutableSet new]; 57 | objc_setAssociatedObject(self,&wc_textView_blockTarget_set_key,_targets, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 58 | } 59 | return _targets; 60 | } 61 | - (void)wc_bindTextViewEditingChangedBlockNext:(void (^)(UITextView *textView,NSString *value))block { 62 | WCTextViewBlockTarget *taget = [WCTextViewBlockTarget new]; 63 | taget.editingChangedBlock = block; 64 | taget.textView = self; 65 | [[self wc_blockTargetSet] addObject:taget]; 66 | } 67 | - (void)wc_bindTextViewEditingDidBeginBlockNext:(void (^)(UITextView *textField))block { 68 | WCTextViewBlockTarget *taget = [WCTextViewBlockTarget new]; 69 | taget.editingDidBeginBlock = block; 70 | taget.textView = self; 71 | [[self wc_blockTargetSet] addObject:taget]; 72 | } 73 | - (void)wc_bindTextViewEditingDidEndBlockNext:(void (^)(UITextView *textField))block { 74 | WCTextViewBlockTarget *taget = [WCTextViewBlockTarget new]; 75 | taget.editingDidEndBlock = block; 76 | taget.textView = self; 77 | [[self wc_blockTargetSet] addObject:taget]; 78 | } 79 | - (void)wc_bindTextViewShouldChangeTextWithHandlerBlock:(BOOL (^)(UITextView*textView,NSRange inRange ,NSString*replacementText))block { 80 | objc_setAssociatedObject(self,&wc_textView_shouldChangeTextHandlerBlock_key,block, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 81 | self.delegate = self; 82 | } 83 | - (void)wc_bindTextViewdShouldBeginEditingHandlerBlock:(BOOL (^)(UITextView*textView))block { 84 | objc_setAssociatedObject(self,&wc_textView_shouldBeginEditingHandlerBlock_key,block, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 85 | self.delegate = self; 86 | } 87 | - (void)wc_bindTextViewShouldEndEditingHandlerBlock:(BOOL (^)(UITextView*textView))block; { 88 | objc_setAssociatedObject(self,&wc_textView_shouldEndEditingHandlerBlock_key,block, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 89 | self.delegate = self; 90 | } 91 | - (void)wc_bindTextViewShouldInteractWithUrlHandlerBlock:(BOOL (^)(UITextView*textView,NSURL *url,NSRange inRange,UITextItemInteraction interaction NS_AVAILABLE_IOS(10_0)))block{ 92 | objc_setAssociatedObject(self,&wc_textView_shouldInteractWithUrlHandlerBlock_key,block, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 93 | self.delegate = self; 94 | } 95 | - (void)wc_bindTextViewShouldInteractWithTextAttachmentHandlerBlock:(BOOL (^)(UITextView*textView,NSTextAttachment *textAttachment,NSRange inRange,UITextItemInteraction interaction NS_AVAILABLE_IOS(10_0)))block{ 96 | objc_setAssociatedObject(self,&wc_textView_shouldInteractWithTextAttachmentHandlerBlock_key,block, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 97 | self.delegate = self; 98 | } 99 | - (BOOL)textViewShouldBeginEditing:(UITextView *)textView { 100 | BOOL(^block)(UITextView*) = objc_getAssociatedObject(self, &wc_textView_shouldBeginEditingHandlerBlock_key); 101 | if (block) return block(textView); 102 | return YES; 103 | } 104 | - (BOOL)textViewShouldEndEditing:(UITextView *)textView { 105 | BOOL(^block)(UITextView*) = objc_getAssociatedObject(self, &wc_textView_shouldEndEditingHandlerBlock_key); 106 | if (block) return block(textView); 107 | return YES; 108 | } 109 | - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { 110 | BOOL(^block)(UITextView*,NSRange,NSString*) = objc_getAssociatedObject(self, &wc_textView_shouldChangeTextHandlerBlock_key); 111 | if (block) return block(textView,range,text); 112 | return YES; 113 | } 114 | - (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction NS_AVAILABLE_IOS(10_0){ 115 | BOOL(^block)(UITextView*,NSURL*,NSRange,UITextItemInteraction) = objc_getAssociatedObject(self, &wc_textView_shouldInteractWithUrlHandlerBlock_key); 116 | if(block) return block(textView,URL,characterRange,interaction); 117 | return YES; 118 | } 119 | - (BOOL)textView:(UITextView *)textView shouldInteractWithTextAttachment:(NSTextAttachment *)textAttachment inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction NS_AVAILABLE_IOS(10_0){ 120 | BOOL(^block)(UITextView*,NSTextAttachment*,NSRange,UITextItemInteraction) = objc_getAssociatedObject(self, &wc_textView_shouldInteractWithTextAttachmentHandlerBlock_key); 121 | if(block)return block(textView,textAttachment,characterRange,interaction); 122 | return YES; 123 | } 124 | 125 | @end 126 | -------------------------------------------------------------------------------- /WCBlock/UIView+WCBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+WCBlock.h 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/16. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "WCViewGesture.h" 11 | @interface UIView (WCBlock) 12 | ///轻拍 13 | -(WCViewTap*)wc_bindViewTapBlockNext:(void (^)(UIView *view,WCViewTap *tap))block; 14 | ///轻扫 15 | -(WCViewSwipe*)wc_bindViewSwipeBlockNext:(void (^)(UIView *view,WCViewSwipe *swipe))block; 16 | ///长按 17 | -(WCViewLongPress*)wc_bindViewLongPressBlockNext:(void (^)(UIView *view,WCViewLongPress *longPress))block; 18 | ///平移 19 | -(WCViewPan*)wc_bindViewPanBlockNext:(void (^)(UIView *view,WCViewPan *pan))block; 20 | ///捏合(缩放) 21 | -(WCViewPinch*)wc_bindViewPinchBlockNext:(void (^)(UIView *view,WCViewPinch *pinch))block; 22 | ///旋转 23 | -(WCViewRotation*)wc_bindViewRotationBlockNext:(void (^)(UIView *view,WCViewRotation *rotation))block ; 24 | ///屏幕边缘平移 25 | -(WCViewScreenEdgePan*)wc_bindViewScreenEdgePanBlockNext:(void (^)(UIView *view,WCViewScreenEdgePan *screenEdgePan))block; 26 | @end 27 | -------------------------------------------------------------------------------- /WCBlock/UIView+WCBlock.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+WCBlock.m 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/16. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import "UIView+WCBlock.h" 10 | #import 11 | 12 | @interface WCViewBlockTarget : NSObject 13 | @property (nonatomic,copy)void(^tapBlock)(UIView *,WCViewTap *); 14 | @property (nonatomic,copy)void(^swipeBlock)(UIView *,WCViewSwipe *); 15 | @property (nonatomic,copy)void(^longPressBlock)(UIView*,WCViewLongPress *); 16 | @property (nonatomic,copy)void(^panBlock)(UIView *,WCViewPan *); 17 | @property (nonatomic,copy)void(^pinchBlock)(UIView *,WCViewPinch *); 18 | @property (nonatomic,copy)void(^rotationBlock)(UIView *,WCViewRotation *); 19 | @property (nonatomic,copy)void(^screenEdgePanBlock)(UIView *,WCViewScreenEdgePan *); 20 | @property (nonatomic,weak) UIView *view; 21 | @end 22 | @implementation WCViewBlockTarget 23 | @end 24 | @implementation UIView (WCBlock) 25 | 26 | -(WCViewTap*)wc_bindViewTapBlockNext:(void (^)(UIView *view,WCViewTap *tap))block{ 27 | return [self wc_setTapGestureWithBlock:block]; 28 | } 29 | 30 | -(WCViewSwipe*)wc_bindViewSwipeBlockNext:(void (^)(UIView *view,WCViewSwipe *swipe))block { 31 | return [self wc_setSwipeGestureWithBlock:block]; 32 | } 33 | 34 | -(WCViewLongPress*)wc_bindViewLongPressBlockNext:(void (^)(UIView *view,WCViewLongPress *longPress))block { 35 | return [self wc_setLongPressGestureWithBlock:block]; 36 | } 37 | 38 | -(WCViewPan*)wc_bindViewPanBlockNext:(void (^)(UIView *view,WCViewPan *pan))block { 39 | return [self wc_setPanGestureWithBlock:block]; 40 | } 41 | 42 | -(WCViewPinch*)wc_bindViewPinchBlockNext:(void (^)(UIView *view,WCViewPinch *pinch))block { 43 | return [self wc_setPinchGestureWithBlock:block]; 44 | } 45 | 46 | -(WCViewRotation*)wc_bindViewRotationBlockNext:(void (^)(UIView *view,WCViewRotation *rotation))block { 47 | return [self wc_setRotationGestureWithBlock:block]; 48 | } 49 | 50 | -(WCViewScreenEdgePan*)wc_bindViewScreenEdgePanBlockNext:(void (^)(UIView *view,WCViewScreenEdgePan *screenEdgePan))block { 51 | return [self wc_setScreenEdgePanGestureWithBlock:block]; 52 | } 53 | 54 | -(WCViewTap*)wc_setTapGestureWithBlock:(void (^)(UIView*,WCViewTap*))block { 55 | WCViewBlockTarget *target = [WCViewBlockTarget new]; 56 | target.tapBlock = block; 57 | [[self wc_blockTargetSet] addObject:target]; 58 | WCViewTap *gesture = (WCViewTap*)[self wc_gestureRecognizerOf:[WCViewTap class]]; 59 | if (!gesture) { 60 | gesture = [[WCViewTap alloc] initWithTarget:self action:@selector(wc_viewGestrueEmit:)]; 61 | [self addGestureRecognizer:gesture]; 62 | } 63 | return gesture; 64 | } 65 | -(WCViewSwipe*)wc_setSwipeGestureWithBlock:(void (^)(UIView*,WCViewSwipe*))block { 66 | WCViewBlockTarget *target = [WCViewBlockTarget new]; 67 | target.swipeBlock = block; 68 | [[self wc_blockTargetSet] addObject:target]; 69 | WCViewSwipe *gesture = (WCViewSwipe*)[self wc_gestureRecognizerOf:[WCViewSwipe class]]; 70 | if (!gesture) { 71 | gesture = [[WCViewSwipe alloc] initWithTarget:self action:@selector(wc_viewGestrueEmit:)]; 72 | [self addGestureRecognizer:gesture]; 73 | } 74 | return gesture; 75 | } 76 | -(WCViewLongPress*)wc_setLongPressGestureWithBlock:(void (^)(UIView*,WCViewLongPress*))block { 77 | WCViewBlockTarget *target = [WCViewBlockTarget new]; 78 | target.longPressBlock = block; 79 | [[self wc_blockTargetSet] addObject:target]; 80 | WCViewLongPress *gesture = (WCViewLongPress*)[self wc_gestureRecognizerOf:[WCViewLongPress class]]; 81 | if (!gesture) { 82 | gesture = [[WCViewLongPress alloc] initWithTarget:self action:@selector(wc_viewGestrueEmit:)]; 83 | [self addGestureRecognizer:gesture]; 84 | } 85 | return gesture; 86 | } 87 | -(WCViewPan*)wc_setPanGestureWithBlock:(void (^)(UIView*,WCViewPan*))block { 88 | WCViewBlockTarget *target = [WCViewBlockTarget new]; 89 | target.panBlock = block; 90 | [[self wc_blockTargetSet] addObject:target]; 91 | WCViewPan *gesture = (WCViewPan*)[self wc_gestureRecognizerOf:[WCViewPan class]]; 92 | if (!gesture) { 93 | gesture = [[WCViewPan alloc] initWithTarget:self action:@selector(wc_viewGestrueEmit:)]; 94 | [self addGestureRecognizer:gesture]; 95 | } 96 | return gesture; 97 | } 98 | -(WCViewPinch*)wc_setPinchGestureWithBlock:(void (^)(UIView*,WCViewPinch*))block { 99 | WCViewBlockTarget *target = [WCViewBlockTarget new]; 100 | target.pinchBlock = block; 101 | [[self wc_blockTargetSet] addObject:target]; 102 | WCViewPinch *gesture = (WCViewPinch*)[self wc_gestureRecognizerOf:[WCViewPinch class]]; 103 | if (!gesture) { 104 | gesture = [[WCViewPinch alloc] initWithTarget:self action:@selector(wc_viewGestrueEmit:)]; 105 | [self addGestureRecognizer:gesture]; 106 | } 107 | return gesture; 108 | } 109 | -(WCViewRotation*)wc_setRotationGestureWithBlock:(void (^)(UIView*,WCViewRotation*))block { 110 | WCViewBlockTarget *target = [WCViewBlockTarget new]; 111 | target.rotationBlock = block; 112 | [[self wc_blockTargetSet] addObject:target]; 113 | WCViewRotation *gesture = (WCViewRotation*)[self wc_gestureRecognizerOf:[WCViewRotation class]]; 114 | if (!gesture) { 115 | gesture = [[WCViewRotation alloc] initWithTarget:self action:@selector(wc_viewGestrueEmit:)]; 116 | [self addGestureRecognizer:gesture]; 117 | } 118 | return gesture; 119 | } 120 | -(WCViewScreenEdgePan*)wc_setScreenEdgePanGestureWithBlock:(void (^)(UIView*,WCViewScreenEdgePan*))block { 121 | WCViewBlockTarget *target = [WCViewBlockTarget new]; 122 | target.screenEdgePanBlock = block; 123 | [[self wc_blockTargetSet] addObject:target]; 124 | WCViewScreenEdgePan *gesture = (WCViewScreenEdgePan*)[self wc_gestureRecognizerOf:[WCViewScreenEdgePan class]]; 125 | if (!gesture) { 126 | gesture = [[WCViewScreenEdgePan alloc] initWithTarget:self action:@selector(wc_viewGestrueEmit:)]; 127 | [self addGestureRecognizer:gesture]; 128 | } 129 | return gesture; 130 | } 131 | 132 | -(NSMutableSet*)wc_blockTargetSet{ 133 | static const int wc_view_blockTarget_set_key; 134 | NSMutableSet *_targets = objc_getAssociatedObject(self, &wc_view_blockTarget_set_key); 135 | if (!_targets) { 136 | _targets = [NSMutableSet new]; 137 | objc_setAssociatedObject(self,&wc_view_blockTarget_set_key,_targets, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 138 | } 139 | return _targets; 140 | } 141 | - (UIGestureRecognizer*)wc_gestureRecognizerOf:(Class)gestureCalss{ 142 | for (UIGestureRecognizer *gesture in self.gestureRecognizers) { 143 | if ([gesture isKindOfClass:gestureCalss]) { 144 | return gesture; 145 | break; 146 | } 147 | } 148 | return nil; 149 | } 150 | - (void)wc_viewGestrueEmit:(id)sender { 151 | [[self wc_blockTargetSet]enumerateObjectsUsingBlock:^(WCViewBlockTarget * _Nonnull target, BOOL * _Nonnull stop) { 152 | if ([sender isKindOfClass:[WCViewTap class]]) { 153 | WCViewTap *tap = (WCViewTap*)sender; 154 | if (target.tapBlock) target.tapBlock(tap.view, tap); 155 | }else if ([sender isKindOfClass:[WCViewSwipe class]]) { 156 | WCViewSwipe *swipe = (WCViewSwipe*)sender; 157 | if (target.swipeBlock) target.swipeBlock(swipe.view, swipe); 158 | }else if ([sender isKindOfClass:[WCViewLongPress class]]) { 159 | WCViewLongPress *longPress = (WCViewLongPress*)sender; 160 | if (target.longPressBlock) target.longPressBlock(longPress.view, longPress); 161 | }else if ([sender isKindOfClass:[WCViewPan class]]) { 162 | WCViewPan *pan = (WCViewPan*)sender; 163 | if (target.panBlock) target.panBlock(pan.view, pan); 164 | }else if ([sender isKindOfClass:[WCViewPinch class]]) { 165 | WCViewPinch *pinch = (WCViewPinch*)sender; 166 | if (target.pinchBlock) target.pinchBlock(pinch.view, pinch); 167 | }else if ([sender isKindOfClass:[WCViewRotation class]]) { 168 | WCViewRotation *rotation = (WCViewRotation*)sender; 169 | if (target.rotationBlock) target.rotationBlock(rotation.view, rotation); 170 | }else if ([sender isKindOfClass:[WCViewScreenEdgePan class]]){ 171 | WCViewScreenEdgePan *screenEdgePan = (WCViewScreenEdgePan*)sender; 172 | if (target.screenEdgePanBlock) target.screenEdgePanBlock(screenEdgePan.view, screenEdgePan); 173 | }else { 174 | ///..none 175 | } 176 | }]; 177 | } 178 | 179 | @end 180 | -------------------------------------------------------------------------------- /WCBlock/WCBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // WCBlockExtension.h 3 | // WCBlockKit 4 | // 5 | // Created by zhao weicheng on 2018/4/18. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | //github https://github.com/manakiaHk/WCBlock 8 | //Welcome 9 | #ifndef WCBlock_h 10 | #define WCBlock_h 11 | 12 | #import "UIControl+WCBlock.h" 13 | #import "UIGestureRecognizer+WCBlock.h" 14 | #import "NSObject+WCKVOBlock.h" 15 | #import "UIAlertView+WCBlock.h" 16 | #import "UIView+WCBlock.h" 17 | #import "UITextField+WCBlock.h" 18 | #import "UITextView+WCBlock.h" 19 | #import "UISegmentedControl+WCBlock.h" 20 | #import "UISlider+WCBlock.h" 21 | #import "UISwitch+WCBlock.h" 22 | #import "UISearchBar+WCBlock.h" 23 | #import "NSNotificationCenter+WCBlock.h" 24 | #endif /* WCBlock_h */ 25 | -------------------------------------------------------------------------------- /WCBlock/WCViewGesture.h: -------------------------------------------------------------------------------- 1 | // 2 | // WCViewGesture.h 3 | // WCBlock 4 | // 5 | // Created by zhao weicheng on 2018/4/29. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | @interface WCViewTap:UITapGestureRecognizer 12 | @end 13 | @interface WCViewSwipe:UISwipeGestureRecognizer 14 | @end 15 | @interface WCViewLongPress:UILongPressGestureRecognizer 16 | @end 17 | @interface WCViewPan:UIPanGestureRecognizer 18 | @end 19 | @interface WCViewPinch: UIPinchGestureRecognizer 20 | @end 21 | @interface WCViewRotation:UIRotationGestureRecognizer 22 | @end 23 | @interface WCViewScreenEdgePan:UIScreenEdgePanGestureRecognizer 24 | @end 25 | -------------------------------------------------------------------------------- /WCBlock/WCViewGesture.m: -------------------------------------------------------------------------------- 1 | // 2 | // WCViewGesture.m 3 | // WCBlock 4 | // 5 | // Created by zhao weicheng on 2018/4/29. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import "WCViewGesture.h" 10 | @implementation WCViewTap 11 | @end 12 | @implementation WCViewSwipe 13 | @end 14 | @implementation WCViewLongPress 15 | @end 16 | @implementation WCViewPan 17 | @end 18 | @implementation WCViewPinch 19 | @end 20 | @implementation WCViewRotation 21 | @end 22 | @implementation WCViewScreenEdgePan 23 | @end 24 | -------------------------------------------------------------------------------- /WCBlockDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // WCBlock 4 | // 5 | // Created by zhao weicheng on 2018/4/24. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /WCBlockDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // WCBlock 4 | // 5 | // Created by zhao weicheng on 2018/4/24. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /WCBlockDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /WCBlockDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /WCBlockDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /WCBlockDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /WCBlockDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // WCBlock 4 | // 5 | // Created by zhao weicheng on 2018/4/24. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /WCBlockDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // WCBlock 4 | // 5 | // Created by zhao weicheng on 2018/4/24. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | //github https://github.com/manakiaHk/WCBlock 8 | 9 | #import "ViewController.h" 10 | #import "WCBlock.h" 11 | @interface ViewController () 12 | @property (nonatomic,weak) UILabel *label; 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | ///alear 21 | UIAlertView *alearView = [[UIAlertView alloc]initWithTitle:@"hello" message:@"keep your dream" delegate:nil cancelButtonTitle:@"cancle" otherButtonTitles:@"ok", nil]; 22 | 23 | [alearView wc_bindAlertButtonClickedBlockNext:^(NSInteger index) { 24 | NSLog(@"0--clicked index: %ld",index); 25 | }]; 26 | [alearView wc_bindAlertButtonClickedBlockNext:^(NSInteger index) { 27 | NSLog(@"1--clicked index: %ld",index); 28 | }]; 29 | 30 | [alearView show]; 31 | 32 | ////button 33 | UIButton *button = [[UIButton alloc]init]; 34 | [button wc_bindForControlEvents:UIControlEventTouchUpInside blockNext:^(id sender) { 35 | NSLog(@"%@",sender); 36 | }]; 37 | 38 | ///textfiled 39 | UITextField *textfiled = [[UITextField alloc]initWithFrame:CGRectMake(40, 40, 180, 35)]; 40 | textfiled.backgroundColor = [UIColor colorWithWhite:0 alpha:0.1]; 41 | textfiled.placeholder = @"please input your tel number..."; 42 | [self.view addSubview:textfiled]; 43 | [textfiled wc_bindTextFieldEditingChangedBlockNext:^(UITextField *textField, NSString *value) { 44 | NSLog(@"textfiled text:%@",value); 45 | }]; 46 | [textfiled wc_bindTextFieldShouldChangeCharactersHandlerBlock:^BOOL(UITextField *textField, NSRange shouldChangeCharactersInRange, NSString *replacementString) { 47 | return YES; 48 | }]; 49 | [textfiled wc_bindTextFieldEditingDidBeginBlockNext:^(UITextField *textField) { 50 | NSLog(@"textfiled did begin editing"); 51 | }]; 52 | [textfiled wc_bindTextFieldEditingDidEndBlockNext:^(UITextField *textField) { 53 | NSLog(@"textfiled did end editing"); 54 | }]; 55 | 56 | ///view 57 | UIView *view = [[UIView alloc]initWithFrame:CGRectMake(40, CGRectGetMaxY(textfiled.frame)+15, 80, 40)]; 58 | view.backgroundColor = [UIColor blueColor]; 59 | [self.view addSubview:view]; 60 | 61 | ///segmentedControl 62 | UISegmentedControl *segment = [[UISegmentedControl alloc]initWithItems:@[@"title0",@"title1",@"title2"]]; 63 | segment.frame = CGRectMake(40, CGRectGetMaxY(view.frame)+15, 180, 40); 64 | [self.view addSubview:segment]; 65 | [segment wc_bindSegmentControlValueChangedBlockNext:^(NSInteger selectedIndex) { 66 | NSLog(@"segment selected index %ld",selectedIndex); 67 | }]; 68 | 69 | ///gestureRecognizer 70 | UITapGestureRecognizer *tapGes = [[UITapGestureRecognizer alloc]init]; 71 | [self.view addGestureRecognizer:tapGes]; 72 | [tapGes wc_bindGestureBlockNext:^(UIGestureRecognizer *sender) { 73 | NSLog(@"gestureRecognizer sender--%@",sender); 74 | }]; 75 | 76 | 77 | ///slider 78 | UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(40, CGRectGetMaxY(segment.frame)+15, 60, 30)]; 79 | label.textColor = [UIColor redColor]; 80 | label.textAlignment =NSTextAlignmentCenter; 81 | [self.view addSubview:label]; 82 | self.label = label; 83 | UISlider *slider = [[UISlider alloc]initWithFrame:CGRectMake(CGRectGetMaxX(label.frame)+15, label.frame.origin.y, 200, 40)]; 84 | [self.view addSubview:slider]; 85 | 86 | ///tip: 和以往一样,当wcblock 捕获了外部变量,可能将导致循环引用 ,你需要用 __weak 避免这样事情发生 87 | __weak typeof(self) weakSelf = self; 88 | [slider wc_bindSliderValueChangedBlockNext:^(CGFloat value) { 89 | __strong typeof(weakSelf) self = weakSelf; 90 | NSLog(@"slider value :%0.2f",value); 91 | self.label.text = [NSString stringWithFormat:@"%0.02f",value]; 92 | self.label.backgroundColor = [UIColor greenColor]; 93 | self.label.alpha = 1-value; 94 | }]; 95 | 96 | 97 | ///NSNotificationCenter 98 | ///WCBlock 将自动为你管理移除消息中心的observer对象,你可放心使用 99 | [WCNotificationCenter wc_addObserverForName:@"wc_noti_demo" object:nil contextObj:self blockNext:^(NSNotification * _Nullable note) { 100 | NSLog(@"%@",note.userInfo[@"note_demo"]); 101 | }]; 102 | 103 | ///notification test demo 104 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 105 | [WCNotificationCenter postNotificationName:@"wc_noti_demo" object:nil userInfo:@{@"note_demo":@"WCBlock将自动为你管理移除observer对象"}]; 106 | 107 | }); 108 | 109 | //KVO drag slider changed 110 | [self.label wc_addObserverForKeyPath:@"text" valueBlockNext:^(NSString *keypath, id ofObj, id oldValue, id newValue) { 111 | NSLog(@"label.text = %@",newValue); 112 | }]; 113 | [self.label wc_addObserverForKeyPaths:@[@"alpha",@"text"] valueBlockNext:^(NSString *keypath, id ofObj, id oldValue, id newValue) { 114 | if ([keypath isEqualToString:@"alpha"]) { 115 | NSLog(@"label.alpha= %@",newValue); 116 | }else if([keypath isEqualToString:@"text"]){ 117 | NSLog(@"label.text= %@",newValue); 118 | }else; 119 | }]; 120 | 121 | [self.label wc_addObserverForKeyPath:@"text" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld changeBlockNext:^(NSString *keypath, id ofObj, NSDictionary *change) { 122 | ///.. 123 | }]; 124 | // and so on ... 125 | 126 | 127 | ///tip:你可以为每个对象绑定多个同样类型的block ,每个block都会调用 ,这样设计是因为不排除你会在多个地方同时使用,所以你要知道WCBlock是可以做到这点的。 但是记住 handerBlock 除外,它只能绑定一个,因为你并不希望多个hander同时操作一个对象,所以对于handerBlock WCBlock 是不允许的。e.g: 128 | 129 | ///下面view的每个block 都将调用 且返回值是同一个WCViewTap对象,因为你知道 ,每一个view只能同时绑定一个同样类型的手势 130 | WCViewTap *tap0 = [view wc_bindViewTapBlockNext:^(UIView *view, WCViewTap *tap) { 131 | NSLog(@"0--view taped"); 132 | }]; 133 | ///你可以通过返回值设置属性以及代理 这点和Apple的api完全一样 ,比如 134 | tap0.numberOfTapsRequired = 2; 135 | tap0.delegate = self; 136 | 137 | WCViewTap *tap1 = [view wc_bindViewTapBlockNext:^(UIView *view, WCViewTap *tap) { 138 | NSLog(@"1--view taped"); 139 | }]; 140 | WCViewTap *tap2 = [view wc_bindViewTapBlockNext:^(UIView *view, WCViewTap *tap) { 141 | NSLog(@"2--view taped"); 142 | }]; 143 | WCViewTap *tap3 = [view wc_bindViewTapBlockNext:^(UIView *view, WCViewTap *tap) { 144 | NSLog(@"3--view taped"); 145 | }]; 146 | 147 | 148 | ///你还可以绑定其他的手势block回调。e.g: 149 | WCViewPan *pan0 = [view wc_bindViewPanBlockNext:^(UIView *view, WCViewPan *pan) { 150 | NSLog(@"pan..."); 151 | }]; 152 | WCViewLongPress *longPress0 = [view wc_bindViewLongPressBlockNext:^(UIView *view, WCViewLongPress *longPress) { 153 | NSLog(@"0--longPressed"); 154 | }]; 155 | WCViewLongPress *longPress1 = [view wc_bindViewLongPressBlockNext:^(UIView *view, WCViewLongPress *longPress) { 156 | NSLog(@"1--longPressed"); 157 | }]; 158 | 159 | [view wc_bindViewRotationBlockNext:^(UIView *view, WCViewRotation *rotation) { 160 | NSLog(@"%0.2f",rotation.rotation);//旋转角度 161 | NSLog(@"%0.2f",rotation.velocity);//旋转速度 162 | }]; 163 | 164 | NSLog(@">>>>>%p-%p-%p-%p-%p-%p-%p",tap0,tap1,tap2,tap3,pan0,longPress0,longPress1); 165 | 166 | 167 | ///像下面的 block 只有最后一个有效(请注意,它们是 HandlerBlock) 168 | [textfiled wc_bindTextFieldShouldChangeCharactersHandlerBlock:^BOOL(UITextField *textField, NSRange shouldChangeCharactersInRange, NSString *replacementString) { 169 | if ([replacementString containsString:@"a"]) { 170 | return NO; 171 | } 172 | return YES; 173 | }]; 174 | [textfiled wc_bindTextFieldShouldChangeCharactersHandlerBlock:^BOOL(UITextField *textField, NSRange shouldChangeCharactersInRange, NSString *replacementString) { 175 | if ([replacementString containsString:@"b"]) { 176 | return NO; 177 | } 178 | return YES; 179 | }]; 180 | [textfiled wc_bindTextFieldShouldChangeCharactersHandlerBlock:^BOOL(UITextField *textField, NSRange shouldChangeCharactersInRange, NSString *replacementString) { 181 | if ([replacementString containsString:@"c"]) { 182 | return NO; 183 | } 184 | return YES; 185 | }]; 186 | 187 | 188 | UISearchBar *searchBar = [[UISearchBar alloc]initWithFrame:CGRectMake(40, CGRectGetMaxY(slider.frame), 200, 50)]; 189 | [self.view addSubview:searchBar]; 190 | searchBar.backgroundColor = [UIColor purpleColor]; 191 | searchBar.placeholder = @"亲输入文字"; 192 | [searchBar wc_bindSearchBarTextDidChangeBlockNext:^(UISearchBar *searchBar, NSString *searchText) { 193 | NSLog(@"0--%@",searchText); 194 | }]; 195 | [searchBar wc_bindSearchBarTextDidChangeBlockNext:^(UISearchBar *searchBar, NSString *searchText) { 196 | NSLog(@"1--%@",searchText); 197 | }]; 198 | [searchBar wc_bindSearchBarTextDidChangeBlockNext:^(UISearchBar *searchBar, NSString *searchText) { 199 | NSLog(@"2--%@",searchText); 200 | }]; 201 | [searchBar wc_bindSearchBarCancelButtonClickedBlockNext:^(UISearchBar *searchBar) { 202 | NSLog(@"CancelButtonClicked"); 203 | }]; 204 | 205 | [searchBar wc_bindSearchBarShouldChangeCharactersHandlerBlock:^BOOL(UISearchBar *searchBar, NSRange inRange, NSString *replacementString) { 206 | if ([replacementString isEqualToString:@"q"]) { 207 | return NO; 208 | } 209 | return YES; 210 | }]; 211 | 212 | } 213 | 214 | ///和Apple api 一样 对于KVO 你需要自己移除键值观察,  像这样 215 | - (void)dealloc { 216 | [self.label wc_removeObserverForKeyPath:@"text"]; 217 | [self.label wc_removeObserverForKeyPath:@"alpha"]; 218 | // [self.label wc_removeObserverForKeyPaths:@[@"alpha",@"text"]]; 219 | } 220 | 221 | - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { 222 | return YES; 223 | } 224 | - (void)didReceiveMemoryWarning { 225 | [super didReceiveMemoryWarning]; 226 | // Dispose of any resources that can be recreated. 227 | } 228 | 229 | 230 | @end 231 | -------------------------------------------------------------------------------- /WCBlockDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // WCBlock 4 | // 5 | // Created by zhao weicheng on 2018/4/24. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /WCBlockTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /WCBlockTests/WCBlockTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // WCBlockTests.m 3 | // WCBlockTests 4 | // 5 | // Created by zhao weicheng on 2018/4/24. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WCBlockTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation WCBlockTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /WCBlockUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /WCBlockUITests/WCBlockUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // WCBlockUITests.m 3 | // WCBlockUITests 4 | // 5 | // Created by zhao weicheng on 2018/4/24. 6 | // Copyright © 2018年 weichengz. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WCBlockUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation WCBlockUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // 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. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | --------------------------------------------------------------------------------