├── DVDataBindKit ├── Products │ └── DVDataBindKit.framework │ │ ├── _CodeSignature │ │ ├── CodeSignature │ │ ├── CodeDirectory │ │ ├── CodeRequirements │ │ ├── CodeRequirements-1 │ │ └── CodeResources │ │ ├── Info.plist │ │ ├── DVDataBindKit │ │ ├── Modules │ │ └── module.modulemap │ │ └── Headers │ │ ├── DVDataBindKit.h │ │ └── DVDataBind.h ├── DVDataBindKit.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcuserdata │ │ │ └── mlgPro.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── mlgPro.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── DVDataBindKit │ ├── Category │ ├── NSNumber+DataBind.h │ ├── NSString+DataBind.h │ ├── NSObject+DataBind.h │ ├── NSNumber+DataBind.m │ ├── NSString+DataBind.m │ └── NSObject+DataBind.m │ ├── Model │ ├── DVDataBindTargetModel.h │ ├── DVDataBindTargetModel.m │ ├── DVDataBindObserverModel.h │ └── DVDataBindObserverModel.m │ ├── DVDataBindKit.h │ ├── Info.plist │ ├── Define │ └── DVDataBindDefine.h │ ├── Core │ ├── DVDataBindObserver.h │ └── DVDataBindObserverManager.h │ └── DVDataBind.h └── DVDataBindDemo ├── DVDataBindDemo ├── Project │ ├── Assets.xcassets │ │ ├── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ └── Info.plist ├── Resource │ └── image │ │ ├── user.png │ │ ├── icon-dog.jpg │ │ └── password.png ├── UI │ ├── 普通例子 │ │ ├── Model │ │ │ ├── DemoModel.m │ │ │ └── DemoModel.h │ │ ├── ViewController │ │ │ ├── DemoViewController.h │ │ │ └── DemoViewController.m │ │ └── View │ │ │ ├── DemoView.h │ │ │ ├── DemoView.m │ │ │ └── DemoView.xib │ ├── MVVM实现登录界面 例子 │ │ ├── Model │ │ │ ├── LoginModel.m │ │ │ └── LoginModel.h │ │ ├── ViewController │ │ │ ├── LoginViewController.h │ │ │ └── LoginViewController.m │ │ ├── View │ │ │ ├── LoginView.h │ │ │ ├── LoginView.m │ │ │ └── LoginView.xib │ │ └── ViewModel │ │ │ ├── LoginViewModel.h │ │ │ └── LoginViewModel.m │ ├── UIImageView 例子 │ │ ├── Model │ │ │ ├── ImageModel.m │ │ │ └── ImageModel.h │ │ ├── ViewController │ │ │ ├── ImageViewController.h │ │ │ └── ImageViewController.m │ │ └── View │ │ │ ├── ImageView.h │ │ │ ├── ImageView.m │ │ │ └── ImageView.xib │ ├── UISlider 例子 │ │ ├── Model │ │ │ ├── SliderModel.m │ │ │ └── SliderModel.h │ │ ├── ViewController │ │ │ ├── SliderViewController.h │ │ │ └── SliderViewController.m │ │ └── View │ │ │ ├── SliderView.h │ │ │ └── SliderView.m │ ├── UISwitch 例子 │ │ ├── Model │ │ │ ├── SwitchModel.m │ │ │ └── SwitchModel.h │ │ ├── ViewController │ │ │ ├── SwitchViewController.h │ │ │ └── SwitchViewController.m │ │ └── View │ │ │ ├── SwitchView.m │ │ │ └── SwitchView.h │ ├── UISegmented 例子 │ │ ├── Model │ │ │ ├── SegmentedModel.m │ │ │ └── SegmentedModel.h │ │ ├── ViewController │ │ │ ├── SegmentedViewController.h │ │ │ └── SegmentedViewController.m │ │ └── View │ │ │ ├── SegmentedView.h │ │ │ ├── SegmentedView.m │ │ │ └── SegmentedView.xib │ ├── UITextField 例子 │ │ ├── Model │ │ │ ├── TextFieldModel.m │ │ │ └── TextFieldModel.h │ │ ├── ViewController │ │ │ ├── TextFieldViewController.h │ │ │ └── TextFieldViewController.m │ │ └── View │ │ │ ├── TextFieldView.h │ │ │ └── TextFieldView.m │ ├── RootNavigationController.h │ ├── 数组 例子 │ │ ├── ViewController │ │ │ ├── ArrayViewController.h │ │ │ └── ArrayViewController.m │ │ ├── Model │ │ │ ├── ArrayModel.h │ │ │ └── ArrayModel.m │ │ └── View │ │ │ ├── ArrayView.h │ │ │ └── ArrayView.m │ ├── MainViewController │ │ ├── ViewController │ │ │ ├── MainViewController.h │ │ │ └── MainViewController.m │ │ ├── ViewModel │ │ │ ├── MainViewModel.h │ │ │ └── MainViewModel.m │ │ └── View │ │ │ ├── MainTableView.h │ │ │ └── MainTableView.m │ └── RootNavigationController.m ├── AOP │ ├── AOPKit.h │ └── UIViewController+AOP.h ├── Manager │ ├── DVManager.m │ ├── DVManager.h │ ├── DVAPPManager.h │ └── DVAPPManager.m ├── Category │ ├── UI │ │ ├── UIToolbar+Common.h │ │ ├── UIBarButtonItem+Common.h │ │ ├── UITextField+Common.h │ │ ├── UIBarButtonItem+Common.m │ │ ├── UIPanGestureRecognizer+Common.h │ │ ├── UINavigationController+Common.h │ │ ├── UITableView+Common.h │ │ ├── UILabel+Common.h │ │ ├── UINavigationController+Common.m │ │ ├── UIPanGestureRecognizer+Common.m │ │ ├── UIButton+Common.h │ │ ├── UIToolbar+Common.m │ │ ├── UIImage+Common.h │ │ ├── UITableView+Common.m │ │ ├── UICollectionView+Common.h │ │ ├── UITabBarController+Common.h │ │ ├── UIColor+BaseColor.h │ │ ├── UIViewController+Common.h │ │ ├── UIView+Common.h │ │ ├── UIColor+BaseColor.m │ │ ├── UIColor+Common.h │ │ ├── UITextField+Common.m │ │ ├── UICollectionView+Common.m │ │ ├── UIButton+Common.m │ │ ├── UILabel+Common.m │ │ ├── UITabBarController+Common.m │ │ ├── UIImage+Common.m │ │ ├── UIColor+Common.m │ │ └── UIViewController+Common.m │ └── DVCategoryKit.h ├── AppDelegate │ ├── AppDelegate.h │ ├── AppDelegate+UISetting.h │ ├── AppDelegate+Notification.h │ ├── AppDelegate.m │ └── AppDelegate+UISetting.m ├── Define │ └── Header.pch ├── Utils │ ├── Runtime │ │ ├── DVRuntimeKit.h │ │ ├── Model │ │ │ ├── DVRuntimeObjectModel.m │ │ │ └── DVRuntimeObjectModel.h │ │ ├── Category │ │ │ ├── NSObject+Runtime_Class.h │ │ │ ├── NSObject+Runtime_Class.m │ │ │ ├── NSObject+Runtime_VAR.h │ │ │ └── NSObject+Runtime_Method.h │ │ ├── DVRuntime.h │ │ └── DVRuntime.m │ ├── Frame │ │ └── DVFrame.h │ └── Info │ │ └── DVInfo.h └── Other │ └── main.m └── DVDataBindDemo.xcodeproj ├── project.xcworkspace ├── contents.xcworkspacedata ├── xcuserdata │ └── mlgPro.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── IDEFindNavigatorScopes.plist └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── xcuserdata └── mlgPro.xcuserdatad │ ├── xcschemes │ └── xcschememanagement.plist │ └── xcdebugger │ └── Breakpoints_v2.xcbkptlist └── xcshareddata └── xcschemes └── DVDataBindDemo.xcscheme /DVDataBindKit/Products/DVDataBindKit.framework/_CodeSignature/CodeSignature: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Project/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Resource/image/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shidavid/DVDataBind/HEAD/DVDataBindDemo/DVDataBindDemo/Resource/image/user.png -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Resource/image/icon-dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shidavid/DVDataBind/HEAD/DVDataBindDemo/DVDataBindDemo/Resource/image/icon-dog.jpg -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Resource/image/password.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shidavid/DVDataBind/HEAD/DVDataBindDemo/DVDataBindDemo/Resource/image/password.png -------------------------------------------------------------------------------- /DVDataBindKit/Products/DVDataBindKit.framework/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shidavid/DVDataBind/HEAD/DVDataBindKit/Products/DVDataBindKit.framework/Info.plist -------------------------------------------------------------------------------- /DVDataBindKit/Products/DVDataBindKit.framework/DVDataBindKit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shidavid/DVDataBind/HEAD/DVDataBindKit/Products/DVDataBindKit.framework/DVDataBindKit -------------------------------------------------------------------------------- /DVDataBindKit/Products/DVDataBindKit.framework/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module DVDataBindKit { 2 | umbrella header "DVDataBindKit.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /DVDataBindKit/Products/DVDataBindKit.framework/_CodeSignature/CodeDirectory: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shidavid/DVDataBind/HEAD/DVDataBindKit/Products/DVDataBindKit.framework/_CodeSignature/CodeDirectory -------------------------------------------------------------------------------- /DVDataBindKit/Products/DVDataBindKit.framework/_CodeSignature/CodeRequirements: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shidavid/DVDataBind/HEAD/DVDataBindKit/Products/DVDataBindKit.framework/_CodeSignature/CodeRequirements -------------------------------------------------------------------------------- /DVDataBindKit/Products/DVDataBindKit.framework/_CodeSignature/CodeRequirements-1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shidavid/DVDataBind/HEAD/DVDataBindKit/Products/DVDataBindKit.framework/_CodeSignature/CodeRequirements-1 -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit.xcodeproj/project.xcworkspace/xcuserdata/mlgPro.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shidavid/DVDataBind/HEAD/DVDataBindKit/DVDataBindKit.xcodeproj/project.xcworkspace/xcuserdata/mlgPro.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo.xcodeproj/project.xcworkspace/xcuserdata/mlgPro.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shidavid/DVDataBind/HEAD/DVDataBindDemo/DVDataBindDemo.xcodeproj/project.xcworkspace/xcuserdata/mlgPro.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/普通例子/Model/DemoModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoModel.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/18. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "DemoModel.h" 10 | 11 | @implementation DemoModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo.xcodeproj/project.xcworkspace/xcuserdata/mlgPro.xcuserdatad/IDEFindNavigatorScopes.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/MVVM实现登录界面 例子/Model/LoginModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // LoginModel.m 3 | // DVDataBindDemo 4 | // 5 | // Created by 施达威 on 2020/3/18. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "LoginModel.h" 10 | 11 | @implementation LoginModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UIImageView 例子/Model/ImageModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageModel.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "ImageModel.h" 10 | 11 | @implementation ImageModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UISlider 例子/Model/SliderModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // SliderModel.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "SliderModel.h" 10 | 11 | @implementation SliderModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UISwitch 例子/Model/SwitchModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // SwitchModel.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "SwitchModel.h" 10 | 11 | @implementation SwitchModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/AOP/AOPKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // AOPKit.h 3 | // iOS_Template_Objc 4 | // 5 | // Created by DV on 2019/8/21. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #ifndef AOPKit_h 10 | #define AOPKit_h 11 | 12 | #import "UIViewController+AOP.h" 13 | 14 | 15 | #endif /* AOPKit_h */ 16 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UISegmented 例子/Model/SegmentedModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // SegmentedModel.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "SegmentedModel.h" 10 | 11 | @implementation SegmentedModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UITextField 例子/Model/TextFieldModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // TextFieldModel.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "TextFieldModel.h" 10 | 11 | @implementation TextFieldModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/AOP/UIViewController+AOP.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+AOP.h 3 | // French 4 | // 5 | // Created by DV on 2019/7/31. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface UIViewController (AOP) 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Manager/DVManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // DVManager.m 3 | // 4 | // 5 | // Created by mlgPro on 2018/1/9. 6 | // Copyright © 2018年 com.znjk.test. All rights reserved. 7 | // 8 | 9 | #import "DVManager.h" 10 | 11 | @implementation DVManager 12 | 13 | + (DVAPPManager *)app { 14 | return [DVAPPManager sharedInstance]; 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UIToolbar+Common.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIToolbar+Common.h 3 | // French 4 | // 5 | // Created by DV on 2019/3/29. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface UIToolbar (Common) 14 | 15 | - (void)spaceToFit; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/AppDelegate/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // DVDataBindDemo 4 | // 5 | // Created by David.Shi on 2018/3/16. 6 | // Copyright © 2018 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/AppDelegate/AppDelegate+UISetting.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate+UISetting.h 3 | // 4 | // Created by David.Shi on 2018/1/27. 5 | // Copyright © 2018年 iOS. All rights reserved. 6 | // 7 | 8 | #import "AppDelegate.h" 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface AppDelegate (UISetting) 13 | 14 | /// 全局UI设置 15 | - (void)UISetting; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/普通例子/ViewController/DemoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoViewController.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/18. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DemoViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UIBarButtonItem+Common.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIBarButtonItem+Common.h 3 | // French 4 | // 5 | // Created by DV on 2019/3/29. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface UIBarButtonItem (Common) 14 | 15 | + (instancetype)spaceItem; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/RootNavigationController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RootNavigationController.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/16. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface RootNavigationController : UINavigationController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/数组 例子/ViewController/ArrayViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ArrayViewController.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ArrayViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/MVVM实现登录界面 例子/ViewController/LoginViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LoginViewController.h 3 | // DVDataBindDemo 4 | // 5 | // Created by 施达威 on 2020/3/18. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface LoginViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/MainViewController/ViewController/MainViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MainViewController.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/16. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MainViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UIImageView 例子/ViewController/ImageViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ImageViewController.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ImageViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UISlider 例子/ViewController/SliderViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SliderViewController.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface SliderViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UISwitch 例子/ViewController/SwitchViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SwitchViewController.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface SwitchViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/普通例子/Model/DemoModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoModel.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/18. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DemoModel : NSObject 14 | 15 | @property(nonatomic, copy) NSString *text; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UISegmented 例子/ViewController/SegmentedViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SegmentedViewController.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface SegmentedViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UITextField 例子/ViewController/TextFieldViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TextFieldViewController.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface TextFieldViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UISwitch 例子/Model/SwitchModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // SwitchModel.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface SwitchModel : NSObject 14 | 15 | @property(nonatomic, assign) BOOL isON; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UITextField+Common.h: -------------------------------------------------------------------------------- 1 | // 2 | // UITextField+DV.h 3 | // 4 | // 5 | // Created by DV on 2018/2/9. 6 | // Copyright © 2018年 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UITextField (Common) 12 | 13 | ///自动隐藏键盘 14 | @property(nonatomic, assign) BOOL isHiddenKeyBoardByReturnKeyDone; 15 | 16 | ///增加左边View 17 | - (void)addLeftView:(UIView *)view; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/数组 例子/Model/ArrayModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // ArrayModel.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ArrayModel : NSObject 14 | 15 | @property(nonatomic, strong) NSMutableArray *array; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/数组 例子/Model/ArrayModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // ArrayModel.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "ArrayModel.h" 10 | 11 | @implementation ArrayModel 12 | 13 | - (NSMutableArray *)array { 14 | if (!_array) { 15 | _array = [NSMutableArray array]; 16 | } 17 | return _array; 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UISegmented 例子/Model/SegmentedModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // SegmentedModel.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface SegmentedModel : NSObject 14 | 15 | @property(nonatomic, assign) int index; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UISlider 例子/Model/SliderModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // SliderModel.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface SliderModel : NSObject 14 | 15 | @property(nonatomic, assign) float sliderValue; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UIImageView 例子/Model/ImageModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // ImageModel.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ImageModel : NSObject 14 | 15 | @property(nonatomic, strong, nullable) UIImage *image; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit/Category/NSNumber+DataBind.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSNumber+DataBind.h 3 | // 4 | // Created by David.Shi on 2018/3/16. 5 | // Copyright © 2018 DVKit. All rights reserved. 6 | // 7 | 8 | #import 9 | #import "DVDataBindDefine.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface NSNumber (DataBind) 14 | 15 | - (NSNumber *)db_covertToNumberForType:(DBPropertyType)type; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/MainViewController/ViewModel/MainViewModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // MainViewModel.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/16. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MainViewModel : NSObject 14 | 15 | - (NSDictionary *)tableItems; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UIBarButtonItem+Common.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIBarButtonItem+Common.m 3 | // French 4 | // 5 | // Created by DV on 2019/3/29. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import "UIBarButtonItem+Common.h" 10 | 11 | @implementation UIBarButtonItem (Common) 12 | 13 | + (instancetype)spaceItem { 14 | return [[self alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Define/Header.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Header.pch 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/16. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #ifndef Header_pch 10 | #define Header_pch 11 | 12 | #import "DVCategoryKit.h" 13 | #import "DVFrame.h" 14 | #import "DVInfo.h" 15 | #import "DVManager.h" 16 | #import "DVRuntimeKit.h" 17 | #import "AOPKit.h" 18 | #import 19 | 20 | #endif /* Header_pch */ 21 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Utils/Runtime/DVRuntimeKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVRuntimeKit.h 3 | // iOS_Template_Objc 4 | // 5 | // Created by DV on 2019/8/12. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #ifndef DVRuntimeKit_h 10 | #define DVRuntimeKit_h 11 | 12 | #import "DVRuntime.h" 13 | #import "DVRuntimeObjectModel.h" 14 | #import "NSObject+Runtime_Class.h" 15 | #import "NSObject+Runtime_Method.h" 16 | #import "NSObject+Runtime_VAR.h" 17 | 18 | #endif /* DVRuntimeKit_h */ 19 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UITextField 例子/Model/TextFieldModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // TextFieldModel.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface TextFieldModel : NSObject 14 | 15 | @property(nonatomic, assign) int num; 16 | @property(nonatomic, copy) NSString *text; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo.xcodeproj/xcuserdata/mlgPro.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | DVDataBindDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit/Model/DVDataBindTargetModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVDataBindTargetModel.h 3 | // 4 | // Created by David.Shi on 2018/3/16. 5 | // Copyright © 2018 iOS. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface DVDataBindTargetModel : NSObject 13 | 14 | @property(nonatomic, copy) NSString *targetHash; 15 | 16 | - (instancetype)initWithTargetHash:(NSString *)targetHash; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/AppDelegate/AppDelegate+Notification.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate+Notification.h 3 | // MM 4 | // 5 | // Created by DV on 2019/8/27. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface AppDelegate (Notification) 14 | 15 | /// 添加全局通知监听 16 | - (void)addGlobalNotification; 17 | 18 | /// 移除全局通知监听,一般情况下不用移除 19 | - (void)removeGlobalNotification; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UIPanGestureRecognizer+Common.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIPanGestureRecognizer+Common.h 3 | // DVKit 4 | // 5 | // Created by mlgPro on 2020/1/18. 6 | // Copyright © 2020 DVKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface UIPanGestureRecognizer (Common) 14 | 15 | - (void)setXTranslationWithView:(UIView *)view; 16 | - (void)setYTranslationWithView:(UIView *)view; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/MVVM实现登录界面 例子/Model/LoginModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // LoginModel.h 3 | // DVDataBindDemo 4 | // 5 | // Created by 施达威 on 2020/3/18. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | // 这个 Model 是服务器的数据 14 | @interface LoginModel : NSObject 15 | 16 | @property(nonatomic, copy) NSString *userName; 17 | @property(nonatomic, copy) NSString *password; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/普通例子/View/DemoView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoView.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/18. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DemoView : UIView 14 | 15 | @property (weak, nonatomic) IBOutlet UILabel *label; 16 | @property (weak, nonatomic) IBOutlet UITextField *textField; 17 | @property (weak, nonatomic) IBOutlet UIButton *button; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UINavigationController+Common.h: -------------------------------------------------------------------------------- 1 | // 2 | // UINavigationController+DV.h 3 | // 4 | // 5 | // Created by DV on 2018/2/9. 6 | // Copyright © 2018年 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UINavigationController (Common) 12 | 13 | #pragma mark - <-- Method --> 14 | - (void)pushViewControllerWithStoryBoard:(NSString *)storyBoardName 15 | identifier:(NSString *)identifier 16 | animated:(BOOL)flag; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit/Category/NSString+DataBind.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+DataBind.h 3 | // 4 | // Created by David.Shi on 2018/3/16. 5 | // Copyright © 2018 DVKit. All rights reserved. 6 | // 7 | 8 | #import 9 | #import "DVDataBindDefine.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface NSString (DataBind) 14 | 15 | - (unsigned int)db_unsignedIntValue; 16 | - (unsigned long long)db_unsignedLongLongValue; 17 | 18 | - (NSNumber *)db_covertToNumberForType:(DBPropertyType)type; 19 | 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/MVVM实现登录界面 例子/View/LoginView.h: -------------------------------------------------------------------------------- 1 | // 2 | // LoginView.h 3 | // DVDataBindDemo 4 | // 5 | // Created by 施达威 on 2020/3/18. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface LoginView : UIView 14 | 15 | @property (weak, nonatomic) IBOutlet UITextField *userNameText; 16 | @property (weak, nonatomic) IBOutlet UITextField *passwordText; 17 | @property (weak, nonatomic) IBOutlet UIButton *btnLogin; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Manager/DVManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVManager.h 3 | // 4 | // 5 | // Created by mlgPro on 2018/1/9. 6 | // Copyright © 2018年 com.znjk.test. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "DVAPPManager.h" 11 | 12 | 13 | /** 14 | * APP运行时 生命周期内 数据管理 数据缓存 中间态 其他类型管理 15 | * APP关闭将失去所有数据 不保存 16 | * APP 中间件管理 17 | */ 18 | //TODO: Manager 尽量是 变量 或者 实现Delegate 的 服务管理 类,尽量少写方法,方法封装成工具类 19 | @interface DVManager : NSObject 20 | 21 | /// APP管理 22 | @property(nonatomic, class, readonly) DVAPPManager *app; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UIImageView 例子/View/ImageView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ImageView.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ImageView : UIView 14 | 15 | @property (weak, nonatomic) IBOutlet UIImageView *imageView; 16 | 17 | @property (weak, nonatomic) IBOutlet UIButton *btnChangeImage; 18 | @property (weak, nonatomic) IBOutlet UIButton *btnChangeNil; 19 | 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UISegmented 例子/View/SegmentedView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SegmentedView.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface SegmentedView : UIView 14 | 15 | @property (weak, nonatomic) IBOutlet UISegmentedControl *segmented; 16 | @property (weak, nonatomic) IBOutlet UIStepper *stepper; 17 | @property (weak, nonatomic) IBOutlet UIButton *btnChangeIndex; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/普通例子/View/DemoView.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoView.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/18. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "DemoView.h" 10 | 11 | @implementation DemoView 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | 16 | self.button.titleColor = [UIColor whiteColor]; 17 | self.button.backgroundImage = [UIImage imageWithColor:[UIColor Blue]]; 18 | self.button.backgroundImageForHighlighted = [UIImage imageWithColor:[UIColor Blue].darkColor]; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Other/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // DVDataBindDemo 4 | // 5 | // Created by David.Shi on 2018/3/16. 6 | // Copyright © 2018 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | NSString * appDelegateClassName; 14 | @autoreleasepool { 15 | // Setup code that might create autoreleased objects goes here. 16 | appDelegateClassName = NSStringFromClass([AppDelegate class]); 17 | } 18 | return UIApplicationMain(argc, argv, nil, appDelegateClassName); 19 | } 20 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/数组 例子/View/ArrayView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ArrayView.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ArrayView : UIView 14 | @property (weak, nonatomic) IBOutlet UITextField *textField1; 15 | @property (weak, nonatomic) IBOutlet UIButton *btnChange1; 16 | 17 | @property (weak, nonatomic) IBOutlet UITextField *textField2; 18 | @property (weak, nonatomic) IBOutlet UIButton *btnChange2; 19 | 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit.xcodeproj/xcuserdata/mlgPro.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | DVDataBindKit.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 19 11 | 12 | DVDataBindKitShell.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 17 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UISlider 例子/View/SliderView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SliderView.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface SliderView : UIView 14 | 15 | @property (weak, nonatomic) IBOutlet UILabel *lblTitle; 16 | @property (weak, nonatomic) IBOutlet UISlider *slider; 17 | 18 | @property (weak, nonatomic) IBOutlet UIProgressView *progressView; 19 | 20 | @property (weak, nonatomic) IBOutlet UIButton *btnChangeValue; 21 | 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit/DVDataBindKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVDataBindKit.h 3 | // 4 | // Created by David.Shi on 2018/3/16. 5 | // Copyright © 2018 DVUntilKit. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | #if __has_include() 11 | //! Project version number for DVDataBindKit. 12 | FOUNDATION_EXPORT double DVDataBindKitVersionNumber; 13 | 14 | //! Project version string for DVDataBindKit. 15 | FOUNDATION_EXPORT const unsigned char DVDataBindKitVersionString[]; 16 | 17 | 18 | #import 19 | 20 | #else 21 | 22 | #import "DVDataBind.h" 23 | 24 | #endif 25 | 26 | 27 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Utils/Runtime/Model/DVRuntimeObjectModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // DVRuntimeObjectModel.m 3 | // French 4 | // 5 | // Created by DV on 2019/8/12. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import "DVRuntimeObjectModel.h" 10 | 11 | @implementation DVRuntimeObjectModel 12 | 13 | - (NSString *)description { 14 | NSDictionary *dict = @{ 15 | @"name" : self.name, 16 | @"value" : self.value != nil ? self.value : @"nil", 17 | @"className" : self.className, 18 | }; 19 | 20 | return [dict description]; 21 | } 22 | 23 | @end 24 | 25 | -------------------------------------------------------------------------------- /DVDataBindKit/Products/DVDataBindKit.framework/Headers/DVDataBindKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVDataBindKit.h 3 | // 4 | // Created by David.Shi on 2018/3/16. 5 | // Copyright © 2018 DVUntilKit. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | #if __has_include() 11 | //! Project version number for DVDataBindKit. 12 | FOUNDATION_EXPORT double DVDataBindKitVersionNumber; 13 | 14 | //! Project version string for DVDataBindKit. 15 | FOUNDATION_EXPORT const unsigned char DVDataBindKitVersionString[]; 16 | 17 | 18 | #import 19 | 20 | #else 21 | 22 | #import "DVDataBind.h" 23 | 24 | #endif 25 | 26 | 27 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/MVVM实现登录界面 例子/ViewModel/LoginViewModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // LoginViewModel.h 3 | // DVDataBindDemo 4 | // 5 | // Created by 施达威 on 2020/3/18. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | // ViewModel 是关于 View的Model 14 | @interface LoginViewModel : NSObject 15 | 16 | @property(nonatomic, copy) NSString *userName; 17 | @property(nonatomic, copy) NSString *password; 18 | 19 | - (BOOL)btnLoginEnable; 20 | 21 | - (BOOL)filterUserName:(NSString *)userName; 22 | 23 | - (BOOL)filterPassword:(NSString *)password; 24 | 25 | - (void)login; 26 | 27 | @end 28 | 29 | NS_ASSUME_NONNULL_END 30 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UISlider 例子/View/SliderView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SliderView.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "SliderView.h" 10 | 11 | @implementation SliderView 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | 16 | self.slider.minimumValue = 0; 17 | self.slider.maximumValue = 100; 18 | 19 | self.btnChangeValue.titleColor = [UIColor whiteColor]; 20 | self.btnChangeValue.backgroundImage = [UIImage imageWithColor:[UIColor Blue]]; 21 | self.btnChangeValue.backgroundImageForHighlighted = [UIImage imageWithColor:[UIColor Blue].darkColor]; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UITableView+Common.h: -------------------------------------------------------------------------------- 1 | // 2 | // UITableView+DV.h 3 | // 4 | // 5 | // Created by DV on 2018/2/9. 6 | // Copyright © 2018年 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #pragma mark - <-------------------- UITableView (Common) --------------------> 12 | @interface UITableView (Common) 13 | 14 | /** 15 | * 获取已注册的Cell,若为nil,自动初始化 16 | * @param cellClass 已注册Cell的类 17 | */ 18 | - (__kindof UITableViewCell *)dequeueReusableCellWithClass:(Class)cellClass 19 | forIndexPath:(NSIndexPath *)indexPath; 20 | 21 | - (void)registerClass:(Class)cellClass; 22 | 23 | - (void)registerNibWithClass:(Class)cellClass; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/MainViewController/View/MainTableView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MainTableView.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/16. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @class MainTableView; 14 | @protocol MainTableViewDelegate 15 | 16 | - (void)MainTableView:(MainTableView *)view didSelectItem:(NSString *)item; 17 | 18 | @end 19 | 20 | 21 | @interface MainTableView : UITableView 22 | 23 | @property(nonatomic, weak) id mtvDelegate; 24 | @property(nonatomic, strong) NSDictionary *models; 25 | 26 | 27 | @end 28 | 29 | NS_ASSUME_NONNULL_END 30 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UISegmented 例子/View/SegmentedView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SegmentedView.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "SegmentedView.h" 10 | 11 | @implementation SegmentedView 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | 16 | self.stepper.minimumValue = 0; 17 | self.stepper.maximumValue = 4; 18 | 19 | self.btnChangeIndex.titleColor = [UIColor whiteColor]; 20 | self.btnChangeIndex.backgroundImage = [UIImage imageWithColor:[UIColor Blue]]; 21 | self.btnChangeIndex.backgroundImageForHighlighted = [UIImage imageWithColor:[UIColor Blue].darkColor]; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit/Model/DVDataBindTargetModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // DVDataBindTargetModel.m 3 | // 4 | // Created by David.Shi on 2018/3/16. 5 | // Copyright © 2018 iOS. All rights reserved. 6 | // 7 | 8 | #import "DVDataBindTargetModel.h" 9 | #import "DVDataBindObserverManager.h" 10 | 11 | @implementation DVDataBindTargetModel 12 | 13 | #pragma mark - <-- Instance --> 14 | - (instancetype)initWithTargetHash:(NSString *)targetHash { 15 | self = [super init]; 16 | if (self) { 17 | self.targetHash = targetHash; 18 | } 19 | return self; 20 | } 21 | 22 | 23 | #pragma mark - <-- Dealloc --> 24 | - (void)dealloc { 25 | [[DVDataBindObserverManager sharedInstance] unbindWithTargetHash:self.targetHash]; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo.xcodeproj/xcuserdata/mlgPro.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UILabel+Common.h: -------------------------------------------------------------------------------- 1 | // 2 | // UILabel+DV.h 3 | // 4 | // 5 | // Created by 施达威 on 2018/2/8. 6 | // Copyright © 2018年 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UILabel (Common) 12 | 13 | @property(nonatomic, assign) CGFloat fontSize; 14 | 15 | - (CGFloat)heightFromFitWidth:(CGFloat)width; 16 | 17 | 18 | /// 自动根据宽度适应字间距 19 | - (void)wordSpaceToFitWidth:(CGFloat)width; 20 | 21 | 22 | /// 改变行间距 23 | - (void)changeLineSpace:(float)space; 24 | 25 | /// 改变字间距 26 | - (void)changeWordSpace:(float)space; 27 | 28 | /// 改变行间距和字间距 29 | - (void)changeLineSpace:(float)lineSpace wordSpace:(float)wordSpace; 30 | 31 | - (void)addUnderLineWithString:(NSString *)string; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UINavigationController+Common.m: -------------------------------------------------------------------------------- 1 | // 2 | // UINavigationController+DV.m 3 | // 4 | // 5 | // Created by DV on 2018/2/9. 6 | // Copyright © 2018年 iOS. All rights reserved. 7 | // 8 | 9 | #import "UINavigationController+Common.h" 10 | 11 | @implementation UINavigationController (Common) 12 | 13 | - (void)pushViewControllerWithStoryBoard:(NSString *)storyBoardName 14 | identifier:(NSString *)identifier 15 | animated:(BOOL)flag { 16 | UIStoryboard *sb = [UIStoryboard storyboardWithName:storyBoardName bundle:nil]; 17 | UIViewController *vc = [sb instantiateViewControllerWithIdentifier:identifier]; 18 | [self pushViewController:vc animated:flag]; 19 | } 20 | 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UITextField 例子/View/TextFieldView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TextFieldView.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface TextFieldView : UIView 14 | 15 | @property (weak, nonatomic) IBOutlet UILabel *lblNormal; 16 | @property (weak, nonatomic) IBOutlet UILabel *lblConvert; 17 | 18 | @property (weak, nonatomic) IBOutlet UITextField *textField1; 19 | @property (weak, nonatomic) IBOutlet UITextField *textField2; 20 | 21 | @property (weak, nonatomic) IBOutlet UIButton *btnChangeNum; 22 | @property (weak, nonatomic) IBOutlet UIButton *btnChangeText; 23 | 24 | @end 25 | 26 | NS_ASSUME_NONNULL_END 27 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Utils/Runtime/Category/NSObject+Runtime_Class.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Runtime_Class.h 3 | // French 4 | // 5 | // Created by DV on 2019/8/12. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface NSObject (Runtime_Class) 14 | 15 | #pragma mark - <-- 获取信息 --> 16 | /// 获取本类 17 | - (Class)getClass; 18 | 19 | /// 获取本类 20 | + (Class)getClass; 21 | 22 | 23 | /// 获取元类 24 | - (Class)getMetaClass; 25 | 26 | /// 获取元类 27 | + (Class)getMetaClass; 28 | 29 | 30 | ///获取本类的类名 31 | - (NSString *)getClassName; 32 | 33 | ///获取本类的类名 34 | + (NSString *)getClassName; 35 | 36 | 37 | #pragma mark - <-- Method --> 38 | - (void)changeToClass:(Class)aClass; 39 | 40 | @end 41 | 42 | NS_ASSUME_NONNULL_END 43 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Manager/DVAPPManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVAPPManager.h 3 | // 4 | // 5 | // Created by mlgPro on 2019/2/28. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface DVAPPManager : NSObject 15 | 16 | #pragma mark - <-- Property --> 17 | @property(nonatomic, weak) AppDelegate *appDelegate; 18 | 19 | /// 当前ViewController 20 | @property(nonatomic, weak) UIViewController *currentViewController; 21 | 22 | @property(nonatomic, weak) UIViewController *topViewController; 23 | 24 | @property(nonatomic, strong) NSMutableArray *viewControllerStack; 25 | 26 | #pragma mark - <-- SharedInstance --> 27 | + (instancetype)sharedInstance; 28 | 29 | @end 30 | 31 | NS_ASSUME_NONNULL_END 32 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/MainViewController/ViewModel/MainViewModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // MainViewModel.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/16. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "MainViewModel.h" 10 | 11 | @implementation MainViewModel 12 | 13 | - (NSDictionary *)tableItems { 14 | return @{ 15 | @"MVVM 实现登录界面 例子" : @"LoginViewController", 16 | @"普通例子" : @"DemoViewController", 17 | @"UISwitch 例子" : @"SwitchViewController", 18 | @"UITextField 例子" : @"TextFieldViewController", 19 | @"UIImageView 例子" : @"ImageViewController", 20 | @"UISlider 例子" : @"SliderViewController", 21 | @"UISegmentControl 例子" : @"SegmentedViewController", 22 | @"数组 例子" : @"ArrayViewController", 23 | }; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/数组 例子/View/ArrayView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ArrayView.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "ArrayView.h" 10 | 11 | @implementation ArrayView 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | 16 | self.btnChange1.titleColor = [UIColor whiteColor]; 17 | self.btnChange1.backgroundImage = [UIImage imageWithColor:[UIColor Blue]]; 18 | self.btnChange1.backgroundImageForHighlighted = [UIImage imageWithColor:[UIColor Blue].darkColor]; 19 | 20 | self.btnChange2.titleColor = [UIColor whiteColor]; 21 | self.btnChange2.backgroundImage = [UIImage imageWithColor:[UIColor Blue]]; 22 | self.btnChange2.backgroundImageForHighlighted = [UIImage imageWithColor:[UIColor Blue].darkColor]; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | $(MARKETING_VERSION) 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UIPanGestureRecognizer+Common.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIPanGestureRecognizer+Common.m 3 | // DVKit 4 | // 5 | // Created by mlgPro on 2020/1/18. 6 | // Copyright © 2020 DVKit. All rights reserved. 7 | // 8 | 9 | #import "UIPanGestureRecognizer+Common.h" 10 | 11 | @implementation UIPanGestureRecognizer (Common) 12 | 13 | - (void)setXTranslationWithView:(UIView *)view { 14 | CGPoint transPoint = [self translationInView:view]; 15 | view.transform = CGAffineTransformTranslate(view.transform, transPoint.x, 0); 16 | [self setTranslation:CGPointZero inView:view]; 17 | } 18 | 19 | - (void)setYTranslationWithView:(UIView *)view { 20 | CGPoint transPoint = [self translationInView:view]; 21 | view.transform = CGAffineTransformTranslate(view.transform, 0, transPoint.y); 22 | [self setTranslation:CGPointZero inView:view]; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/DVCategoryKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVCategoryKit.h 3 | // DVLibrary 4 | // 5 | // Created by DV on 2019/12/31. 6 | // Copyright © 2019 DVLibrary. All rights reserved. 7 | // 8 | 9 | #ifndef DVCategoryKit_h 10 | #define DVCategoryKit_h 11 | 12 | // UI 13 | #import "UIColor+Common.h" 14 | #import "UIColor+BaseColor.h" 15 | #import "UIImage+Common.h" 16 | #import "UIButton+Common.h" 17 | #import "UIBarButtonItem+Common.h" 18 | #import "UILabel+Common.h" 19 | #import "UIView+Common.h" 20 | #import "UITableView+Common.h" 21 | #import "UICollectionView+Common.h" 22 | #import "UITextField+Common.h" 23 | #import "UIViewController+Common.h" 24 | #import "UINavigationController+Common.h" 25 | #import "UITabBarController+Common.h" 26 | #import "UIToolbar+Common.h" 27 | #import "UIPanGestureRecognizer+Common.h" 28 | 29 | //#endif 30 | 31 | 32 | #endif /* DVCategoryKit_h */ 33 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UIButton+Common.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+Common.h 3 | // iOS_Template_Objc 4 | // 5 | // Created by DV on 2018/1/9. 6 | // Copyright © 2018年 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIButton (Common) 12 | 13 | @property(nonatomic, strong) NSString *title; 14 | @property(nonatomic, strong) NSString *titleForHighlighted; 15 | 16 | @property(nonatomic, strong) UIImage *image; 17 | @property(nonatomic, strong) UIImage *imageForHighlighted; 18 | @property(nonatomic, strong) UIImage *imageForSelected; 19 | 20 | @property(nonatomic, strong) UIImage *backgroundImage; 21 | @property(nonatomic, strong) UIImage *backgroundImageForHighlighted; 22 | 23 | @property(nonatomic, strong) UIColor *titleColor; 24 | @property(nonatomic, strong) UIColor *titleColorForHighlighted; 25 | 26 | - (void)constraintToFit; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UIImageView 例子/View/ImageView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageView.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "ImageView.h" 10 | 11 | @implementation ImageView 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | 16 | self.btnChangeImage.titleColor = [UIColor whiteColor]; 17 | self.btnChangeImage.backgroundImage = [UIImage imageWithColor:[UIColor Blue]]; 18 | self.btnChangeImage.backgroundImageForHighlighted = [UIImage imageWithColor:[UIColor Blue].darkColor]; 19 | 20 | self.btnChangeNil.titleColor = [UIColor whiteColor]; 21 | self.btnChangeNil.backgroundImage = [UIImage imageWithColor:[UIColor Blue]]; 22 | self.btnChangeNil.backgroundImageForHighlighted = [UIImage imageWithColor:[UIColor Blue].darkColor]; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UIToolbar+Common.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIToolbar+Common.m 3 | // French 4 | // 5 | // Created by DV on 2019/3/29. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import "UIToolbar+Common.h" 10 | 11 | @implementation UIToolbar (Common) 12 | 13 | - (void)spaceToFit { 14 | if (self.items && self.items.count > 1) { 15 | NSUInteger count = self.items.count * 2 - 1; 16 | 17 | UIBarButtonItem *spaceItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; 18 | NSMutableArray *items = [self.items mutableCopy]; 19 | 20 | for (NSUInteger i = 1; i < count; i+=2) { 21 | [items insertObject:spaceItem atIndex:i]; 22 | } 23 | 24 | [self setItems:[items copy] animated:NO]; 25 | } 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UISwitch 例子/View/SwitchView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SwitchView.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "SwitchView.h" 10 | 11 | @implementation SwitchView 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | 16 | self.btnChangeEnable.titleColor = [UIColor whiteColor]; 17 | self.btnChangeEnable.backgroundImage = [UIImage imageWithColor:[UIColor Blue]]; 18 | self.btnChangeEnable.backgroundImageForHighlighted = [UIImage imageWithColor:[UIColor Blue].darkColor]; 19 | 20 | self.btnChangeIsON.titleColor = [UIColor whiteColor]; 21 | self.btnChangeIsON.backgroundImage = [UIImage imageWithColor:[UIColor Blue]]; 22 | self.btnChangeIsON.backgroundImageForHighlighted = [UIImage imageWithColor:[UIColor Blue].darkColor]; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UITextField 例子/View/TextFieldView.m: -------------------------------------------------------------------------------- 1 | // 2 | // TextFieldView.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "TextFieldView.h" 10 | 11 | @implementation TextFieldView 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | 16 | self.btnChangeNum.titleColor = [UIColor whiteColor]; 17 | self.btnChangeNum.backgroundImage = [UIImage imageWithColor:[UIColor Blue]]; 18 | self.btnChangeNum.backgroundImageForHighlighted = [UIImage imageWithColor:[UIColor Blue].darkColor]; 19 | 20 | self.btnChangeText.titleColor = [UIColor whiteColor]; 21 | self.btnChangeText.backgroundImage = [UIImage imageWithColor:[UIColor Blue]]; 22 | self.btnChangeText.backgroundImageForHighlighted = [UIImage imageWithColor:[UIColor Blue].darkColor]; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Manager/DVAPPManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // DVAPPManager.m 3 | // 4 | // 5 | // Created by mlgPro on 2019/2/28. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import "DVAPPManager.h" 10 | 11 | @implementation DVAPPManager 12 | 13 | + (instancetype)sharedInstance { 14 | static dispatch_once_t onceToken; 15 | static DVAPPManager *instance = nil; 16 | dispatch_once(&onceToken,^{ 17 | instance = [[super allocWithZone:NULL] init]; 18 | }); 19 | return instance; 20 | } 21 | 22 | + (id)allocWithZone:(struct _NSZone *)zone{ 23 | return [self sharedInstance]; 24 | } 25 | 26 | 27 | #pragma mark - <-- Property --> 28 | - (NSMutableArray *)viewControllerStack { 29 | if (!_viewControllerStack) { 30 | _viewControllerStack = [NSMutableArray array]; 31 | } 32 | return _viewControllerStack; 33 | } 34 | 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/RootNavigationController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RootNavigationController.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/16. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "RootNavigationController.h" 10 | 11 | @interface RootNavigationController () 12 | 13 | @end 14 | 15 | @implementation RootNavigationController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view. 20 | } 21 | 22 | /* 23 | #pragma mark - Navigation 24 | 25 | // In a storyboard-based application, you will often want to do a little preparation before navigation 26 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 27 | // Get the new view controller using [segue destinationViewController]. 28 | // Pass the selected object to the new view controller. 29 | } 30 | */ 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit/Category/NSObject+DataBind.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+DataBind.h 3 | // 4 | // Created by David.Shi on 2018/3/16. 5 | // Copyright © 2018 iOS. All rights reserved. 6 | // 7 | 8 | #import 9 | #import "DVDataBindDefine.h" 10 | #import "DVDataBindTargetModel.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface NSObject (DataBind) 15 | 16 | @property(nonatomic, assign) BOOL db_isDidChanged; 17 | 18 | @property(nonatomic, strong) DVDataBindTargetModel *db_targetModel; 19 | 20 | @property(nonatomic, copy) NSString *db_ctrl_targetKeyHash; 21 | 22 | @property(nonatomic, copy, readonly) NSString *db_Hash; 23 | 24 | /// 获取属性property类型, 只能对于对象 25 | @property(nonatomic, assign, readonly) DBPropertyType db_propertyType; 26 | 27 | 28 | /// 获取属性property类型, 任意类型 29 | - (DBPropertyType)db_getDBPropertyTypeWithName:(NSString *)propertyName; 30 | 31 | 32 | @end 33 | 34 | NS_ASSUME_NONNULL_END 35 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Utils/Runtime/Category/NSObject+Runtime_Class.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Runtime_Class.m 3 | // French 4 | // 5 | // Created by DV on 2019/8/12. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import "NSObject+Runtime_Class.h" 10 | #import 11 | 12 | @implementation NSObject (Runtime_Class) 13 | 14 | #pragma mark - <-- 获取信息 --> 15 | - (Class)getClass { 16 | return [self class]; 17 | } 18 | 19 | + (Class)getClass { 20 | return [self class]; 21 | } 22 | 23 | - (Class)getMetaClass { 24 | return object_getClass([self class]); 25 | } 26 | 27 | + (Class)getMetaClass { 28 | return object_getClass([self class]); 29 | } 30 | 31 | - (NSString *)getClassName { 32 | return NSStringFromClass([self class]); 33 | } 34 | 35 | + (NSString *)getClassName { 36 | return NSStringFromClass([self class]); 37 | } 38 | 39 | 40 | #pragma mark - <-- Method --> 41 | - (void)changeToClass:(Class)aClass { 42 | object_setClass(self, aClass); 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UIImage+Common.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Common.h 3 | // 4 | // 5 | // Created by DV on 2019/2/25. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface UIImage (Common) 14 | 15 | #pragma mark - <-- Instance --> 16 | + (instancetype)imageWithColor:(UIColor *)color; 17 | 18 | + (instancetype)imageWithColor:(UIColor *)color size:(CGSize)size; 19 | 20 | /// 渲染模式:Original 21 | + (instancetype)imageWithOriginal:(NSString *)name; 22 | 23 | 24 | #pragma mark - <-- Method --> 25 | /// 根据面积 改变图片尺寸 26 | - (UIImage *)resizeImageWithSize:(CGSize)size; 27 | 28 | /// 根据比例 改变图片尺寸 29 | - (UIImage *)resizeImageWithScale:(CGFloat)scale; 30 | 31 | /// 剪切成圆形 32 | - (UIImage *)clipToCircleImage; 33 | 34 | - (UIImage *)addText:(NSString *)text fontColor:(UIColor *)fontColor fontSize:(CGFloat)fontSize; 35 | 36 | /// 保存至系统相册 37 | - (void)saveToPhotoAlbum:(nullable void(^)(BOOL finished))completion; 38 | 39 | @end 40 | 41 | NS_ASSUME_NONNULL_END 42 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/MVVM实现登录界面 例子/ViewModel/LoginViewModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // LoginViewModel.m 3 | // DVDataBindDemo 4 | // 5 | // Created by 施达威 on 2020/3/18. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "LoginViewModel.h" 10 | #import "LoginModel.h" 11 | 12 | 13 | @implementation LoginViewModel 14 | 15 | - (BOOL)btnLoginEnable { 16 | return (self.userName && self.userName.length > 0 17 | && self.password && self.password.length > 0); 18 | } 19 | 20 | - (BOOL)filterUserName:(NSString *)userName { 21 | // 这里可加 userName判断处理 22 | return userName.length <= 15; 23 | } 24 | 25 | - (BOOL)filterPassword:(NSString *)password { 26 | // 这里可加 password判断处理 27 | return password.length <= 20; 28 | } 29 | 30 | - (void)login { 31 | // Model是服务器请求数据, ViewModel是关于View的Model 32 | LoginModel *model = [[LoginModel alloc] init]; 33 | model.userName = self.userName; 34 | model.password = self.password; 35 | 36 | // 这里post model 到服务器 37 | NSLog(@"登录成功, userName -> %@, password -> %@", model.userName, model.password); 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UITableView+Common.m: -------------------------------------------------------------------------------- 1 | // 2 | // UITableView+DV.m 3 | // 4 | // 5 | // Created by DV on 2018/2/9. 6 | // Copyright © 2018年 iOS. All rights reserved. 7 | // 8 | 9 | #import "UITableView+Common.h" 10 | 11 | @implementation UITableView (Common) 12 | 13 | - (UITableViewCell *)dequeueReusableCellWithClass:(Class)cellClass forIndexPath:(NSIndexPath *)indexPath { 14 | UITableViewCell *cell = [self dequeueReusableCellWithIdentifier:NSStringFromClass(cellClass) 15 | forIndexPath:indexPath]; 16 | 17 | return cell ? cell : [[cellClass alloc] initWithStyle:UITableViewCellStyleDefault 18 | reuseIdentifier:NSStringFromClass(cellClass)]; 19 | } 20 | 21 | - (void)registerClass:(Class)cellClass { 22 | [self registerClass:cellClass forCellReuseIdentifier:NSStringFromClass(cellClass)]; 23 | } 24 | 25 | - (void)registerNibWithClass:(Class)cellClass { 26 | NSString *cellName = NSStringFromClass(cellClass); 27 | UINib *nib = [UINib nibWithNibName:cellName bundle:nil]; 28 | [self registerNib:nib forCellReuseIdentifier:cellName]; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UISwitch 例子/View/SwitchView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SwitchView.h 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface SwitchView : UIView 14 | 15 | @property (weak, nonatomic) IBOutlet UISwitch *inSW1; 16 | @property (weak, nonatomic) IBOutlet UISwitch *inSW2; 17 | @property (weak, nonatomic) IBOutlet UISwitch *inSW3; 18 | 19 | @property (weak, nonatomic) IBOutlet UISwitch *inoutSW1; 20 | @property (weak, nonatomic) IBOutlet UISwitch *inoutSW2; 21 | @property (weak, nonatomic) IBOutlet UISwitch *inoutSW3; 22 | 23 | @property (weak, nonatomic) IBOutlet UISwitch *outSW1; 24 | @property (weak, nonatomic) IBOutlet UISwitch *outSW2; 25 | @property (weak, nonatomic) IBOutlet UISwitch *outSW3; 26 | @property (weak, nonatomic) IBOutlet UISwitch *notSW; 27 | 28 | @property (weak, nonatomic) IBOutlet UITextField *textField; 29 | 30 | @property (weak, nonatomic) IBOutlet UIButton *btnChangeEnable; 31 | 32 | @property (weak, nonatomic) IBOutlet UIButton *btnChangeIsON; 33 | 34 | @end 35 | 36 | NS_ASSUME_NONNULL_END 37 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UICollectionView+Common.h: -------------------------------------------------------------------------------- 1 | // 2 | // UICollectionView+Common.h 3 | // French 4 | // 5 | // Created by DV on 2019/3/12. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface UICollectionView (Common) 14 | 15 | #pragma mark - <-- Method --> 16 | /** 17 | * 获取已注册的Cell,若为nil,自动初始化 18 | * @param cellClass 已注册Cell的类 19 | */ 20 | - (__kindof UICollectionViewCell *)dequeueReusableCellWithClass:(Class)cellClass 21 | forIndexPath:(NSIndexPath *)indexPath; 22 | 23 | /// 24 | - (__kindof UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)elementKind 25 | withClass:(Class)viewClass 26 | forIndexPath:(NSIndexPath *)indexPath; 27 | 28 | /// 29 | - (void)registerClass:(Class)cellClass; 30 | 31 | /// 32 | - (void)registerClassForSectionHeader:(Class)viewClass; 33 | 34 | /// 35 | - (void)registerClassForSectionFooter:(Class)viewClass; 36 | 37 | @end 38 | 39 | NS_ASSUME_NONNULL_END 40 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UITabBarController+Common.h: -------------------------------------------------------------------------------- 1 | // 2 | // UITabBarController+Common.h 3 | // French 4 | // 5 | // Created by DV on 2019/3/29. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | #pragma mark - <-------------------- Define --------------------> 14 | @protocol UITabBarControllerDataSource 15 | 16 | - (NSUInteger)numberOfTabItems; 17 | 18 | - (UIViewController *)tabItemAtIndex:(NSUInteger)index; 19 | 20 | @end 21 | 22 | 23 | #pragma mark - <-------------------- Class --------------------> 24 | @interface UITabBarController (Common) 25 | 26 | @property(nonatomic, weak) id dataSource; 27 | 28 | - (void)reload; 29 | 30 | - (void)setTabBarItems:(NSArray *)viewControllers; 31 | - (void)insertTabItem:(UIViewController *)viewController atIndex:(NSInteger)index; 32 | - (void)insertTabItemAtFirst:(UIViewController *)viewController; 33 | - (void)insertTabItemAtLast:(UIViewController *)viewController; 34 | 35 | - (void)removeAllTabItems; 36 | - (void)removeTabItem:(NSInteger)index; 37 | - (void)removeFirstTabItem; 38 | - (void)removeLastTabItem; 39 | 40 | @end 41 | 42 | NS_ASSUME_NONNULL_END 43 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UIColor+BaseColor.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+BaseColor.h 3 | // MM 4 | // 5 | // Created by DV on 2019/8/30. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface UIColor (BaseColor) 14 | 15 | #pragma mark - <-- 基础色 --> 16 | @property(nonatomic, class, readonly) UIColor *Blue; 17 | @property(nonatomic, class, readonly) UIColor *Blue1; 18 | @property(nonatomic, class, readonly) UIColor *Blue2; 19 | 20 | @property(nonatomic, class, readonly) UIColor *Green; 21 | @property(nonatomic, class, readonly) UIColor *Green1; 22 | @property(nonatomic, class, readonly) UIColor *Green2; 23 | 24 | @property(nonatomic, class, readonly) UIColor *Red; 25 | @property(nonatomic, class, readonly) UIColor *Red1; 26 | @property(nonatomic, class, readonly) UIColor *Red2; 27 | 28 | @property(nonatomic, class, readonly) UIColor *Orange; 29 | @property(nonatomic, class, readonly) UIColor *Orange1; 30 | @property(nonatomic, class, readonly) UIColor *Orange2; 31 | 32 | @property(nonatomic, class, readonly) UIColor *Gray; 33 | @property(nonatomic, class, readonly) UIColor *Gray1; 34 | @property(nonatomic, class, readonly) UIColor *Gray2; 35 | 36 | @end 37 | 38 | NS_ASSUME_NONNULL_END 39 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/AppDelegate/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // DVDataBindDemo 4 | // 5 | // Created by David.Shi on 2018/3/16. 6 | // Copyright © 2018 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "RootNavigationController.h" 11 | #import "MainViewController.h" 12 | #import "AppDelegate+UISetting.h" 13 | #import "AppDelegate+Notification.h" 14 | 15 | @interface AppDelegate () 16 | 17 | @end 18 | 19 | @implementation AppDelegate 20 | 21 | 22 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 23 | 24 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 25 | [self.window setBackgroundColor:[UIColor whiteColor]]; 26 | [self initMainViewController:self.window]; 27 | [self.window makeKeyAndVisible]; 28 | 29 | [self UISetting]; 30 | [self addGlobalNotification]; 31 | 32 | return YES; 33 | } 34 | 35 | - (void)initMainViewController:(UIWindow *)window { 36 | MainViewController *mainVC = [[MainViewController alloc] init]; 37 | RootNavigationController *rootNC = [[RootNavigationController alloc] initWithRootViewController:mainVC]; 38 | 39 | [window setRootViewController:rootNC]; 40 | } 41 | 42 | 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Utils/Runtime/Category/NSObject+Runtime_VAR.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Runtime_VAR.h 3 | // French 4 | // 5 | // Created by DV on 2019/8/12. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "DVRuntimeObjectModel.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | @class DVRuntimeObjectModel; 14 | 15 | @interface NSObject (Runtime_VAR) 16 | 17 | /// 获取属性property类型, 只能对于对象 18 | @property(nonatomic, assign, readonly) PropertyType propertyType; 19 | 20 | /// 获取属性property列表 21 | @property(nonatomic, copy, readonly) NSArray *propertyList; 22 | 23 | /// 获取所有成员属性列表 (包括property) 24 | @property(nonatomic, copy, readonly) NSArray *ivarList; 25 | 26 | /// 获取所有Property详细信息 27 | @property(nonatomic, copy, readonly) NSArray *propertyListInDetail; 28 | 29 | /// 获取所有Ivar详细信息 (包括property) 30 | @property(nonatomic, copy, readonly) NSArray *ivarListInDetail; 31 | 32 | /// 获取所有Property和Ivar详细信息 33 | @property(nonatomic, copy, readonly) NSArray *allListInDetail; 34 | 35 | 36 | ///将所有property的值清空 37 | - (void)cleanAllProperyValue; 38 | 39 | ///将所有ivar的值清空 40 | - (void)cleanAllIvarValue; 41 | 42 | /// 获取属性property类型, 任意类型 43 | - (PropertyType)getPropertyTypeWithName:(NSString *)propertyName; 44 | 45 | @end 46 | 47 | NS_ASSUME_NONNULL_END 48 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UIViewController+Common.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+Common.h 3 | // iOS_Template_Objc 4 | // 5 | // Created by DV on 2018/1/10. 6 | // Copyright © 2018年 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface UIViewController (Common) 14 | 15 | #pragma mark - <-- Property --> 16 | /** 导航栏是否隐藏 */ 17 | @property(nonatomic, assign) BOOL isHiddenNavBar; 18 | 19 | /** 导航栏透明度 */ 20 | @property(nonatomic, assign) CGFloat navBarAlpha; 21 | 22 | 23 | #pragma mark - <-- Method --> 24 | + (instancetype)viewControlWithStoryBoard; 25 | 26 | + (instancetype)storyBoardWithName:(NSString *)storyBoardName identifier:(NSString *)identifier; 27 | 28 | - (void)presentViewControllerWithStoryBoard:(NSString *)storyBoardName 29 | identifier:(NSString *)identifier 30 | animated:(BOOL)flag 31 | completion:(void (^ __nullable)(void))completion; 32 | 33 | - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated; 34 | 35 | - (void)pushViewControllerWithClassName:(NSString *)className animated:(BOOL)animated; 36 | 37 | - (void)popViewControllerAnimated:(BOOL)animated; 38 | 39 | - (void)setTabBarItemWithTitle:(NSString *)title 40 | fontSize:(CGFloat)fontSize 41 | image:(UIImage *)image; 42 | 43 | @end 44 | 45 | NS_ASSUME_NONNULL_END 46 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Utils/Runtime/DVRuntime.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVRuntime.h 3 | // French 4 | // 5 | // Created by DV on 2019/8/12. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DVRuntime : NSObject 14 | 15 | #pragma mark - <-- Class --> 16 | + (Class)newSubClassWithName:(NSString *)subClassName base:(Class)baseClass; 17 | 18 | + (void)deleteClass:(Class)aClass; 19 | 20 | + (void)deleteClassWithName:(NSString *)className; 21 | 22 | 23 | #pragma mark - <-- Method --> 24 | + (const char *)getMethodTypeWithProtocol:(Protocol *)protocol 25 | selector:(SEL)selector 26 | isRequired:(BOOL)isRequiredMethod 27 | isInstanceMethod:(BOOL)isInstanceMethod; 28 | 29 | + (const char *)getMethodTypeWithClass:(Class)aClass 30 | selector:(SEL)selector 31 | isInstanceMethod:(BOOL)isInstanceMethod; 32 | 33 | + (void)exchangeInstanceMethodWithOriginalClass:(Class)oClass 34 | originalSel:(SEL)originalSelector 35 | swizzledClass:(Class)sClass 36 | swizzledSel:(SEL)swizzledSelector; 37 | 38 | + (SEL)convertGetSelFromSetSel:(SEL)setSel; 39 | 40 | + (NSString *)convertGetNameFromSetName:(NSString *)setName; 41 | 42 | #pragma mark - <-- Var --> 43 | 44 | 45 | @end 46 | 47 | NS_ASSUME_NONNULL_END 48 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UIView+Common.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Common.h 3 | // iOS_Template_Objc 4 | // 5 | // Created by DV on 2018/1/10. 6 | // Copyright © 2018年 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIView (Common) 12 | 13 | #pragma mark - <-- Frame --> 14 | @property(nonatomic, assign, readonly) CGFloat x; 15 | @property(nonatomic, assign, readonly) CGFloat y; 16 | 17 | @property(nonatomic, assign, readonly) CGFloat width; 18 | @property(nonatomic, assign, readonly) CGFloat height; 19 | 20 | @property(nonatomic, assign, readonly) CGFloat minX; 21 | @property(nonatomic, assign, readonly) CGFloat midX; 22 | @property(nonatomic, assign, readonly) CGFloat maxX; 23 | 24 | @property(nonatomic, assign, readonly) CGFloat minY; 25 | @property(nonatomic, assign, readonly) CGFloat midY; 26 | @property(nonatomic, assign, readonly) CGFloat maxY; 27 | 28 | @property(nonatomic, assign, readonly) CGPoint origin; 29 | @property(nonatomic, assign, readonly) CGSize size; 30 | 31 | @property(nonatomic, assign) BOOL isDisplay; 32 | 33 | @property(nonatomic, assign, readonly) CGRect lastFrame; 34 | 35 | 36 | #pragma mark - <-- Common --> 37 | ///截图 38 | @property(nonatomic, strong, readonly) UIImage *screenShotImage; 39 | 40 | + (instancetype)viewWithNib; 41 | 42 | ///显示边框 43 | - (void)showBorder; 44 | 45 | - (void)showAllSubViewBorder; 46 | 47 | - (void)addShadow:(UIColor *)shadowColor frame:(CGRect)frame; 48 | 49 | - (void)updateSubViewLayout:(NSArray<__kindof UIView *> *)subViews margin:(CGFloat)margin; 50 | 51 | - (void)layoutIfNeededForSafeArea; 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UISegmented 例子/ViewController/SegmentedViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SegmentedViewController.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "SegmentedViewController.h" 10 | #import "SegmentedView.h" 11 | #import "SegmentedModel.h" 12 | 13 | @interface SegmentedViewController () 14 | 15 | @property(nonatomic, strong) SegmentedView *segView; 16 | @property(nonatomic, strong) SegmentedModel *segModel; 17 | 18 | @end 19 | 20 | @implementation SegmentedViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | [self initViews]; 25 | [self initModels]; 26 | [self bindData]; 27 | } 28 | 29 | #pragma mark - <-- Init --> 30 | - (void)initViews { 31 | self.segView = (SegmentedView *)self.view; 32 | } 33 | 34 | - (void)initModels { 35 | self.segModel = [[SegmentedModel alloc] init]; 36 | } 37 | 38 | - (void)bindData { 39 | 40 | DVDataBind 41 | ._inout(self.segModel, @"index") 42 | ._inout_ui(self.segView.segmented, @"selectedSegmentIndex", UIControlEventValueChanged) 43 | ._inout_ui(self.segView.stepper, @"value", UIControlEventValueChanged); 44 | 45 | 46 | [self.segView.btnChangeIndex addTarget:self 47 | action:@selector(onClickForChangeIndex:) 48 | forControlEvents:UIControlEventTouchUpInside]; 49 | } 50 | 51 | 52 | #pragma mark - <-- Response --> 53 | - (void)onClickForChangeIndex:(UIButton *)sender { 54 | self.segModel.index = 3; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UIColor+BaseColor.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+BaseColor.m 3 | // MM 4 | // 5 | // Created by DV on 2019/8/30. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import "UIColor+BaseColor.h" 10 | 11 | @implementation UIColor (BaseColor) 12 | 13 | #pragma mark - <-- 基础色 --> 14 | + (UIColor *)Blue { 15 | return [UIColor colorWithHex:0x3489FF]; 16 | } 17 | 18 | + (UIColor *)Blue1 { 19 | return [UIColor colorWithHex:0x90C3FF]; 20 | } 21 | 22 | + (UIColor *)Blue2 { 23 | return [UIColor colorWithHex:0xE8F2FF]; 24 | } 25 | 26 | 27 | + (UIColor *)Green { 28 | return [UIColor colorWithHex:0x58BA2D]; 29 | } 30 | 31 | + (UIColor *)Green1 { 32 | return [UIColor colorWithHex:0xDAF1CF]; 33 | } 34 | 35 | + (UIColor *)Green2 { 36 | return [UIColor colorWithHex:0xEDF8E6]; 37 | } 38 | 39 | 40 | + (UIColor *)Orange { 41 | return [UIColor colorWithHex:0xDE912F]; 42 | } 43 | 44 | + (UIColor *)Orange1 { 45 | return [UIColor colorWithHex:0xF8E8CF]; 46 | } 47 | 48 | + (UIColor *)Orange2 { 49 | return [UIColor colorWithHex:0xFCF4E7]; 50 | } 51 | 52 | 53 | + (UIColor *)Red { 54 | return [UIColor colorWithHex:0xF05459]; 55 | } 56 | 57 | + (UIColor *)Red1 { 58 | return [UIColor colorWithHex:0xFCDADB]; 59 | } 60 | 61 | + (UIColor *)Red2 { 62 | return [UIColor colorWithHex:0xFDECEC]; 63 | } 64 | 65 | 66 | + (UIColor *)Gray { 67 | return [UIColor colorWithHex:0x7E8087]; 68 | } 69 | 70 | + (UIColor *)Gray1 { 71 | return [UIColor colorWithHex:0xE4E3E6]; 72 | } 73 | 74 | + (UIColor *)Gray2 { 75 | return [UIColor colorWithHex:0xF1F1F2]; 76 | } 77 | 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/MainViewController/ViewController/MainViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // MainViewController.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/16. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "MainViewController.h" 10 | #import "MainTableView.h" 11 | #import "MainViewModel.h" 12 | 13 | @interface MainViewController () 14 | 15 | @property(nonatomic, strong) MainTableView *mainView; 16 | 17 | @property(nonatomic, strong) MainViewModel *mainViewModel; 18 | 19 | @end 20 | 21 | @implementation MainViewController 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | 26 | 27 | [self initViews]; 28 | [self initModels]; 29 | [self loadData]; 30 | } 31 | 32 | #pragma mark - <-- Init --> 33 | - (void)initViews { 34 | self.mainView = ({ 35 | MainTableView *v; 36 | v = [[MainTableView alloc] initWithFrame:DVFrame.frame_not_nav]; 37 | v.mtvDelegate = self; 38 | v; 39 | }); 40 | 41 | [self.view addSubview:self.mainView]; 42 | } 43 | 44 | - (void)initModels { 45 | self.mainViewModel = [[MainViewModel alloc] init]; 46 | } 47 | 48 | - (void)loadData { 49 | self.mainView.models = self.mainViewModel.tableItems; 50 | } 51 | 52 | 53 | #pragma mark - <-- Delegate --> 54 | - (void)MainTableView:(MainTableView *)view didSelectItem:(NSString *)item { 55 | Class class = NSClassFromString(item); 56 | 57 | if (!class) return; 58 | 59 | __kindof UIViewController *vc = [[class alloc] init]; 60 | [self.navigationController pushViewController:vc animated:YES]; 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/普通例子/ViewController/DemoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoViewController.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/18. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "DemoViewController.h" 10 | #import "DemoView.h" 11 | #import "DemoModel.h" 12 | 13 | @interface DemoViewController () 14 | 15 | @property(nonatomic, strong) DemoView *demoView; 16 | @property(nonatomic, strong) DemoModel *demoModel; 17 | 18 | @end 19 | 20 | @implementation DemoViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | [self initViews]; 26 | [self initModels]; 27 | [self bindData]; 28 | } 29 | 30 | #pragma mark - <-- Init --> 31 | - (void)initViews { 32 | self.demoView = (DemoView *)self.view; 33 | } 34 | 35 | - (void)initModels { 36 | self.demoModel = [[DemoModel alloc] init]; 37 | } 38 | 39 | - (void)bindData { 40 | 41 | __weak __typeof(self)weakSelf = self; 42 | 43 | DVDataBind 44 | ._inout(self.demoModel, @"text") 45 | ._inout_ui(self.demoView.textField, @"text", UIControlEventEditingChanged) 46 | ._out(self.demoView.label, @"text") 47 | ._out_key_any(@"com.text", ^(NSString *text) { 48 | NSString *pText = weakSelf.demoModel.text; 49 | NSLog(@"demoModel 最新值为 %@", pText); 50 | }); 51 | 52 | [self.demoView.button addTarget:self 53 | action:@selector(onClickForButton:) 54 | forControlEvents:UIControlEventTouchUpInside]; 55 | } 56 | 57 | 58 | #pragma mark - <-- Response --> 59 | - (void)onClickForButton:(UIButton *)sender { 60 | self.demoModel.text = @"Hello World"; 61 | } 62 | 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit/Category/NSNumber+DataBind.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSNumber+DataBind.m 3 | // 4 | // Created by David.Shi on 2018/3/16. 5 | // Copyright © 2018 DVKit. All rights reserved. 6 | // 7 | 8 | #import "NSNumber+DataBind.h" 9 | 10 | @implementation NSNumber (DataBind) 11 | 12 | - (NSNumber *)db_covertToNumberForType:(DBPropertyType)type { 13 | NSNumber *num = @(0); 14 | 15 | if (type == DBPropertyType_NSInteger) { 16 | num = [NSNumber numberWithInteger:self.integerValue]; 17 | } else if (type == DBPropertyType_NSUInteger) { 18 | num = [NSNumber numberWithUnsignedInteger:self.unsignedIntegerValue]; 19 | } else if (type == DBPropertyType_Int) { 20 | num = [NSNumber numberWithInt:self.intValue]; 21 | } else if (type == DBPropertyType_UInt) { 22 | num = [NSNumber numberWithUnsignedInt:self.unsignedIntValue]; 23 | } else if (type == DBPropertyType_Float) { 24 | num = [NSNumber numberWithFloat:self.floatValue]; 25 | } else if (type == DBPropertyType_Double) { 26 | num = [NSNumber numberWithDouble:self.doubleValue]; 27 | } else if (type == DBPropertyType_Bool) { 28 | num = [NSNumber numberWithBool:self.boolValue]; 29 | } else if (type == DBPropertyType_Char) { 30 | num = [NSNumber numberWithChar:self.charValue]; 31 | } else if (type == DBPropertyType_UChar) { 32 | num = [NSNumber numberWithUnsignedChar:self.unsignedCharValue]; 33 | } else if (type == DBPropertyType_Short) { 34 | num = [NSNumber numberWithShort:self.shortValue]; 35 | } else if (type == DBPropertyType_UShort) { 36 | num = [NSNumber numberWithUnsignedShort:self.unsignedShortValue]; 37 | } 38 | 39 | return num; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UIColor+Common.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+Common.h 3 | // iOS_Template_Objc 4 | // 5 | // Created by DV on 2018/1/9. 6 | // Copyright © 2018年 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIColor (Common) 12 | 13 | #pragma mark - <-- Property --> 14 | /// UIColor 颜色调至暗点 15 | @property(nonatomic, strong, readonly) UIColor *darkColor; 16 | 17 | /// UIColor 随机颜色 18 | @property(nonatomic, class, readonly) UIColor *randomColor; 19 | 20 | /// UIColor 转换为 RGB 21 | @property(nonatomic, strong, readonly) NSArray *RGB; 22 | 23 | 24 | #pragma mark - <-- Instance --> 25 | /** 26 | * RGB 转换为 UIColor 27 | * @param rgba @[@(r),@(g),@(b),@(alpha)] 28 | * r g b 类型:float 取值范围:[0,255] 29 | * alpha 类型:float 取值范围:[0,1] 可选写 30 | * 举例: [UIColor colorWithRGB: @[@(1),@(2),@(3),@(0.4)]]; 31 | */ 32 | + (instancetype)colorWithRGBA:(NSArray *)rgba; 33 | 34 | /** 35 | * 16进制 转为 UIColor 36 | * @param hex 16进制 0x000000 37 | * @return UIColor 38 | */ 39 | + (instancetype)colorWithHex:(UInt32)hex; 40 | 41 | /** 42 | * 16进制 转换为 UIColor 43 | * @param hex 16进制 0x000000 44 | * @param opacity 透明度 45 | * @return UIColor 46 | */ 47 | + (instancetype)colorWithHex:(UInt32)hex alpha:(float)opacity; 48 | 49 | /** 50 | * 16进制颜色(html颜色值)字符串 转为 UIColor 51 | * @param hexString 16进制字符串 @"0x000000" @"#000000" 52 | * @return UIColor 53 | */ 54 | + (instancetype)colorWithHexString:(NSString *)hexString; 55 | 56 | /** 57 | * 16进制颜色(html颜色值)字符串 转为 UIColor 58 | * @param hexString 16进制字符串 @"0x000000" @"#000000" 59 | * @param opacity 透明度 60 | * @return UIColor 61 | */ 62 | + (instancetype)colorWithHexString:(NSString *)hexString alpha:(float)opacity; 63 | 64 | 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Project/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 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UIImageView 例子/ViewController/ImageViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageViewController.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "ImageViewController.h" 10 | #import "ImageView.h" 11 | #import "ImageModel.h" 12 | 13 | @interface ImageViewController () 14 | 15 | @property(nonatomic, strong) ImageView *imageView; 16 | @property(nonatomic, strong) ImageModel *imageModel; 17 | 18 | @end 19 | 20 | @implementation ImageViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | [self initViews]; 26 | [self initModels]; 27 | [self bindData]; 28 | } 29 | 30 | #pragma mark - <-- Init --> 31 | - (void)initViews { 32 | self.imageView = (ImageView *)self.view; 33 | } 34 | 35 | - (void)initModels { 36 | self.imageModel = [[ImageModel alloc] init]; 37 | } 38 | 39 | - (void)bindData { 40 | 41 | DVDataBind 42 | ._inout(self.imageView.imageView, @"image") 43 | ._inout(self.imageModel, @"image"); 44 | 45 | 46 | 47 | [self.imageView.btnChangeImage addTarget:self 48 | action:@selector(onClickForChangeImage:) 49 | forControlEvents:UIControlEventTouchUpInside]; 50 | [self.imageView.btnChangeNil addTarget:self 51 | action:@selector(onClickForChangeNil:) 52 | forControlEvents:UIControlEventTouchUpInside]; 53 | } 54 | 55 | 56 | #pragma mark - <-- Response --> 57 | - (void)onClickForChangeImage:(UIButton *)sender { 58 | self.imageModel.image = [UIImage imageNamed:@"icon-dog.jpg"]; 59 | } 60 | 61 | - (void)onClickForChangeNil:(UIButton *)sender { 62 | self.imageModel.image = nil; 63 | } 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UITextField+Common.m: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // UITextField+DV.m 4 | // 5 | // 6 | // Created by DV on 2018/2/9. 7 | // Copyright © 2018年 iOS. All rights reserved. 8 | // 9 | 10 | #import "UITextField+Common.h" 11 | 12 | @implementation UITextField (Common) 13 | 14 | #pragma mark - <-- Property --> 15 | - (BOOL)isHiddenKeyBoardByReturnKeyDone { 16 | return [self targetForAction:@selector(handleKeyboardHiddenEvent:) withSender:self] != nil; 17 | } 18 | 19 | - (void)setIsHiddenKeyBoardByReturnKeyDone:(BOOL)isHiddenKeyBoardByReturnKeyDone { 20 | if (isHiddenKeyBoardByReturnKeyDone == YES) { 21 | self.returnKeyType = UIReturnKeyDone; 22 | [self addTarget:self action:@selector(handleKeyboardHiddenEvent:) forControlEvents:UIControlEventEditingDidEndOnExit]; 23 | } else { 24 | self.returnKeyType = UIReturnKeyDefault; 25 | [self removeTarget:self action:@selector(handleKeyboardHiddenEvent:) forControlEvents:UIControlEventEditingDidEndOnExit]; 26 | } 27 | } 28 | 29 | - (void)handleKeyboardHiddenEvent:(id)sender { 30 | [self resignFirstResponder]; 31 | } 32 | 33 | 34 | #pragma mark - <-- Method --> 35 | - (void)addLeftView:(UIView *)view { 36 | UIView *leftView = self.leftView != nil ? self.leftView : [[UIView alloc] init]; 37 | 38 | if (self.leftView != nil) { 39 | view.frame = CGRectMake(leftView.width, 0, view.width, self.height); 40 | leftView.frame = CGRectMake(0, 0, leftView.width+view.width, self.height); 41 | } else { 42 | view.frame = CGRectMake(0, 0, view.width, self.height); 43 | leftView.frame = CGRectMake(0, 0, view.width, self.height); 44 | } 45 | 46 | [leftView addSubview:view]; 47 | self.leftView = leftView; 48 | self.leftViewMode = UITextFieldViewModeAlways; 49 | } 50 | 51 | 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UISlider 例子/ViewController/SliderViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SliderViewController.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "SliderViewController.h" 10 | #import "SliderView.h" 11 | #import "SliderModel.h" 12 | 13 | @interface SliderViewController () 14 | 15 | @property(nonatomic, strong) SliderView *sliderView; 16 | @property(nonatomic, strong) SliderModel *sliderModel; 17 | 18 | @end 19 | 20 | @implementation SliderViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | [self initViews]; 26 | [self initModels]; 27 | [self bindData]; 28 | [self loadData]; 29 | } 30 | 31 | #pragma mark - <-- Init --> 32 | - (void)initViews { 33 | self.sliderView = (SliderView *)self.view; 34 | } 35 | 36 | - (void)initModels { 37 | self.sliderModel = [[SliderModel alloc] init]; 38 | } 39 | 40 | - (void)bindData { 41 | 42 | DVDataBind 43 | ._inout(self.sliderModel, @"sliderValue") 44 | ._out(self.sliderView.lblTitle, @"text") 45 | ._inout_ui(self.sliderView.slider, @"value", UIControlEventValueChanged) 46 | ._out_cv(self.sliderView.progressView, @"progress", ^NSNumber *(NSNumber *value) { 47 | float tempValue = [value floatValue]; 48 | tempValue = tempValue / 100.f; 49 | return @(tempValue); 50 | }); 51 | 52 | 53 | [self.sliderView.btnChangeValue addTarget:self 54 | action:@selector(onClickForChangeValue:) 55 | forControlEvents:UIControlEventTouchUpInside]; 56 | } 57 | 58 | - (void)loadData { 59 | self.sliderModel.sliderValue = 20; 60 | } 61 | 62 | #pragma mark - <-- Response --> 63 | - (void)onClickForChangeValue:(UIButton *)sender { 64 | self.sliderModel.sliderValue = 50; 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UICollectionView+Common.m: -------------------------------------------------------------------------------- 1 | // 2 | // UICollectionView+Common.m 3 | // French 4 | // 5 | // Created by DV on 2019/3/12. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import "UICollectionView+Common.h" 10 | #import 11 | 12 | 13 | @implementation UICollectionView (Common) 14 | 15 | 16 | #pragma mark - <-- Method --> 17 | - (UICollectionViewCell *)dequeueReusableCellWithClass:(Class)cellClass forIndexPath:(NSIndexPath *)indexPath { 18 | UICollectionViewCell * cell = [self dequeueReusableCellWithReuseIdentifier:NSStringFromClass(cellClass) 19 | forIndexPath:indexPath]; 20 | return cell ? cell : [[cellClass alloc] init]; 21 | } 22 | 23 | - (UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)elementKind withClass:(Class)viewClass forIndexPath:(NSIndexPath *)indexPath { 24 | UICollectionReusableView *view = [self dequeueReusableSupplementaryViewOfKind:elementKind 25 | withReuseIdentifier:NSStringFromClass(viewClass) 26 | forIndexPath:indexPath]; 27 | return view ? view : [[viewClass alloc] init]; 28 | } 29 | 30 | - (void)registerClass:(Class)cellClass { 31 | [self registerClass:cellClass forCellWithReuseIdentifier:NSStringFromClass(cellClass)]; 32 | } 33 | 34 | - (void)registerClassForSectionHeader:(Class)viewClass { 35 | [self registerClass:viewClass forSupplementaryViewOfKind:UICollectionElementKindSectionHeader 36 | withReuseIdentifier:NSStringFromClass(viewClass)]; 37 | } 38 | 39 | - (void)registerClassForSectionFooter:(Class)viewClass { 40 | [self registerClass:viewClass forSupplementaryViewOfKind:UICollectionElementKindSectionFooter 41 | withReuseIdentifier:NSStringFromClass(viewClass)]; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit/Define/DVDataBindDefine.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVDataBindDefine.h 3 | // 4 | // Created by David.Shi on 2018/3/16. 5 | // Copyright © 2018 DVKit. All rights reserved. 6 | // 7 | 8 | #ifndef DVDataBindDefine_h 9 | #define DVDataBindDefine_h 10 | 11 | #ifndef DV_DATABIND_TYPE 12 | #define DV_DATABIND_TYPE 13 | typedef NS_OPTIONS(NSUInteger, DVDataBindType) { 14 | DVDataBindType_IN = 0x001, 15 | DVDataBindType_OUT = 0x010, 16 | DVDataBindType_IN_OUT = 0x011, 17 | DVDataBindType_IN_NOT = 0x101, 18 | DVDataBindType_OUT_NOT = 0x110, 19 | DVDataBindType_IN_OUT_NOT = 0x111, 20 | 21 | DVDataBindType_NOT = 0x100, 22 | }; 23 | #endif 24 | 25 | 26 | typedef NS_ENUM(NSUInteger, DVDataBindObserverModelType) { 27 | DVDataBindObserverModelType_Object, 28 | DVDataBindObserverModelType_UI, 29 | DVDataBindObserverModelType_Array, 30 | }; 31 | 32 | 33 | #ifndef DBPROPERTY_TYPE 34 | #define DBPROPERTY_TYPE 35 | typedef NS_ENUM(NSUInteger, DBPropertyType) { 36 | DBPropertyType_NSObject = 0x1000, 37 | DBPropertyType_NSString = 0x2000, 38 | DBPropertyType_NSArray = 0x3000, 39 | DBPropertyType_NSDictionary = 0x4000, 40 | DBPropertyType_NSSet = 0x5000, 41 | 42 | DBPropertyType_NSNumber = 0x5000, 43 | DBPropertyType_Int = 0x5001, 44 | DBPropertyType_UInt = 0x5002, 45 | DBPropertyType_Short = 0x5003, 46 | DBPropertyType_UShort = 0x5004, 47 | DBPropertyType_NSInteger = 0x5005, 48 | DBPropertyType_NSUInteger = 0x5006, 49 | DBPropertyType_Char = 0x5007, 50 | DBPropertyType_UChar = 0x5008, 51 | DBPropertyType_Chars = 0x5009, 52 | DBPropertyType_Float = 0x5010, 53 | DBPropertyType_Double = 0x5011, 54 | DBPropertyType_Bool = 0x5012, 55 | 56 | DBPropertyType_Void = 0x6000, 57 | DBPropertyType_Class = 0x7000, 58 | DBPropertyType_Sel = 0x8000, 59 | }; 60 | #endif 61 | 62 | #endif /* DVDataBindDefine_h */ 63 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Project/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 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/MVVM实现登录界面 例子/View/LoginView.m: -------------------------------------------------------------------------------- 1 | // 2 | // LoginView.m 3 | // DVDataBindDemo 4 | // 5 | // Created by 施达威 on 2020/3/18. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "LoginView.h" 10 | 11 | @implementation LoginView 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | 16 | [self.userNameText setNeedsLayout]; 17 | [self.passwordText setNeedsLayout]; 18 | 19 | 20 | UIView *userNameLeftView = ({ 21 | UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)]; 22 | UIImageView *image = [[UIImageView alloc] initWithFrame:CGRectMake(8, 8, 24, 24)]; 23 | image.image = [UIImage imageNamed:@"user.png"]; 24 | [v addSubview:image]; 25 | v; 26 | }); 27 | 28 | UIView *passwordLeftView = ({ 29 | UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)]; 30 | UIImageView *image = [[UIImageView alloc] initWithFrame:CGRectMake(8, 8, 24, 24)]; 31 | image.image = [UIImage imageNamed:@"password.png"]; 32 | [v addSubview:image]; 33 | v; 34 | }); 35 | 36 | 37 | self.userNameText.textColor = [UIColor Gray]; 38 | self.userNameText.clearButtonMode = UITextFieldViewModeWhileEditing; 39 | self.userNameText.leftView = userNameLeftView; 40 | self.userNameText.leftViewMode = UITextFieldViewModeAlways; 41 | 42 | self.passwordText.textColor = [UIColor Gray]; 43 | self.passwordText.clearButtonMode = UITextFieldViewModeWhileEditing; 44 | self.passwordText.leftView = passwordLeftView; 45 | self.passwordText.leftViewMode = UITextFieldViewModeAlways; 46 | self.passwordText.secureTextEntry = YES; 47 | 48 | self.btnLogin.enabled = NO; 49 | self.btnLogin.layer.cornerRadius = 8; 50 | self.btnLogin.clipsToBounds = YES; 51 | self.btnLogin.titleColor = [UIColor Blue]; 52 | self.btnLogin.backgroundImage = [UIImage imageWithColor:[UIColor whiteColor]]; 53 | self.btnLogin.backgroundImageForHighlighted = [UIImage imageWithColor:[UIColor darkGrayColor]]; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Utils/Frame/DVFrame.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVFrame.h 3 | // 4 | // 5 | // Created by DV on 2018/2/10. 6 | // Copyright © 2018年 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #define CGSizeOne CGSizeMake(1, 1) 12 | 13 | @interface DVFrame : NSObject 14 | 15 | @property(nonatomic, class, readonly) CGFloat width; 16 | @property(nonatomic, class, readonly) CGFloat height; 17 | @property(nonatomic, class, readonly) CGFloat height_not_nav; 18 | 19 | @property(nonatomic, class, readonly) CGFloat statusBarHeight; 20 | @property(nonatomic, class, readonly) CGFloat navBarHeight; 21 | @property(nonatomic, class, readonly) CGFloat tabBarHeight; 22 | 23 | @property(nonatomic, class, readonly) CGRect bounds; 24 | @property(nonatomic, class, readonly) CGRect frame; 25 | @property(nonatomic, class, readonly) CGRect frame_full; 26 | @property(nonatomic, class, readonly) CGRect frame_not_nav; 27 | 28 | @property(nonatomic, class, readonly) CGFloat switchWidth; 29 | @property(nonatomic, class, readonly) CGFloat switchHeight; 30 | 31 | @property(nonatomic, class, readonly) CGRect celllFrameTop; 32 | @property(nonatomic, class, readonly) CGRect celllFrame1; 33 | @property(nonatomic, class, readonly) CGRect celllFrame2; 34 | @property(nonatomic, class, readonly) CGRect celllFrame3; 35 | @property(nonatomic, class, readonly) CGRect celllFrame4; 36 | @property(nonatomic, class, readonly) CGRect celllFrame5; 37 | @property(nonatomic, class, readonly) CGRect celllFrame6; 38 | @property(nonatomic, class, readonly) CGRect celllFrame7; 39 | @property(nonatomic, class, readonly) CGRect celllFrame8; 40 | @property(nonatomic, class, readonly) CGRect celllFrame9; 41 | 42 | @property(nonatomic, class, readonly) CGRect celllFrame12; 43 | @property(nonatomic, class, readonly) CGRect celllFrame23; 44 | @property(nonatomic, class, readonly) CGRect celllFrame34; 45 | @property(nonatomic, class, readonly) CGRect celllFrame45; 46 | @property(nonatomic, class, readonly) CGRect celllFrame56; 47 | @property(nonatomic, class, readonly) CGRect celllFrame67; 48 | @property(nonatomic, class, readonly) CGRect celllFrame78; 49 | @property(nonatomic, class, readonly) CGRect celllFrame89; 50 | 51 | + (CGRect)cellFrameWithOffset:(CGFloat)offset count:(CGFloat)count; 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UISwitch 例子/ViewController/SwitchViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SwitchViewController.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "SwitchViewController.h" 10 | #import "SwitchView.h" 11 | #import "SwitchModel.h" 12 | 13 | @interface SwitchViewController () 14 | 15 | @property(nonatomic, strong) SwitchView *swView; 16 | @property(nonatomic, strong) SwitchModel *swModel; 17 | 18 | @end 19 | 20 | @implementation SwitchViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | [self initViews]; 26 | [self initModels]; 27 | [self bindData]; 28 | } 29 | 30 | #pragma mark - <-- Init --> 31 | - (void)initViews { 32 | self.swView = (SwitchView *)self.view; 33 | } 34 | 35 | - (void)initModels { 36 | self.swModel = [[SwitchModel alloc] init]; 37 | } 38 | 39 | - (void)bindData { 40 | __weak __typeof(self)weakSelf = self; 41 | 42 | DVDataBind 43 | ._inout(self.swModel, @"isON") 44 | ._in_ui(self.swView.inSW1, @"on", UIControlEventValueChanged) 45 | ._in_ui(self.swView.inSW2, @"on", UIControlEventValueChanged) 46 | ._in_ui(self.swView.inSW3, @"on", UIControlEventValueChanged) 47 | ._inout_ui(self.swView.inoutSW1, @"on", UIControlEventValueChanged) 48 | ._inout_ui(self.swView.inoutSW2, @"on", UIControlEventValueChanged) 49 | ._inout_ui(self.swView.inoutSW3, @"on", UIControlEventValueChanged) 50 | ._out(self.swView.outSW1, @"on") 51 | ._out(self.swView.outSW2, @"on") 52 | ._out(self.swView.outSW3, @"on") 53 | ._out_not(self.swView.notSW, @"on") 54 | ._inout_ui(self.swView.textField, @"text", UIControlEventEditingChanged) 55 | ._out(self.swView.btnChangeEnable , @"enabled") 56 | ._out_key_any(@"自定义名", ^{ 57 | BOOL isON = weakSelf.swModel.isON; 58 | // 可断点查看 model的isON 是否同步改变 59 | NSLog(@"[SwitchViewController LOG]: swModel -> isON 为 %@", isON ? @"YES" : @"NO"); 60 | }); 61 | 62 | 63 | DVDataBind 64 | ._in_ui(self.swView.btnChangeIsON, @"highlighted", UIControlEventTouchUpInside) 65 | ._out_key_any(@"自定义", ^{ 66 | weakSelf.swModel.isON = !weakSelf.swModel.isON; //model绑定了UI,直接改变model的数据会自动更新UI 67 | }); 68 | } 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Project/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | zh_CN 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | $(MARKETING_VERSION) 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | LSRequiresIPhoneOS 22 | 23 | NSAppTransportSecurity 24 | 25 | NSAllowsArbitraryLoads 26 | 27 | 28 | NSBluetoothPeripheralUsageDescription 29 | Please allow Bluetooth to connect to the device 30 | NSCameraUsageDescription 31 | 32 | NSLocationAlwaysAndWhenInUseUsageDescription 33 | 34 | NSMicrophoneUsageDescription 35 | 36 | NSPhotoLibraryUsageDescription 37 | 38 | NSSiriUsageDescription 39 | 请允许使用Siri 40 | UIFileSharingEnabled 41 | 42 | UILaunchStoryboardName 43 | Launch Screen 44 | UIRequiredDeviceCapabilities 45 | 46 | armv7 47 | 48 | UISupportedInterfaceOrientations 49 | 50 | UIInterfaceOrientationPortrait 51 | 52 | UISupportedInterfaceOrientations~ipad 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationPortraitUpsideDown 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | UIUserInterfaceStyle 60 | Light 61 | UIViewControllerBasedStatusBarAppearance 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit/Model/DVDataBindObserverModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVDataBindObserverModel.h 3 | // 4 | // Created by David.Shi on 2018/3/16. 5 | // Copyright © 2018 iOS. All rights reserved. 6 | // 7 | 8 | #import 9 | #import "DVDataBindDefine.h" 10 | #import "DVDataBind.h" 11 | 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | 16 | @interface DVDataBindObserverModel : NSObject { 17 | @public 18 | void *_Nullable _context; 19 | } 20 | 21 | #pragma mark - <-- Property --> 22 | @property(nonatomic, weak) id observer; 23 | @property(nonatomic, weak) id target; 24 | @property(nonatomic, copy) NSString *keyPath; 25 | @property(nonatomic, copy, nullable) DBAnyAnyBlock convertBlock; 26 | @property(nonatomic, copy) NSString *targetHash; 27 | @property(nonatomic, weak) id oldValue; 28 | @property(nonatomic, copy) NSString *oldString; 29 | //@property(nonatomic, assign) id oldValueForObject; 30 | @property(nonatomic, assign) DVDataBindType dbType; 31 | @property(nonatomic, assign) DVDataBindObserverModelType modelType; 32 | @property(nonatomic, assign) DBPropertyType propertyType; 33 | 34 | //UI 35 | @property(nonatomic, assign) SEL selector; 36 | @property(nonatomic, assign) UIControlEvents ctrlEvent; 37 | 38 | //Array 39 | @property(nonatomic, assign) NSUInteger index; 40 | 41 | 42 | #pragma mark - <-- Instance --> 43 | - (instancetype)initWithObserver:(id)observer 44 | target:(id)target 45 | keyPath:(NSString *)keyPath 46 | context:(nullable void *)context 47 | convertBlock:(nullable DBAnyAnyBlock)convertBlock 48 | databindType:(DVDataBindType)dbType; 49 | 50 | - (instancetype)initWithObserver:(id)observer 51 | target:(id)target 52 | keyPath:(NSString *)keyPath 53 | selector:(nullable SEL)selector 54 | controlEvent:(UIControlEvents)ctrlEvent 55 | convertBlock:(nullable DBAnyAnyBlock)convertBlock 56 | databindType:(DVDataBindType)dbType; 57 | 58 | - (instancetype)initWithObserver:(id)observer 59 | target:(id)target 60 | keyPath:(NSString *)keyPath 61 | index:(NSUInteger)index 62 | convertBlock:(nullable DBAnyAnyBlock)convertBlock 63 | databindType:(DVDataBindType)dbType; 64 | 65 | @end 66 | 67 | NS_ASSUME_NONNULL_END 68 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/MVVM实现登录界面 例子/ViewController/LoginViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LoginViewController.m 3 | // DVDataBindDemo 4 | // 5 | // Created by 施达威 on 2020/3/18. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "LoginViewController.h" 10 | #import "LoginView.h" 11 | #import "LoginViewModel.h" 12 | 13 | @interface LoginViewController () 14 | 15 | @property(nonatomic, strong) LoginView *loginView; 16 | @property(nonatomic, strong) LoginViewModel *loginViewModel; 17 | 18 | @end 19 | 20 | 21 | @implementation LoginViewController 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | 26 | [self initViews]; 27 | [self initViewModels]; 28 | [self bindViewModel]; 29 | } 30 | 31 | #pragma mark - <-- Init --> 32 | - (void)initViews { 33 | self.loginView = (LoginView *)self.view; 34 | self.loginView.backgroundColor = [UIColor Blue]; 35 | } 36 | 37 | - (void)initViewModels { 38 | self.loginViewModel = [[LoginViewModel alloc] init]; 39 | } 40 | 41 | - (void)bindViewModel { 42 | __weak __typeof(self)weakSelf = self; 43 | 44 | // 这里 View 跟 ViewModel 双向绑定 45 | DVDataBind 46 | ._in_ui(self.loginView.userNameText, @"text", UIControlEventEditingChanged) 47 | ._out(self.loginViewModel, @"userName") 48 | ._filter(^BOOL(NSString *text) { 49 | //这里判断用户名是否符合规范、校验、限制等等操作,return YES 数据才能更新 50 | return [weakSelf.loginViewModel filterUserName:text]; 51 | }) 52 | ._out_key_any(@"login.userName.text", ^{ 53 | weakSelf.loginView.btnLogin.enabled = [weakSelf.loginViewModel btnLoginEnable]; 54 | }); 55 | 56 | 57 | DVDataBind 58 | ._in_ui(self.loginView.passwordText, @"text", UIControlEventEditingChanged) 59 | ._out_cv(self.loginViewModel, @"password", ^(NSString *text){ 60 | // textField.secureTextEntry = YES时, text为密文, 需要转换 61 | return [NSString stringWithUTF8String:text.UTF8String]; 62 | }) 63 | ._filter(^BOOL(NSString *text) { 64 | NSString *tempText = [NSString stringWithUTF8String:text.UTF8String]; 65 | return [weakSelf.loginViewModel filterPassword:tempText]; 66 | }) 67 | ._out_key_any(@"login.passwordText.text", ^{ 68 | weakSelf.loginView.btnLogin.enabled = [weakSelf.loginViewModel btnLoginEnable]; 69 | }); 70 | 71 | 72 | DVDataBind 73 | ._in_ui(self.loginView.btnLogin, @"highlighted", UIControlEventTouchUpInside) 74 | ._out_key_any(@"login.btnLogin.login", ^{ 75 | [weakSelf.loginViewModel login]; 76 | }); 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/MainViewController/View/MainTableView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MainTableView.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/16. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "MainTableView.h" 10 | 11 | @interface MainTableView () 12 | 13 | @property(nonatomic, strong) NSArray *keys; 14 | 15 | @end 16 | 17 | 18 | @implementation MainTableView 19 | 20 | #pragma mark - <-- Initializer --> 21 | - (instancetype)initWithFrame:(CGRect)frame { 22 | self = [super initWithFrame:frame]; 23 | if (self) { 24 | [self initViews]; 25 | } 26 | return self; 27 | } 28 | 29 | - (void)dealloc{ 30 | self.delegate = nil; 31 | self.dataSource = nil; 32 | 33 | _models = nil; 34 | _mtvDelegate = nil; 35 | } 36 | 37 | 38 | #pragma mark - <-- Property --> 39 | - (void)setModels:(NSDictionary *)models { 40 | _models = models; 41 | _keys = models.allKeys; 42 | [self reloadData]; 43 | } 44 | 45 | 46 | #pragma mark - <-- Init --> 47 | - (void)initViews { 48 | self.delegate = self; 49 | self.dataSource = self; 50 | [self registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"]; 51 | } 52 | 53 | 54 | #pragma mark - Delegate 55 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ 56 | return 1; 57 | } 58 | 59 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 60 | return self.keys ? self.keys.count : 0; 61 | } 62 | 63 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 64 | 65 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath]; 66 | 67 | if (cell && self.keys && indexPath.row < self.keys.count) { 68 | cell.textLabel.text = self.keys[indexPath.row]; 69 | } 70 | 71 | return cell; 72 | } 73 | 74 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 75 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 76 | 77 | if (self.mtvDelegate && self.keys && indexPath.row < self.keys.count) { 78 | NSString *key = self.keys[indexPath.row]; 79 | NSString *value = self.models[key]; 80 | [self.mtvDelegate MainTableView:self didSelectItem:value]; 81 | } 82 | } 83 | 84 | - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{ 85 | return [UIView new]; 86 | } 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Utils/Runtime/Model/DVRuntimeObjectModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVRuntimeObjectModel.h 3 | // French 4 | // 5 | // Created by DV on 2019/8/12. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | #pragma mark - <-------------------- Define --------------------> 14 | /** 15 | ———————————————— 16 | |Code Meaning | 17 | ———————————————— 18 | c A char 19 | i An int 20 | s A short 21 | l A long // l is treated as a 32-bit quantity on 64-bit programs. 22 | q A long long 23 | C An unsigned char 24 | I An unsigned int 25 | S An unsigned short 26 | L An unsigned long 27 | Q An unsigned long long 28 | f A float 29 | d A double 30 | B A C++ bool or a C99 _Bool 31 | v A void 32 | * A character string (char *) 33 | @ An object (whether statically typed or typed id) 34 | # A class object (Class) 35 | : A method selector (SEL) 36 | [array type] An array 37 | {name=type...} A structure 38 | (name=type...) A union 39 | bnum A bit field of num bits 40 | ^type A pointer to type 41 | ? An unknown type (among other things, this code is used for function pointers) 42 | 43 | */ 44 | #pragma mark - Todo 45 | #ifndef PROPERTY_TYPE 46 | #define PROPERTY_TYPE 47 | typedef NS_ENUM(NSUInteger, PropertyType) { 48 | PropertyType_NSObject, 49 | PropertyType_NSNumber, 50 | PropertyType_NSString, 51 | PropertyType_NSArray, 52 | PropertyType_NSDictionary, 53 | PropertyType_NSSet, 54 | 55 | PropertyType_Void, 56 | PropertyType_Id, 57 | PropertyType_Class, 58 | PropertyType_Sel, 59 | 60 | PropertyType_Int, 61 | PropertyType_UInt, 62 | PropertyType_Short, 63 | PropertyType_UShort, 64 | PropertyType_Long, 65 | PropertyType_ULong, 66 | PropertyType_LongLong, 67 | PropertyType_ULongLong, 68 | PropertyType_NSInteger, 69 | PropertyType_NSUInteger, 70 | PropertyType_Char, 71 | PropertyType_UChar, 72 | PropertyType_Chars, 73 | PropertyType_Float, 74 | PropertyType_Double, 75 | PropertyType_Bool, 76 | }; 77 | #endif 78 | 79 | 80 | #pragma mark - <-------------------- Class --------------------> 81 | @interface DVRuntimeObjectModel : NSObject 82 | 83 | @property(nonatomic, copy) NSString *name; 84 | @property(nonatomic, strong) id value; 85 | @property(nonatomic, assign) PropertyType type; 86 | @property(nonatomic, copy) NSString *className; 87 | 88 | @end 89 | 90 | NS_ASSUME_NONNULL_END 91 | -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit/Category/NSString+DataBind.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+DataBind.m 3 | // 4 | // Created by David.Shi on 2018/3/16. 5 | // Copyright © 2018 DVKit. All rights reserved. 6 | // 7 | 8 | #import "NSString+DataBind.h" 9 | 10 | @implementation NSString (DataBind) 11 | 12 | - (unsigned int)db_unsignedIntValue { 13 | uint value = self.intValue; 14 | 15 | if (value == INT_MAX) { 16 | NSString *s1 = [self substringToIndex:5]; 17 | NSString *s2 = [self substringFromIndex:5]; 18 | int v1 = s1.intValue; 19 | int v2 = s2.intValue; 20 | value = v1 * 10e5 + v2; 21 | } 22 | 23 | return value; 24 | } 25 | 26 | - (unsigned long long)db_unsignedLongLongValue { 27 | unsigned long long value = self.longLongValue; 28 | 29 | if (value == LONG_LONG_MAX) { 30 | NSString *s1 = [self substringToIndex:10]; 31 | NSString *s2 = [self substringFromIndex:10]; 32 | unsigned long long v1 = s1.longLongValue; 33 | unsigned long long v2 = s2.longLongValue; 34 | value = v1 * 10e10 + v2; 35 | } 36 | 37 | return value; 38 | } 39 | 40 | - (NSNumber *)db_covertToNumberForType:(DBPropertyType)type { 41 | NSNumber *num = @(0); 42 | 43 | if (type == DBPropertyType_NSInteger) { 44 | num = [NSNumber numberWithInteger:self.integerValue]; 45 | } else if (type == DBPropertyType_NSUInteger) { 46 | num = [NSNumber numberWithUnsignedLongLong:self.db_unsignedLongLongValue]; 47 | } else if (type == DBPropertyType_Int) { 48 | num = [NSNumber numberWithInt:self.intValue]; 49 | } else if (type == DBPropertyType_UInt) { 50 | num = [NSNumber numberWithUnsignedInt:self.db_unsignedIntValue]; 51 | } else if (type == DBPropertyType_Float) { 52 | num = [NSNumber numberWithFloat:self.floatValue]; 53 | } else if (type == DBPropertyType_Double) { 54 | num = [NSNumber numberWithDouble:self.doubleValue]; 55 | } else if (type == DBPropertyType_Bool) { 56 | num = [NSNumber numberWithBool:self.length > 0]; 57 | } else if (type == DBPropertyType_Char) { 58 | num = [NSNumber numberWithChar:(char)self.integerValue]; 59 | } else if (type == DBPropertyType_UChar) { 60 | num = [NSNumber numberWithUnsignedChar:(unsigned char)self.integerValue]; 61 | } else if (type == DBPropertyType_Short) { 62 | num = [NSNumber numberWithShort:(short)self.integerValue]; 63 | } else if (type == DBPropertyType_UShort) { 64 | num = [NSNumber numberWithUnsignedShort:(unsigned short)self.integerValue]; 65 | } 66 | 67 | return num; 68 | } 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/数组 例子/ViewController/ArrayViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ArrayViewController.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "ArrayViewController.h" 10 | #import "ArrayView.h" 11 | #import "ArrayModel.h" 12 | 13 | 14 | @interface ArrayViewController () 15 | 16 | @property(nonatomic, strong) ArrayView *arrayView; 17 | @property(nonatomic, strong) ArrayModel *arrayModel; 18 | 19 | @end 20 | 21 | @implementation ArrayViewController 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | [self initViews]; 26 | [self initModels]; 27 | [self bindData]; 28 | } 29 | 30 | #pragma mark - <-- Init --> 31 | - (void)initViews { 32 | self.arrayView = (ArrayView *)self.view; 33 | } 34 | 35 | - (void)initModels { 36 | self.arrayModel = [[ArrayModel alloc] init]; 37 | [self.arrayModel.array addObject:@""]; 38 | [self.arrayModel.array addObject:@(0)]; 39 | } 40 | 41 | - (void)bindData { 42 | __weak __typeof(self)weakSelf = self; 43 | 44 | DVDataBind 45 | ._inout_ui(self.arrayView.textField1, @"text", UIControlEventEditingChanged) 46 | ._inout_arr(self.arrayModel, @"array", 0) 47 | ._out_key_any(@"com.array.0", ^{ 48 | NSString *text = weakSelf.arrayModel.array[0]; 49 | NSLog(@"[ArrayViewController LOG]: array第0位 -> %@",text); 50 | }); 51 | 52 | DVDataBind 53 | ._inout_ui(self.arrayView.textField2, @"text", UIControlEventEditingChanged) 54 | ._inout_arr(self.arrayModel, @"array", 1) 55 | ._out_key_any(@"com.array.1", ^ { 56 | NSNumber *value = weakSelf.arrayModel.array[1]; 57 | NSString *text = [value stringValue]; 58 | NSLog(@"[ArrayViewController LOG]: array第1位 -> %@",text); 59 | }); 60 | 61 | 62 | [self.arrayView.btnChange1 addTarget:self 63 | action:@selector(onClickForChange1:) 64 | forControlEvents:UIControlEventTouchUpInside]; 65 | [self.arrayView.btnChange2 addTarget:self 66 | action:@selector(onClickForChange2:) 67 | forControlEvents:UIControlEventTouchUpInside]; 68 | } 69 | 70 | 71 | #pragma mark - <-- Response --> 72 | - (void)onClickForChange1:(UIButton *)sender { 73 | NSMutableArray *array = [self.arrayModel mutableArrayValueForKey:@"array"]; 74 | array[0] = @"Hello World"; 75 | } 76 | 77 | - (void)onClickForChange2:(UIButton *)sender { 78 | NSMutableArray *array = [self.arrayModel mutableArrayValueForKey:@"array"]; 79 | array[1] = @(123456); 80 | } 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UITextField 例子/ViewController/TextFieldViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TextFieldViewController.m 3 | // DVDataBindDemo 4 | // 5 | // Created by mlgPro on 2020/3/17. 6 | // Copyright © 2020 DVUntilKit. All rights reserved. 7 | // 8 | 9 | #import "TextFieldViewController.h" 10 | #import "TextFieldView.h" 11 | #import "TextFieldModel.h" 12 | 13 | @interface TextFieldViewController () 14 | 15 | @property(nonatomic, strong) TextFieldView *textView; 16 | @property(nonatomic, strong) TextFieldModel *textModel; 17 | 18 | @end 19 | 20 | @implementation TextFieldViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | [self initViews]; 25 | [self initModels]; 26 | [self bindData]; 27 | } 28 | 29 | #pragma mark - <-- Init --> 30 | - (void)initViews { 31 | self.textView = (TextFieldView *)self.view; 32 | } 33 | 34 | - (void)initModels { 35 | self.textModel = [[TextFieldModel alloc] init]; 36 | } 37 | 38 | - (void)bindData { 39 | __weak __typeof(self)weakSelf = self; 40 | 41 | DVDataBind 42 | ._inout(self.textModel, @"num") 43 | ._inout(self.textModel, @"text") 44 | ._out(self.textView.lblNormal, @"text") 45 | ._out_cv(self.textView.lblConvert, @"text", ^NSString *(NSString *text) { 46 | NSString *tempText = [NSString stringWithFormat:@"AAA - %@ - BBB",text]; 47 | return tempText; 48 | }) 49 | ._inout_ui(self.textView.textField1, @"text", UIControlEventEditingChanged) 50 | ._inout_ui(self.textView.textField2, @"text", UIControlEventEditingChanged) 51 | ._filter(^BOOL(id value) { // 返回YES 则正常数据更新 52 | if ([value isKindOfClass:[NSString class]]) { 53 | NSString *text = (NSString *)value; 54 | return text.length <= 20; 55 | } 56 | return YES; 57 | }) 58 | ._out_key_any(@"自定义名", ^{ 59 | int num = weakSelf.textModel.num; 60 | NSString *text = weakSelf.textModel.text; 61 | // 可断点查看 model的属性 是否同步改变 62 | NSLog(@"[TextFieldViewController LOG]: textModel -> num 为 %d", num); 63 | NSLog(@"[TextFieldViewController LOG]: textModel -> text 为 %@", text); 64 | }); 65 | 66 | 67 | 68 | [self.textView.btnChangeNum addTarget:self 69 | action:@selector(onClickForChangeNum:) 70 | forControlEvents:UIControlEventTouchUpInside]; 71 | [self.textView.btnChangeText addTarget:self 72 | action:@selector(onClickForChangeText:) 73 | forControlEvents:UIControlEventTouchUpInside]; 74 | } 75 | 76 | 77 | #pragma mark - <-- Response --> 78 | - (void)onClickForChangeNum:(UIButton *)sender { 79 | self.textModel.num = 123456; 80 | } 81 | 82 | - (void)onClickForChangeText:(UIButton *)sender { 83 | self.textModel.text = @"Hello World"; 84 | } 85 | 86 | 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit/Core/DVDataBindObserver.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVDataBindObserver.h 3 | // iOS_Test 4 | // 5 | // Created by DV on 2018/8/9. 6 | // Copyright © 2018 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "DVDataBindDefine.h" 11 | #import "DVDataBind.h" 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface DVDataBindObserver : NSObject 16 | 17 | #pragma mark - <-- Property --> 18 | @property(nonatomic, copy, readonly) NSString *chainCode; 19 | @property(nonatomic, assign, readonly) NSUInteger bindCount; 20 | 21 | 22 | #pragma mark - <-- Method --> 23 | - (instancetype)initWithChainCode:(NSString *)chainCode; 24 | 25 | 26 | #pragma mark - <-- 判断包含 --> 27 | - (BOOL)isContainTarget:(id)target; 28 | - (BOOL)isContainTarget:(id)target keyPath:(NSString *)keyPath; 29 | - (BOOL)isContainTarget:(id)target keyPath:(NSString *)keyPath controlEvent:(UIControlEvents)ctrlEvent; 30 | - (BOOL)isContainTarget:(id)target keyPath:(NSString *)keyPath index:(NSUInteger)index; 31 | - (BOOL)isContainTarget:(id)target keyPath:(NSString *)keyPath outBlockKey:(NSString *)key; 32 | 33 | - (BOOL)isContainTargetHash:(NSString *)targetHash; 34 | - (BOOL)isContainTargetHash:(NSString *)targetHash keyPath:(NSString *)keyPath; 35 | - (BOOL)isContainTargetHash:(NSString *)targetHash keyPath:(NSString *)keyPath controlEvent:(UIControlEvents)ctrlEvent; 36 | - (BOOL)isContainTargetHash:(NSString *)targetHash keyPath:(NSString *)keyPath index:(NSUInteger)index; 37 | - (BOOL)isContainTargetHash:(NSString *)targetHash keyPath:(NSString *)keyPath outBlockKey:(NSString *)key; 38 | 39 | 40 | #pragma mark - <-- 绑定 --> 41 | - (void)bindWithTarget:(id)target 42 | keyPath:(NSString *)keyPath 43 | convertBlock:(nullable DBAnyAnyBlock)convertBlock 44 | dataBindType:(DVDataBindType)dbType; 45 | 46 | - (void)bindWithTarget:(id)target 47 | keyPath:(NSString *)keyPath 48 | controlEvent:(UIControlEvents)ctrlEvent 49 | convertBlock:(nullable DBAnyAnyBlock)convertBlock 50 | dataBindType:(DVDataBindType)dbType; 51 | 52 | - (void)bindWithTarget:(id)target 53 | keyPath:(NSString *)keyPath 54 | index:(NSUInteger)index 55 | convertBlock:(nullable DBAnyAnyBlock)convertBlock 56 | dataBindType:(DVDataBindType)dbType; 57 | 58 | - (void)bindWithOutBlock:(DBVoidAnyBlock)outBlock 59 | key:(NSString *)key; 60 | 61 | - (void)bindWithFilterBlock:(DBBoolAnyBlock)filterBlock; 62 | 63 | 64 | #pragma mark - <-- 解绑 --> 65 | - (void)unbindWithTarget:(id)target; 66 | - (void)unbindWithTarget:(id)target keyPath:(NSString *)keyPath; 67 | - (void)unbindWithOutBlockKey:(NSString *)key; 68 | 69 | - (void)unbindWithTargetHash:(NSString *)targetHash; 70 | - (void)unbindWithTargetHash:(NSString *)targetHash keyPath:(NSString *)keyPath; 71 | 72 | @end 73 | 74 | NS_ASSUME_NONNULL_END 75 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UIButton+Common.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+Common.m 3 | // iOS_Template_Objc 4 | // 5 | // Created by DV on 2018/1/9. 6 | // Copyright © 2018年 iOS. All rights reserved. 7 | // 8 | 9 | #import "UIButton+Common.h" 10 | 11 | @implementation UIButton (Common) 12 | 13 | 14 | #pragma mark - <-- Property --> 15 | - (NSString *)title { 16 | return [self titleForState:UIControlStateNormal]; 17 | } 18 | 19 | - (void)setTitle:(NSString *)title { 20 | [self setTitle:title forState:UIControlStateNormal]; 21 | } 22 | 23 | - (NSString *)titleForHighlighted { 24 | return [self titleForState:UIControlStateHighlighted]; 25 | } 26 | 27 | - (void)setTitleForHighlighted:(NSString *)titleForHighlighted { 28 | [self setTitle:titleForHighlighted forState:UIControlStateHighlighted]; 29 | } 30 | 31 | 32 | - (UIColor *)titleColor { 33 | return [self titleColorForState:UIControlStateNormal]; 34 | } 35 | 36 | - (void)setTitleColor:(UIColor *)titleColor { 37 | [self setTitleColor:titleColor forState:UIControlStateNormal]; 38 | } 39 | 40 | - (UIColor *)titleColorForHighlighted { 41 | return [self titleColorForState:UIControlStateHighlighted]; 42 | } 43 | 44 | - (void)setTitleColorForHighlighted:(UIColor *)titleColorForHighlighted { 45 | [self setTitleColor:titleColorForHighlighted forState:UIControlStateHighlighted]; 46 | } 47 | 48 | - (UIImage *)image { 49 | return [self imageForState:UIControlStateNormal]; 50 | } 51 | 52 | - (void)setImage:(UIImage *)image { 53 | [self setImage:image forState:UIControlStateNormal]; 54 | } 55 | 56 | - (UIImage *)imageForHighlighted { 57 | return [self imageForState:UIControlStateHighlighted]; 58 | } 59 | 60 | - (void)setImageForHighlighted:(UIImage *)imageForHighlighted { 61 | [self setImage:imageForHighlighted forState:UIControlStateHighlighted]; 62 | } 63 | 64 | - (UIImage *)imageForSelected { 65 | return [self imageForState:UIControlStateSelected]; 66 | } 67 | 68 | - (void)setImageForSelected:(UIImage *)imageForSelected { 69 | [self setImage:imageForSelected forState:UIControlStateSelected]; 70 | } 71 | 72 | - (UIImage *)backgroundImage { 73 | return [self backgroundImageForState:UIControlStateNormal]; 74 | } 75 | 76 | - (void)setBackgroundImage:(UIImage *)backgroundImage { 77 | [self setBackgroundImage:backgroundImage forState:UIControlStateNormal]; 78 | } 79 | 80 | - (UIImage *)backgroundImageForHighlighted { 81 | return [self backgroundImageForState:UIControlStateHighlighted]; 82 | } 83 | 84 | - (void)setBackgroundImageForHighlighted:(UIImage *)backgroundImageForHighlighted { 85 | [self setBackgroundImage:backgroundImageForHighlighted forState:UIControlStateHighlighted]; 86 | } 87 | 88 | 89 | #pragma mark - <-- Method --> 90 | - (void)constraintToFit { 91 | if (@available(iOS 11, *)) { 92 | [[self.widthAnchor constraintEqualToConstant:self.bounds.size.width] setActive:YES]; 93 | [[self.widthAnchor constraintEqualToConstant:self.bounds.size.height] setActive:YES]; 94 | } 95 | } 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo.xcodeproj/xcshareddata/xcschemes/DVDataBindDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UILabel+Common.m: -------------------------------------------------------------------------------- 1 | // 2 | // UILabel+DV.m 3 | // 4 | // 5 | // Created by 施达威 on 2018/2/8. 6 | // Copyright © 2018年 iOS. All rights reserved. 7 | // 8 | 9 | #import "UILabel+Common.h" 10 | 11 | @implementation UILabel (Common) 12 | 13 | - (CGFloat)fontSize { 14 | return [self.font pointSize]; 15 | } 16 | 17 | - (void)setFontSize:(CGFloat)fontSize { 18 | self.font = [self.font fontWithSize:fontSize]; 19 | } 20 | 21 | - (void)wordSpaceToFitWidth:(CGFloat)width { 22 | if (self.text.length <= 1) { 23 | return; 24 | } 25 | 26 | UILabel *lblTmp = [[UILabel alloc] init]; 27 | lblTmp.text = self.text; 28 | lblTmp.font = self.font; 29 | [lblTmp sizeToFit]; 30 | 31 | 32 | float wordSpace = (float)(width - CGRectGetWidth(lblTmp.frame)) / (float)(self.text.length - 1); 33 | [self changeWordSpace:wordSpace]; 34 | } 35 | 36 | - (CGFloat)heightFromFitWidth:(CGFloat)width { 37 | UILabel *lblTmp = [[UILabel alloc] init]; 38 | lblTmp.text = self.text; 39 | lblTmp.font = self.font; 40 | [lblTmp sizeToFit]; 41 | 42 | CGFloat lblMaxW = lblTmp.frame.size.width; 43 | CGFloat lblMaxH = lblTmp.frame.size.height; 44 | return ceilf(lblMaxW/width) * lblMaxH; 45 | } 46 | 47 | - (void)changeLineSpace:(float)space { 48 | NSString *labelText = self.text; 49 | NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:labelText]; 50 | NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; 51 | [paragraphStyle setLineSpacing:space]; 52 | [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [labelText length])]; 53 | self.attributedText = attributedString; 54 | // [label sizeToFit]; 55 | } 56 | 57 | - (void)changeWordSpace:(float)space { 58 | NSString *labelText = self.text; 59 | NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:labelText attributes:@{NSKernAttributeName:@(space)}]; 60 | NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; 61 | [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [labelText length])]; 62 | self.attributedText = attributedString; 63 | // [label sizeToFit]; 64 | } 65 | 66 | - (void)changeLineSpace:(float)lineSpace wordSpace:(float)wordSpace { 67 | NSString *labelText = self.text; 68 | NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:labelText attributes:@{NSKernAttributeName:@(wordSpace)}]; 69 | NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; 70 | [paragraphStyle setLineSpacing:lineSpace]; 71 | [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [labelText length])]; 72 | self.attributedText = attributedString; 73 | // [label sizeToFit]; 74 | } 75 | 76 | - (void)addUnderLineWithString:(NSString *)string { 77 | NSDictionary *attr = @{NSUnderlineStyleAttributeName:@(1)}; 78 | NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:string attributes:attr]; 79 | self.attributedText = attrStr; 80 | } 81 | 82 | @end 83 | 84 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/AppDelegate/AppDelegate+UISetting.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate+UISetting.m 3 | // 4 | // Created by David.Shi on 2018/1/27. 5 | // Copyright © 2018年 iOS. All rights reserved. 6 | // 7 | 8 | #import "AppDelegate+UISetting.h" 9 | 10 | @implementation AppDelegate (UISetting) 11 | 12 | #pragma mark - <-- Method --> 13 | - (void)UISetting { 14 | 15 | //Bar 16 | [self setAppStatusBar]; 17 | [self setNavigationBar]; 18 | [self setTabBar]; 19 | 20 | //Control 21 | [self setButton]; 22 | [self setTextField]; 23 | 24 | //View 25 | [self setTableView]; 26 | } 27 | 28 | 29 | #pragma mark - <-- Bar --> 30 | - (void)setAppStatusBar { 31 | UIApplication *application = [UIApplication sharedApplication]; 32 | 33 | //状态栏风格 34 | application.statusBarStyle = UIStatusBarStyleLightContent; 35 | //状态栏是否隐藏 36 | // application.statusBarHidden = NO; 37 | } 38 | 39 | - (void)setNavigationBar { 40 | UINavigationBar *naviBar = [UINavigationBar appearance]; 41 | 42 | ///导航栏背景色 43 | [naviBar setBarTintColor: [UIColor blackColor]]; 44 | 45 | ///导航栏标题文字颜色 46 | [naviBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}]; 47 | 48 | ///导航栏左右项文字颜色 49 | [naviBar setTintColor:[UIColor whiteColor]]; 50 | 51 | ///导航栏风格 52 | [naviBar setBarStyle:UIBarStyleDefault]; 53 | 54 | ///导航栏是否为半透明 NO为不透明 55 | // naviBar.translucent = YES; 56 | 57 | } 58 | 59 | - (void)setTabBar { 60 | UITabBar *tabBar = [UITabBar appearance]; 61 | 62 | //TabBar背景色 63 | // [tabBar setBarTintColor:[UIColor whiteColor]]; 64 | 65 | //TabBar选项颜色 66 | // [tabBar setTintColor:DVColor.theme]; 67 | 68 | //TabBar风格 69 | // [tabBar setBarStyle:UIBarStyleDefault]; 70 | 71 | //TabBar是否半透明 NO为不透明 72 | // tabBar.translucent = NO; 73 | 74 | 75 | UITabBarItem *tabBarItem = [UITabBarItem appearance]; 76 | 77 | NSDictionary *normalAttri = @{ 78 | // NSFontAttributeName:[UIFont labelFontSize], //字体 79 | NSForegroundColorAttributeName:[UIColor grayColor], //字体颜色 80 | }; 81 | 82 | NSDictionary *selectedAttri = @{ 83 | // NSFontAttributeName:[UIFont labelFontSize], //字体 84 | NSForegroundColorAttributeName:[UIColor darkGrayColor], //字体颜色 85 | }; 86 | 87 | [tabBarItem setTitleTextAttributes:normalAttri forState:(UIControlStateNormal)]; 88 | [tabBarItem setTitleTextAttributes:selectedAttri forState:(UIControlStateSelected)]; 89 | } 90 | 91 | 92 | #pragma mark - <-- Control --> 93 | - (void)setButton { 94 | UIButton *btn = [UIButton appearance]; 95 | 96 | ///同时只能允许一个button点击 97 | [btn setExclusiveTouch:YES]; 98 | } 99 | 100 | - (void)setTextField { 101 | UITextField *txtField = [UITextField appearance]; 102 | 103 | //设置 点击输入键盘的done,自动隐藏 104 | txtField.isHiddenKeyBoardByReturnKeyDone = YES; 105 | } 106 | 107 | 108 | #pragma mark - <-- View --> 109 | - (void)setTableView { 110 | UITableView *tableView = [UITableView appearance]; 111 | 112 | 113 | 114 | 115 | UITableViewCell *cell = [UITableViewCell appearance]; 116 | 117 | 118 | 119 | 120 | } 121 | 122 | 123 | 124 | @end 125 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UITabBarController+Common.m: -------------------------------------------------------------------------------- 1 | // 2 | // UITabBarController+Common.m 3 | // French 4 | // 5 | // Created by DV on 2019/3/29. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import "UITabBarController+Common.h" 10 | #import 11 | 12 | @implementation UITabBarController (Common) 13 | 14 | static char kAssociatedObjectKey_dataSource; 15 | 16 | #pragma mark - <-- Property --> 17 | - (id)dataSource { 18 | return ((id(^)(void))objc_getAssociatedObject(self, &kAssociatedObjectKey_dataSource))(); 19 | } 20 | 21 | - (void)setDataSource:(id)dataSource { 22 | __weak __typeof(dataSource)weakDataSource = dataSource; 23 | id(^Block)(void) = ^{ 24 | return weakDataSource; 25 | }; 26 | 27 | objc_setAssociatedObject(self, &kAssociatedObjectKey_dataSource, Block, OBJC_ASSOCIATION_COPY_NONATOMIC); 28 | 29 | if (dataSource != nil) { 30 | [self reload]; 31 | } 32 | } 33 | 34 | 35 | #pragma mark - <-- Method --> 36 | - (void)reload{ 37 | id weakDataSource = self.dataSource; 38 | if (weakDataSource!= nil) { 39 | NSUInteger count = weakDataSource.numberOfTabItems; 40 | NSMutableArray* viewCtrls = [NSMutableArray array]; 41 | for (NSUInteger i = 0; i *)viewControllers { 49 | if ([self.viewControllers count] > 0) { 50 | self.viewControllers = nil; 51 | } 52 | self.viewControllers = viewControllers; 53 | } 54 | 55 | 56 | - (void)insertTabItem:(UIViewController *)viewController atIndex:(NSInteger)index{ 57 | NSMutableArray*viewCtrls = [NSMutableArray arrayWithArray:self.viewControllers]; 58 | [viewCtrls insertObject:viewController atIndex:index]; 59 | self.viewControllers = viewCtrls; 60 | } 61 | 62 | - (void)insertTabItemAtFirst:(UIViewController *)viewController{ 63 | NSMutableArray*viewCtrls = [NSMutableArray arrayWithArray:self.viewControllers]; 64 | [viewCtrls insertObject:viewController atIndex:0]; 65 | self.viewControllers = viewCtrls; 66 | } 67 | 68 | - (void)insertTabItemAtLast:(UIViewController *)viewController { 69 | NSMutableArray*viewCtrls = [NSMutableArray arrayWithArray:self.viewControllers]; 70 | [viewCtrls addObject:viewController]; 71 | self.viewControllers = viewCtrls; 72 | } 73 | 74 | - (void)removeAllTabItems { 75 | self.viewControllers = nil; 76 | } 77 | 78 | - (void)removeTabItem:(NSInteger)index { 79 | NSMutableArray*viewCtrls = [NSMutableArray arrayWithArray:self.viewControllers]; 80 | [viewCtrls removeObjectAtIndex:index]; 81 | self.viewControllers = viewCtrls; 82 | } 83 | 84 | - (void)removeFirstTabItem { 85 | NSMutableArray*viewCtrls = [NSMutableArray arrayWithArray:self.viewControllers]; 86 | [viewCtrls removeObjectAtIndex:0]; 87 | self.viewControllers = viewCtrls; 88 | } 89 | 90 | - (void)removeLastTabItem { 91 | NSMutableArray*viewCtrls = [NSMutableArray arrayWithArray:self.viewControllers]; 92 | [viewCtrls removeLastObject]; 93 | self.viewControllers = viewCtrls; 94 | } 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit/Core/DVDataBindObserverManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVDataBindObserverManager.h 3 | // 4 | // Created by David.Shi on 2018/3/16. 5 | // Copyright © 2018 iOS. All rights reserved. 6 | // 7 | 8 | #import 9 | #import "DVDataBindDefine.h" 10 | #import "DVDataBind.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface DVDataBindObserverManager : NSObject 15 | 16 | + (instancetype)sharedInstance; 17 | 18 | 19 | #pragma mark - <-- 查询绑定情况 --> 20 | - (BOOL)queryBindStatusForTarget:(id)target 21 | keyPath:(NSString *)keyPath; 22 | - (BOOL)queryBindStatusForTarget:(id)target 23 | keyPath:(NSString *)keyPath 24 | controlEvent:(UIControlEvents)ctrlEvent; 25 | - (BOOL)queryBindStatusForTarget:(id)target 26 | keyPath:(NSString *)keyPath 27 | index:(NSUInteger)index; 28 | 29 | 30 | #pragma mark - <-- 获取链码 --> 31 | - (NSString *)getChainCodeForTarget:(id)target 32 | keyPath:(NSString *)keyPath; 33 | - (NSString *)getChainCodeForTarget:(id)target 34 | keyPath:(NSString *)keyPath 35 | controlEvent:(UIControlEvents)ctrlEvent; 36 | - (NSString *)getChainCodeForTarget:(id)target 37 | keyPath:(NSString *)keyPath 38 | index:(NSUInteger)index; 39 | 40 | 41 | #pragma mark - <-- 绑定 --> 42 | - (void)bindWithTarget:(id)target 43 | keyPath:(NSString *)keyPath 44 | convertBlock:(nullable DBAnyAnyBlock)convertBlock 45 | dataBindType:(DVDataBindType)dbType 46 | chainCode:(NSString *)chainCode; 47 | 48 | - (void)bindWithTarget:(id)target 49 | keyPath:(NSString *)keyPath 50 | controlEvent:(UIControlEvents)ctrlEvent 51 | convertBlock:(nullable DBAnyAnyBlock)convertBlock 52 | dataBindType:(DVDataBindType)dbType 53 | chainCode:(NSString *)chainCode; 54 | 55 | - (void)bindWithTarget:(id)target 56 | keyPath:(NSString *)keyPath 57 | index:(NSUInteger)index 58 | convertBlock:(nullable DBAnyAnyBlock)convertBlock 59 | dataBindType:(DVDataBindType)dbType 60 | chainCode:(NSString *)chainCode; 61 | 62 | - (void)bindWithOutBlock:(DBVoidAnyBlock)outBlock 63 | key:(NSString *)key 64 | chainCode:(NSString *)chainCode; 65 | 66 | - (void)bindWithFilterBlock:(DBBoolAnyBlock)filterBlock 67 | chainCode:(NSString *)chainCode; 68 | 69 | 70 | #pragma mark - <-- 解绑 --> 71 | - (void)unbindWithTarget:(id)target; 72 | - (void)unbindWithTarget:(id)target keyPath:(NSString *)keyPath; 73 | - (void)unbindWithTarget:(id)target keyPath:(NSString *)keyPath controlEvent:(UIControlEvents)ctrlEvent; 74 | - (void)unbindWithTarget:(id)target keyPath:(NSString *)keyPath index:(NSUInteger)index; 75 | - (void)unbindWithTarget:(id)target keyPath:(NSString *)keyPath outBlockKey:(NSString *)key; 76 | 77 | - (void)unbindWithTargetHash:(NSString *)targetHash; 78 | - (void)unbindWithTargetHash:(NSString *)targetHash keyPath:(NSString *)keyPath; 79 | - (void)unbindWithTargetHash:(NSString *)targetHash keyPath:(NSString *)keyPath controlEvent:(UIControlEvents)ctrlEvent; 80 | - (void)unbindWithTargetHash:(NSString *)targetHash keyPath:(NSString *)keyPath index:(NSUInteger)index; 81 | - (void)unbindWithTargetHash:(NSString *)targetHash keyPath:(NSString *)keyPath outBlockKey:(NSString *)key; 82 | 83 | @end 84 | 85 | NS_ASSUME_NONNULL_END 86 | -------------------------------------------------------------------------------- /DVDataBindKit/Products/DVDataBindKit.framework/_CodeSignature/CodeResources: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | files 6 | 7 | Headers/DVDataBind.h 8 | 9 | TEK4qMfB/8ooTNWinUaW6EGC3KU= 10 | 11 | Headers/DVDataBindKit.h 12 | 13 | uYW1O7f+DX3RfTYjKY0r6qHyz3k= 14 | 15 | Info.plist 16 | 17 | U+3uC0GVGJA5NQH1HbGfRamb5YI= 18 | 19 | Modules/module.modulemap 20 | 21 | 3de2rP9Zrtvn4ufYq2HTQroSXxg= 22 | 23 | 24 | files2 25 | 26 | Headers/DVDataBind.h 27 | 28 | hash 29 | 30 | TEK4qMfB/8ooTNWinUaW6EGC3KU= 31 | 32 | hash2 33 | 34 | md3TF2XEf2U149HCaNqN1eJuKQx+zso2qYIkfxvzlgY= 35 | 36 | 37 | Headers/DVDataBindKit.h 38 | 39 | hash 40 | 41 | uYW1O7f+DX3RfTYjKY0r6qHyz3k= 42 | 43 | hash2 44 | 45 | jxM7UN8BeXYho5hkaCP/R/bnZnJjIBh4kx42BA4/WF8= 46 | 47 | 48 | Modules/module.modulemap 49 | 50 | hash 51 | 52 | 3de2rP9Zrtvn4ufYq2HTQroSXxg= 53 | 54 | hash2 55 | 56 | LAErfOdYdv9rgbHGyYWjMJK18esfIlyhy9W7zt82/aA= 57 | 58 | 59 | 60 | rules 61 | 62 | ^.* 63 | 64 | ^.*\.lproj/ 65 | 66 | optional 67 | 68 | weight 69 | 1000 70 | 71 | ^.*\.lproj/locversion.plist$ 72 | 73 | omit 74 | 75 | weight 76 | 1100 77 | 78 | ^Base\.lproj/ 79 | 80 | weight 81 | 1010 82 | 83 | ^version.plist$ 84 | 85 | 86 | rules2 87 | 88 | .*\.dSYM($|/) 89 | 90 | weight 91 | 11 92 | 93 | ^(.*/)?\.DS_Store$ 94 | 95 | omit 96 | 97 | weight 98 | 2000 99 | 100 | ^.* 101 | 102 | ^.*\.lproj/ 103 | 104 | optional 105 | 106 | weight 107 | 1000 108 | 109 | ^.*\.lproj/locversion.plist$ 110 | 111 | omit 112 | 113 | weight 114 | 1100 115 | 116 | ^Base\.lproj/ 117 | 118 | weight 119 | 1010 120 | 121 | ^Info\.plist$ 122 | 123 | omit 124 | 125 | weight 126 | 20 127 | 128 | ^PkgInfo$ 129 | 130 | omit 131 | 132 | weight 133 | 20 134 | 135 | ^embedded\.provisionprofile$ 136 | 137 | weight 138 | 20 139 | 140 | ^version\.plist$ 141 | 142 | weight 143 | 20 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Utils/Runtime/Category/NSObject+Runtime_Method.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Runtime_Method.h 3 | // French 4 | // 5 | // Created by DV on 2019/8/12. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface NSObject (Runtime_Method) 14 | 15 | @property(nonatomic, strong, readonly) NSArray *methodList; 16 | 17 | #pragma mark - <-- 添加 实例 方法 --> 18 | - (void)addInstanceMethod:(SEL)selector i_block:(int(^)())block; 19 | 20 | - (void)addInstanceMethod:(SEL)selector I_block:(NSInteger(^)())block; 21 | 22 | - (void)addInstanceMethod:(SEL)selector f_block:(float(^)())block; 23 | 24 | - (void)addInstanceMethod:(SEL)selector d_block:(double(^)())block; 25 | 26 | - (void)addInstanceMethod:(SEL)selector b_block:(BOOL(^)())block; 27 | 28 | - (void)addInstanceMethod:(SEL)selector o_block:(id _Nullable(^)())block; 29 | 30 | - (void)addInstanceMethod:(SEL)selector v_block:(void(^)())block; 31 | 32 | 33 | 34 | #pragma mark - <-- 添加 协议 方法 --> 35 | @property(nonatomic, strong) id runtime_delegate; 36 | 37 | - (void)addDelegateMethod:(SEL)selector i_block:(int(^)())block; 38 | 39 | - (void)addDelegateMethod:(SEL)selector I_block:(NSInteger(^)())block; 40 | 41 | - (void)addDelegateMethod:(SEL)selector f_block:(float(^)())block; 42 | 43 | - (void)addDelegateMethod:(SEL)selector d_block:(double(^)())block; 44 | 45 | - (void)addDelegateMethod:(SEL)selector b_block:(BOOL(^)())block; 46 | 47 | - (void)addDelegateMethod:(SEL)selector o_block:(id _Nullable(^)())block; 48 | 49 | - (void)addDelegateMethod:(SEL)selector v_block:(void(^)())block; 50 | 51 | 52 | 53 | #pragma mark - <-- 添加 本类 公共方法 --> 54 | + (void)addPublicMethod:(SEL)selector i_block:(int(^)())block; 55 | 56 | + (void)addPublicMethod:(SEL)selector I_block:(NSInteger(^)())block; 57 | 58 | + (void)addPublicMethod:(SEL)selector f_block:(float(^)())block; 59 | 60 | + (void)addPublicMethod:(SEL)selector d_block:(double(^)())block; 61 | 62 | + (void)addPublicMethod:(SEL)selector b_block:(BOOL(^)())block; 63 | 64 | + (void)addPublicMethod:(SEL)selector o_block:(id _Nullable(^)())block; 65 | 66 | + (void)addPublicMethod:(SEL)selector v_block:(void(^)())block; 67 | 68 | 69 | 70 | #pragma mark - <-- 添加 本类 公共类方法 --> 71 | + (void)addClassMethod:(SEL)selector i_block:(int(^)())block; 72 | 73 | + (void)addClassMethod:(SEL)selector I_block:(NSInteger(^)())block; 74 | 75 | + (void)addClassMethod:(SEL)selector f_block:(float(^)())block; 76 | 77 | + (void)addClassMethod:(SEL)selector d_block:(double(^)())block; 78 | 79 | + (void)addClassMethod:(SEL)selector b_block:(BOOL(^)())block; 80 | 81 | + (void)addClassMethod:(SEL)selector o_block:(id _Nullable(^)())block; 82 | 83 | + (void)addClassMethod:(SEL)selector v_block:(void(^)())block; 84 | 85 | 86 | 87 | #pragma mark - <-- 交换实现方法--> 88 | - (void)exchangeInstanceMethodWithOriginalSel:(SEL)originalSelector 89 | swizzledSel:(SEL)swizzledSelector; 90 | 91 | + (void)exchangeInstanceMethodWithOriginalSel:(SEL)originalSelector 92 | swizzledSel:(SEL)swizzledSelector; 93 | 94 | 95 | 96 | #pragma mark - <-- 执行方法 --> 97 | /// 执行super方法 98 | - (void)performSuperSelector:(SEL)aSelector param:(id)param; 99 | - (void)performSuperSelector:(SEL)aSelector param1:(id)param1 param2:(id)param2; 100 | - (void)performSuperSelector:(SEL)aSelector param1:(id)param1 param2:(id)param2 param3:(id)param3; 101 | 102 | @end 103 | 104 | NS_ASSUME_NONNULL_END 105 | -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit/DVDataBind.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVDataBind.h 3 | // 4 | // Created by David.Shi on 2018/3/16. 5 | // Copyright © 2018 iOS. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | 13 | #pragma mark - <-------------------- Typedef --------------------> 14 | @class DVDataBind; 15 | typedef void(^DBVoidAnyBlock)(); 16 | typedef BOOL(^DBBoolAnyBlock)(); 17 | typedef id(^DBAnyAnyBlock)(); 18 | 19 | typedef DVDataBind *_Nonnull(^DataBindBlock)(id target, NSString *property); 20 | typedef DVDataBind *_Nonnull(^DataBindUIBlock)(id target, NSString *property, UIControlEvents controlEvent); 21 | typedef DVDataBind *_Nonnull(^DataBindNotBlock)(id target, NSString *property); 22 | typedef DVDataBind *_Nonnull(^DataBindUINotBlock)(id target, NSString *property, UIControlEvents controlEvent); 23 | typedef DVDataBind *_Nonnull(^DataBindConvertBlock)(id target, NSString *property, DBAnyAnyBlock block); 24 | typedef DVDataBind *_Nonnull(^DataBindUIConvertBlock)(id target, NSString *property, UIControlEvents controlEvent, DBAnyAnyBlock block); 25 | typedef DVDataBind *_Nonnull(^DataBindArrayBlock)(id target, NSString *property, NSUInteger index); 26 | typedef DVDataBind *_Nonnull(^DataBindKeyAnyOutBlock)(NSString *key, DBVoidAnyBlock block); 27 | typedef DVDataBind *_Nonnull(^DataBindFilterBlock)(DBBoolAnyBlock block); 28 | 29 | 30 | #pragma mark - <-------------------- Class --------------------> 31 | /** 32 | 数据双向绑定 33 | @code 34 | UITextField *textField; 35 | UILabel *lable; 36 | 37 | DVDataBind 38 | ._inout(self.textField, @"text", UIControlEventEditingChanged) 39 | ._inout(self.label, @"text") 40 | ._filter(^BOOL(NSString *string) { 41 | //string 处理 42 | return YES/NO; //返回YES可更新新值 43 | }) 44 | ._out_key_any(@"com.key.xxx", ^(NSString *string){ 45 | //string 处理 46 | }); 47 | @endcode 48 | */ 49 | @interface DVDataBind : NSObject 50 | 51 | 52 | #pragma mark - <-- 双向绑定 --> 53 | + (DataBindBlock)_inout; 54 | + (DataBindUIBlock)_inout_ui; 55 | + (DataBindConvertBlock)_inout_cv; 56 | + (DataBindUIConvertBlock)_inout_ui_cv; 57 | + (DataBindArrayBlock)_inout_arr; 58 | 59 | 60 | - (DataBindBlock)_inout; 61 | - (DataBindUIBlock)_inout_ui; 62 | - (DataBindConvertBlock)_inout_cv; 63 | - (DataBindUIConvertBlock)_inout_ui_cv; 64 | - (DataBindArrayBlock)_inout_arr; 65 | 66 | 67 | #pragma mark - <-- 单向绑定(数据更新,只发送新数据,不接受) --> 68 | + (DataBindBlock)_in; 69 | + (DataBindUIBlock)_in_ui; 70 | + (DataBindArrayBlock)_in_arr; 71 | 72 | 73 | - (DataBindBlock)_in; 74 | - (DataBindUIBlock)_in_ui; 75 | - (DataBindArrayBlock)_in_arr; 76 | 77 | 78 | #pragma mark - <-- 单向绑定(数据更新,只接受新数据,不发送) --> 79 | - (DataBindBlock)_out; 80 | - (DataBindConvertBlock)_out_cv; 81 | - (DataBindArrayBlock)_out_arr; 82 | - (DataBindNotBlock)_out_not; 83 | - (DataBindKeyAnyOutBlock)_out_key_any; 84 | 85 | 86 | #pragma mark - <-- 特殊额外处理绑定 --> 87 | - (DataBindFilterBlock)_filter; 88 | 89 | 90 | 91 | 92 | #pragma mark - <-- 解除绑定 --> 93 | + (void)unbindWithTarget:(id)target; 94 | + (void)unbindWithTarget:(id)target property:(NSString *)property; 95 | + (void)unbindWithTarget:(id)target property:(NSString *)property index:(NSInteger)index; 96 | + (void)unbindWithTarget:(id)target property:(NSString *)property controlEvent:(UIControlEvents)ctrlEvent; 97 | + (void)unbindWithTarget:(id)target property:(NSString *)property outBlockKey:(NSString *)key; 98 | 99 | 100 | #pragma mark - <-- 查询绑定情况 --> 101 | + (BOOL)queryBindStatusForTarget:(id)target property:(NSString *)property; 102 | + (BOOL)queryBindStatusForTarget:(id)target property:(NSString *)property index:(NSUInteger)index; 103 | + (BOOL)queryBindStatusForTarget:(id)target property:(NSString *)property controlEvent:(UIControlEvents)ctrlEvent; 104 | 105 | @end 106 | 107 | NS_ASSUME_NONNULL_END 108 | -------------------------------------------------------------------------------- /DVDataBindKit/Products/DVDataBindKit.framework/Headers/DVDataBind.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVDataBind.h 3 | // 4 | // Created by David.Shi on 2018/3/16. 5 | // Copyright © 2018 iOS. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | 13 | #pragma mark - <-------------------- Typedef --------------------> 14 | @class DVDataBind; 15 | typedef void(^DBVoidAnyBlock)(); 16 | typedef BOOL(^DBBoolAnyBlock)(); 17 | typedef id(^DBAnyAnyBlock)(); 18 | 19 | typedef DVDataBind *_Nonnull(^DataBindBlock)(id target, NSString *property); 20 | typedef DVDataBind *_Nonnull(^DataBindUIBlock)(id target, NSString *property, UIControlEvents controlEvent); 21 | typedef DVDataBind *_Nonnull(^DataBindNotBlock)(id target, NSString *property); 22 | typedef DVDataBind *_Nonnull(^DataBindUINotBlock)(id target, NSString *property, UIControlEvents controlEvent); 23 | typedef DVDataBind *_Nonnull(^DataBindConvertBlock)(id target, NSString *property, DBAnyAnyBlock block); 24 | typedef DVDataBind *_Nonnull(^DataBindUIConvertBlock)(id target, NSString *property, UIControlEvents controlEvent, DBAnyAnyBlock block); 25 | typedef DVDataBind *_Nonnull(^DataBindArrayBlock)(id target, NSString *property, NSUInteger index); 26 | typedef DVDataBind *_Nonnull(^DataBindKeyAnyOutBlock)(NSString *key, DBVoidAnyBlock block); 27 | typedef DVDataBind *_Nonnull(^DataBindFilterBlock)(DBBoolAnyBlock block); 28 | 29 | 30 | #pragma mark - <-------------------- Class --------------------> 31 | /** 32 | 数据双向绑定 33 | @code 34 | UITextField *textField; 35 | UILabel *lable; 36 | 37 | DVDataBind 38 | ._inout(self.textField, @"text", UIControlEventEditingChanged) 39 | ._inout(self.label, @"text") 40 | ._filter(^BOOL(NSString *string) { 41 | //string 处理 42 | return YES/NO; //返回YES可更新新值 43 | }) 44 | ._out_key_any(@"com.key.xxx", ^(NSString *string){ 45 | //string 处理 46 | }); 47 | @endcode 48 | */ 49 | @interface DVDataBind : NSObject 50 | 51 | 52 | #pragma mark - <-- 双向绑定 --> 53 | + (DataBindBlock)_inout; 54 | + (DataBindUIBlock)_inout_ui; 55 | + (DataBindConvertBlock)_inout_cv; 56 | + (DataBindUIConvertBlock)_inout_ui_cv; 57 | + (DataBindArrayBlock)_inout_arr; 58 | 59 | 60 | - (DataBindBlock)_inout; 61 | - (DataBindUIBlock)_inout_ui; 62 | - (DataBindConvertBlock)_inout_cv; 63 | - (DataBindUIConvertBlock)_inout_ui_cv; 64 | - (DataBindArrayBlock)_inout_arr; 65 | 66 | 67 | #pragma mark - <-- 单向绑定(数据更新,只发送新数据,不接受) --> 68 | + (DataBindBlock)_in; 69 | + (DataBindUIBlock)_in_ui; 70 | + (DataBindArrayBlock)_in_arr; 71 | 72 | 73 | - (DataBindBlock)_in; 74 | - (DataBindUIBlock)_in_ui; 75 | - (DataBindArrayBlock)_in_arr; 76 | 77 | 78 | #pragma mark - <-- 单向绑定(数据更新,只接受新数据,不发送) --> 79 | - (DataBindBlock)_out; 80 | - (DataBindConvertBlock)_out_cv; 81 | - (DataBindArrayBlock)_out_arr; 82 | - (DataBindNotBlock)_out_not; 83 | - (DataBindKeyAnyOutBlock)_out_key_any; 84 | 85 | 86 | #pragma mark - <-- 特殊额外处理绑定 --> 87 | - (DataBindFilterBlock)_filter; 88 | 89 | 90 | 91 | 92 | #pragma mark - <-- 解除绑定 --> 93 | + (void)unbindWithTarget:(id)target; 94 | + (void)unbindWithTarget:(id)target property:(NSString *)property; 95 | + (void)unbindWithTarget:(id)target property:(NSString *)property index:(NSInteger)index; 96 | + (void)unbindWithTarget:(id)target property:(NSString *)property controlEvent:(UIControlEvents)ctrlEvent; 97 | + (void)unbindWithTarget:(id)target property:(NSString *)property outBlockKey:(NSString *)key; 98 | 99 | 100 | #pragma mark - <-- 查询绑定情况 --> 101 | + (BOOL)queryBindStatusForTarget:(id)target property:(NSString *)property; 102 | + (BOOL)queryBindStatusForTarget:(id)target property:(NSString *)property index:(NSUInteger)index; 103 | + (BOOL)queryBindStatusForTarget:(id)target property:(NSString *)property controlEvent:(UIControlEvents)ctrlEvent; 104 | 105 | @end 106 | 107 | NS_ASSUME_NONNULL_END 108 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Utils/Runtime/DVRuntime.m: -------------------------------------------------------------------------------- 1 | // 2 | // DVRuntime.m 3 | // French 4 | // 5 | // Created by DV on 2019/8/12. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import "DVRuntime.h" 10 | #import 11 | 12 | @implementation DVRuntime 13 | 14 | #pragma mark - <-- Class --> 15 | + (Class)newSubClassWithName:(NSString *)subClassName base:(Class)baseClass { 16 | Class subClass = NSClassFromString(subClassName); 17 | if (!subClass) { 18 | subClass = objc_allocateClassPair(baseClass, [subClassName UTF8String], 0); 19 | objc_registerClassPair(subClass); 20 | } 21 | return subClass; 22 | } 23 | 24 | + (void)deleteClass:(Class)aClass { 25 | if (aClass) { 26 | objc_disposeClassPair(aClass); 27 | } 28 | } 29 | 30 | + (void)deleteClassWithName:(NSString *)className { 31 | Class aClass = NSClassFromString(className); 32 | if (aClass) { 33 | objc_disposeClassPair(aClass); 34 | } 35 | } 36 | 37 | 38 | #pragma mark - <-- Method --> 39 | + (const char *)getMethodTypeWithProtocol:(Protocol *)protocol 40 | selector:(SEL)selector 41 | isRequired:(BOOL)isRequiredMethod 42 | isInstanceMethod:(BOOL)isInstanceMethod { 43 | struct objc_method_description description = protocol_getMethodDescription(protocol, 44 | selector, 45 | isRequiredMethod, 46 | isInstanceMethod); 47 | return description.types; 48 | } 49 | 50 | + (const char *)getMethodTypeWithClass:(Class)aClass 51 | selector:(SEL)selector 52 | isInstanceMethod:(BOOL)isInstanceMethod { 53 | 54 | const char *type = ""; 55 | 56 | if (isInstanceMethod && [aClass instancesRespondToSelector:selector]) { 57 | Method method = class_getInstanceMethod([aClass class], selector); 58 | type = method_getTypeEncoding(method); 59 | } else if ([aClass respondsToSelector:selector]) { 60 | Method method = class_getClassMethod(object_getClass([aClass class]), selector); 61 | type = method_getTypeEncoding(method); 62 | } 63 | 64 | return type; 65 | } 66 | 67 | + (void)exchangeInstanceMethodWithOriginalClass:(Class)oClass 68 | originalSel:(SEL)originalSelector 69 | swizzledClass:(Class)sClass 70 | swizzledSel:(SEL)swizzledSelector { 71 | 72 | Method originalMethod = class_getInstanceMethod(oClass, originalSelector); 73 | Method swizzleMethod = class_getInstanceMethod(sClass, swizzledSelector); 74 | 75 | BOOL didAddMethod = class_addMethod(sClass, 76 | originalSelector, 77 | method_getImplementation(swizzleMethod), 78 | method_getTypeEncoding(swizzleMethod)); 79 | 80 | if (didAddMethod) { 81 | class_replaceMethod(oClass, 82 | swizzledSelector, 83 | method_getImplementation(originalMethod), 84 | method_getTypeEncoding(originalMethod)); 85 | } else { 86 | method_exchangeImplementations(originalMethod, swizzleMethod); 87 | } 88 | } 89 | 90 | + (SEL)convertGetSelFromSetSel:(SEL)setSel { 91 | NSString *setName = NSStringFromSelector(setSel); 92 | NSString *getName = [self convertGetNameFromSetName:setName]; 93 | return NSSelectorFromString(getName); 94 | } 95 | 96 | + (NSString *)convertGetNameFromSetName:(NSString *)setName { 97 | NSString *head = [[setName substringWithRange:NSMakeRange(3, 1)] lowercaseString]; 98 | NSString *body = [setName substringWithRange:NSMakeRange(4, setName.length-5)]; 99 | NSString *getName = [head stringByAppendingString:body]; 100 | return getName; 101 | } 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Utils/Info/DVInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVInfo.h 3 | // iOS_Template_Objc 4 | // 5 | // Created by DV on 2018/1/10. 6 | // Copyright © 2018年 iOS. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | //判断是否是ipad 14 | #define isPad ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) 15 | //判断iPhone4系列 16 | #define kiPhone4 ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(640, 960), [[UIScreen mainScreen] currentMode].size) && !isPad : NO) 17 | //判断iPhone5系列 18 | #define kiPhone5 ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(640, 1136), [[UIScreen mainScreen] currentMode].size) && !isPad : NO) 19 | //判断iPhone6 6s 7系列 20 | #define kiPhone6 ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(750, 1334), [[UIScreen mainScreen] currentMode].size) && !isPad : NO) 21 | //判断iPhone6p 6sp 7p系列 22 | #define kiPhone6Plus ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1242, 2208), [[UIScreen mainScreen] currentMode].size) && !isPad : NO) 23 | //判断iPhoneX,Xs(iPhoneX,iPhoneXs) 24 | #define IS_IPHONE_X ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) && !isPad : NO) 25 | //判断iPhoneXr 26 | #define IS_IPHONE_Xr ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(828, 1792), [[UIScreen mainScreen] currentMode].size) && !isPad : NO) 27 | //判断iPhoneXsMax 28 | #define IS_IPHONE_Xs_Max ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1242, 2688), [[UIScreen mainScreen] currentMode].size)&& !isPad : NO) 29 | 30 | //判断iPhoneX所有系列 31 | #define IS_PhoneXAll (IS_IPHONE_X || IS_IPHONE_Xr || IS_IPHONE_Xs_Max) 32 | #define k_Height_NavContentBar 44.0f 33 | #define k_Height_StatusBar (IS_PhoneXAll? 44.0 : 20.0) 34 | #define k_Height_NavBar (IS_PhoneXAll ? 88.0 : 64.0) 35 | #define k_Height_TabBar (IS_PhoneXAll ? 83.0 : 49.0) 36 | 37 | 38 | #pragma mark - <-- Define --> 39 | typedef NS_ENUM(NSUInteger, DVPhoneType) { 40 | kiPhone_2G, kiPhone_3G, kiPhone_4, kiPhone_4S, kiPhone_5, 41 | kiPhone_5C, kiPhone_5S, kiPhone_6, kiPhone_6P, kiPhone_6S, 42 | kiPhone_6SP, kiPhone_7, kiPhone_7P, kiPhone_8, kiPhone_8P, 43 | kiPhone_X, kiPhone_XR, kiPhone_XS, kiPhone_XSM, kiPhone_SE, 44 | kiPad_IPAD, k_PC, k_NULL 45 | }; 46 | 47 | 48 | #pragma mark - <-- Class --> 49 | /** 50 | APP信息 & 手机信息 工具类 51 | */ 52 | @interface DVInfo : NSObject 53 | 54 | /// 项目名称 55 | @property(nonatomic, class, readonly) NSString *projectName; 56 | 57 | /// APP名字 58 | @property(nonatomic, class, readonly) NSString *appName; 59 | 60 | /// APP版本 61 | @property(nonatomic, class, readonly) NSString *appVersion; 62 | 63 | /// APP Build版本 64 | @property(nonatomic, class, readonly) NSString *appBuild; 65 | 66 | /// APP Bundle ID 67 | @property(nonatomic, class, readonly) NSString *bundleID; 68 | 69 | /// 手机机型 70 | @property(nonatomic, class, readonly) DVPhoneType phoneType; 71 | 72 | /// 是否为iPhone X 全系列 73 | @property(nonatomic, class, readonly) BOOL isPhoneX_All; 74 | 75 | /// UUID 76 | @property(nonatomic, class, readonly) NSString *UUID; 77 | 78 | /// 开发环境语言 79 | @property(nonatomic, class, readonly) NSString *developRegion; 80 | 81 | /// 当地地区语言 82 | @property(nonatomic, class, readonly) NSString *localLanguage; 83 | 84 | /// 系统语言 85 | @property(nonatomic, class, readonly) NSString *systemLanuage; 86 | 87 | /// APP 支持最低系统版本 88 | @property(nonatomic, class, readonly) NSString *minimumSystemVersion; 89 | 90 | /// 当前系统版本 91 | @property(nonatomic, class, readonly) NSString *systemVersion; 92 | 93 | /// 手机充电状态 94 | @property(nonatomic, class, readonly) UIDeviceBatteryState batteryState; 95 | 96 | /// 手机电量 97 | @property(nonatomic, class, readonly) float batteryLevel; 98 | 99 | /// SIM IP地址 100 | @property(nonatomic, class, readonly) NSString *simIP; 101 | 102 | /// WIFI IP地址 103 | @property(nonatomic, class, readonly) NSString *wifiIP; 104 | 105 | 106 | @end 107 | 108 | NS_ASSUME_NONNULL_END 109 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UIImage+Common.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Common.m 3 | // 4 | // 5 | // Created by DV on 2019/2/25. 6 | // Copyright © 2019 iOS. All rights reserved. 7 | // 8 | 9 | #import "UIImage+Common.h" 10 | #import 11 | 12 | 13 | @implementation UIImage (Common) 14 | 15 | + (instancetype)imageWithColor:(UIColor *)color { 16 | return [self imageWithColor:color size:CGSizeMake(1, 1)]; 17 | } 18 | 19 | + (instancetype)imageWithColor:(UIColor *)color size:(CGSize)size { 20 | //图片尺寸 21 | CGRect rect = CGRectMake(0, 0, size.width, size.height); 22 | //填充画笔 23 | UIGraphicsBeginImageContext(rect.size); 24 | //根据所传颜色绘制 25 | CGContextRef context = UIGraphicsGetCurrentContext(); 26 | CGContextSetFillColorWithColor(context, color.CGColor); 27 | //显示区域 28 | CGContextFillRect(context, rect); 29 | // 得到图片信息 30 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 31 | //消除画笔 32 | UIGraphicsEndImageContext(); 33 | return image; 34 | } 35 | 36 | + (instancetype)imageWithOriginal:(NSString *)name { 37 | return [[UIImage imageNamed:name] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; 38 | } 39 | 40 | 41 | - (UIImage *)resizeImageWithSize:(CGSize)size { 42 | UIGraphicsBeginImageContextWithOptions(size, NO, 0); 43 | [self drawInRect:CGRectMake(0, 0, size.width, size.height)]; 44 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 45 | UIGraphicsEndImageContext(); 46 | return newImage; 47 | } 48 | 49 | - (UIImage *)resizeImageWithScale:(CGFloat)scale { 50 | CGFloat w = self.size.width * scale; 51 | CGFloat h = self.size.height * scale; 52 | CGSize newSize = CGSizeMake(w, h); 53 | UIGraphicsBeginImageContextWithOptions(newSize, NO, 0); 54 | [self drawInRect:CGRectMake(0, 0, w, h)]; 55 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 56 | UIGraphicsEndImageContext(); 57 | return newImage; 58 | } 59 | 60 | - (UIImage *)clipToCircleImage { 61 | UIGraphicsBeginImageContextWithOptions(self.size, NO, 0); 62 | 63 | CGFloat w = self.size.width; 64 | CGFloat h = self.size.height; 65 | UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, w, h)]; 66 | [path addClip]; 67 | 68 | [self drawAtPoint:CGPointZero]; 69 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 70 | 71 | UIGraphicsEndImageContext(); 72 | return newImage; 73 | } 74 | 75 | - (UIImage *)addText:(NSString *)text fontColor:(UIColor *)fontColor fontSize:(CGFloat)fontSize { 76 | UIImage *sourceImage = self; 77 | CGSize imageSize = sourceImage.size; 78 | 79 | UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0); 80 | [sourceImage drawAtPoint:CGPointMake(0, 0)]; 81 | 82 | CGContextRef context = UIGraphicsGetCurrentContext(); 83 | CGContextDrawPath(context, kCGPathStroke); 84 | 85 | NSDictionary *attributes = @{NSFontAttributeName:[UIFont boldSystemFontOfSize:fontSize], 86 | NSForegroundColorAttributeName:fontColor}; 87 | 88 | CGRect sizeToFit = [text boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, fontSize) 89 | options:NSStringDrawingUsesDeviceMetrics 90 | attributes:attributes 91 | context:nil]; 92 | [text drawAtPoint:CGPointMake((imageSize.width-sizeToFit.size.width)/2, (imageSize.height-sizeToFit.size.height)/2-2) withAttributes:attributes]; 93 | 94 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 95 | UIGraphicsEndImageContext(); 96 | return newImage; 97 | } 98 | 99 | 100 | - (void(^)(BOOL))completionBlock { 101 | return (void(^)(BOOL finished))objc_getAssociatedObject(self, _cmd); 102 | } 103 | 104 | - (void)setCompletionBlock:(void(^)(BOOL))completionBlock { 105 | objc_setAssociatedObject(self, @selector(completionBlock), completionBlock, OBJC_ASSOCIATION_COPY_NONATOMIC); 106 | } 107 | 108 | - (void)saveToPhotoAlbum:(void (^)(BOOL))completion { 109 | self.completionBlock = completion; 110 | UIImageWriteToSavedPhotosAlbum(self, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); 111 | } 112 | 113 | @end 114 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UIColor+Common.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+Common.m 3 | // iOS_Template_Objc 4 | // 5 | // Created by DV on 2018/1/9. 6 | // Copyright © 2018年 iOS. All rights reserved. 7 | // 8 | 9 | #import "UIColor+Common.h" 10 | 11 | @implementation UIColor (Common) 12 | 13 | - (UIColor *)darkColor { 14 | NSArray *rgb = self.RGB; 15 | float red = (rgb[0].floatValue < 50.0) ? 0 : (rgb[0].floatValue - 50.0); 16 | float green = (rgb[1].floatValue < 50.0) ? 0 : (rgb[1].floatValue - 50.0); 17 | float blue = (rgb[2].floatValue < 50.0) ? 0 : (rgb[2].floatValue - 50.0); 18 | float alpha = rgb[3].floatValue; 19 | return [UIColor colorWithRGBA:@[@(red),@(green),@(blue),@(alpha)]]; 20 | } 21 | 22 | + (UIColor *)randomColor { 23 | CGFloat hue = (CGFloat)(arc4random() % 256) / 256.0; 24 | CGFloat satur = (CGFloat)(arc4random() % 128) / 256.0 + 0.5; 25 | CGFloat bright = (CGFloat)(arc4random() % 128) / 256.0 + 0.5; 26 | return [UIColor colorWithHue:hue saturation:satur brightness:bright alpha:1]; 27 | } 28 | 29 | - (NSArray *)RGB { 30 | size_t n = CGColorGetNumberOfComponents(self.CGColor); 31 | const CGFloat *rgba = CGColorGetComponents(self.CGColor); 32 | NSMutableArray *resultArr = [NSMutableArray new]; 33 | 34 | for (int i = 0; i < 4; i++){ 35 | NSNumber *value; 36 | 37 | if (n == 2) { 38 | if (i == 3) { 39 | value = @(rgba[1]); 40 | } 41 | else{ 42 | value = @(rgba[0]*255.0); 43 | } 44 | 45 | } 46 | else{ 47 | if (i == 3) { 48 | value = @(rgba[i]); 49 | } 50 | else{ 51 | value = @(rgba[i]*255.0); 52 | } 53 | } 54 | 55 | [resultArr addObject:value]; 56 | } 57 | 58 | return [resultArr copy]; 59 | } 60 | 61 | 62 | 63 | #pragma mark - <-- Instance --> 64 | + (instancetype)colorWithRGBA:(NSArray *)rgba { 65 | float red = rgba[0].floatValue/255.0f; 66 | float green = rgba[1].floatValue/255.0f; 67 | float blue = rgba[2].floatValue/255.0f; 68 | float alpha = (rgba.count < 4 ? 1.0f : rgba[3].floatValue); 69 | 70 | return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; 71 | } 72 | 73 | + (instancetype)colorWithHex:(UInt32)hex { 74 | return [UIColor colorWithHex:hex alpha:1.0f]; 75 | } 76 | 77 | + (instancetype)colorWithHex:(UInt32)hex alpha:(float)opacity { 78 | float red = ((float)((hex & 0xFF0000) >> 16))/255.0; 79 | float green = ((float)((hex & 0xFF00) >> 8))/255.0; 80 | float blue = ((float)(hex & 0xFF))/255.0; 81 | return [UIColor colorWithRed:red green:green blue:blue alpha:opacity]; 82 | } 83 | 84 | + (instancetype)colorWithHexString:(NSString *)hexString { 85 | return [self colorWithHexString:hexString alpha:1.0f]; 86 | } 87 | 88 | + (instancetype)colorWithHexString:(NSString *)hexString alpha:(float)opacity { 89 | NSString *cString = [[hexString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString]; 90 | // String should be 6 or 8 characters 91 | 92 | if ([cString length] < 6) return [UIColor blackColor]; 93 | // strip 0X if it appears 94 | if ([cString hasPrefix:@"0X"] || [cString hasPrefix:@"0x"]) cString = [cString substringFromIndex:2]; 95 | if ([cString hasPrefix:@"#"]) cString = [cString substringFromIndex:1]; 96 | if ([cString length] != 6) return [UIColor blackColor]; 97 | 98 | // Separate into r, g, b substrings 99 | 100 | NSRange range; 101 | range.location = 0; 102 | range.length = 2; 103 | NSString *rString = [cString substringWithRange:range]; 104 | range.location = 2; 105 | NSString *gString = [cString substringWithRange:range]; 106 | range.location = 4; 107 | NSString *bString = [cString substringWithRange:range]; 108 | // Scan values 109 | unsigned int r, g, b; 110 | 111 | [[NSScanner scannerWithString:rString] scanHexInt:&r]; 112 | [[NSScanner scannerWithString:gString] scanHexInt:&g]; 113 | [[NSScanner scannerWithString:bString] scanHexInt:&b]; 114 | 115 | return [UIColor colorWithRed:((float) r / 255.0f) 116 | green:((float) g / 255.0f) 117 | blue:((float) b / 255.0f) 118 | alpha:opacity]; 119 | } 120 | @end 121 | -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit/Model/DVDataBindObserverModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // DVDataBindObserverModel.m 3 | // 4 | // Created by David.Shi on 2018/3/16. 5 | // Copyright © 2018 iOS. All rights reserved. 6 | // 7 | 8 | #import "DVDataBindObserverModel.h" 9 | #import "NSObject+DataBind.h" 10 | 11 | @implementation DVDataBindObserverModel 12 | 13 | #pragma mark - <-- Instance --> 14 | - (instancetype)initWithObserver:(id)observer 15 | target:(id)target 16 | keyPath:(NSString *)keyPath 17 | context:(void *)context 18 | convertBlock:(DBAnyAnyBlock)convertBlock 19 | databindType:(DVDataBindType)dbType { 20 | self = [super init]; 21 | if (self) { 22 | self.observer = observer; 23 | self.target = target; 24 | self.keyPath = keyPath; 25 | self.convertBlock = convertBlock; 26 | self.targetHash = [(NSObject *)target db_Hash]; 27 | self.oldValue = [target valueForKey:keyPath]; 28 | self.dbType = dbType; 29 | self.modelType = DVDataBindObserverModelType_Object; 30 | self.propertyType = [target db_getDBPropertyTypeWithName:keyPath]; 31 | _context = context; 32 | self.index = NSUIntegerMax; 33 | self.oldString = @""; 34 | } 35 | return self; 36 | } 37 | 38 | - (instancetype)initWithObserver:(id)observer 39 | target:(id)target 40 | keyPath:(NSString *)keyPath 41 | selector:(SEL)selector 42 | controlEvent:(UIControlEvents)ctrlEvent 43 | convertBlock:(DBAnyAnyBlock)convertBlock 44 | databindType:(DVDataBindType)dbType { 45 | self = [super init]; 46 | if (self) { 47 | self.observer = observer; 48 | self.target = target; 49 | self.keyPath = keyPath; 50 | self.convertBlock = convertBlock; 51 | self.targetHash = [(NSObject *)target db_Hash]; 52 | self.oldValue = [target valueForKey:keyPath]; 53 | self.dbType = dbType; 54 | self.modelType = DVDataBindObserverModelType_UI; 55 | self.propertyType = [target db_getDBPropertyTypeWithName:keyPath]; 56 | self.selector = selector; 57 | self.ctrlEvent = ctrlEvent; 58 | self.index = NSUIntegerMax; 59 | self.oldString = @""; 60 | } 61 | return self; 62 | } 63 | 64 | - (instancetype)initWithObserver:(id)observer 65 | target:(id)target 66 | keyPath:(NSString *)keyPath 67 | index:(NSUInteger)index 68 | convertBlock:(DBAnyAnyBlock)convertBlock 69 | databindType:(DVDataBindType)dbType { 70 | self = [super init]; 71 | if (self) { 72 | self.observer = observer; 73 | self.target = target; 74 | self.keyPath = keyPath; 75 | self.convertBlock = convertBlock; 76 | self.targetHash = [(NSObject *)target db_Hash]; 77 | self.dbType = dbType; 78 | self.modelType = DVDataBindObserverModelType_Array; 79 | self.propertyType = [target db_getDBPropertyTypeWithName:keyPath]; 80 | self.index = index; 81 | self.oldString = @""; 82 | 83 | NSMutableArray *array = [target valueForKey:keyPath]; 84 | if (array && index < array.count) { 85 | self.oldValue = array[index]; 86 | self.propertyType = [(NSObject *)array[index] db_propertyType]; 87 | } 88 | } 89 | return self; 90 | } 91 | 92 | 93 | 94 | 95 | #pragma mark - <-- Dealloc --> 96 | - (void)dealloc { 97 | if (self.observer 98 | && self.target 99 | && self.keyPath 100 | && ((self.dbType & DVDataBindType_IN) == DVDataBindType_IN)) { 101 | [self.target removeObserver:self.observer forKeyPath:self.keyPath]; 102 | } 103 | 104 | if (self.observer 105 | && self.target 106 | && self.selector != nil 107 | && ((self.ctrlEvent & UIControlEventAllEvents) != 0x00 ) 108 | && ((self.dbType & DVDataBindType_IN) == DVDataBindType_IN)) { 109 | [self.target removeTarget:self.observer action:self.selector forControlEvents:self.ctrlEvent]; 110 | } 111 | 112 | _observer = nil; 113 | _target = nil; 114 | _convertBlock = nil; 115 | _oldValue = nil; 116 | _selector = NULL; 117 | _context = nil; 118 | } 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /DVDataBindKit/DVDataBindKit/Category/NSObject+DataBind.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+DataBind.m 3 | // 4 | // Created by David.Shi on 2018/3/16. 5 | // Copyright © 2018 iOS. All rights reserved. 6 | // 7 | 8 | #import "NSObject+DataBind.h" 9 | #import 10 | 11 | @implementation NSObject (DataBind) 12 | 13 | #pragma mark - <-- Property --> 14 | - (BOOL)db_isDidChanged { 15 | NSNumber *boolValue = objc_getAssociatedObject(self, _cmd); 16 | return [boolValue boolValue]; 17 | } 18 | 19 | - (void)setDb_isDidChanged:(BOOL)db_isDidChanged { 20 | objc_setAssociatedObject(self, @selector(db_isDidChanged), @(db_isDidChanged), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 21 | } 22 | 23 | - (DVDataBindTargetModel *)db_targetModel { 24 | return objc_getAssociatedObject(self, _cmd); 25 | } 26 | 27 | - (void)setDb_targetModel:(DVDataBindTargetModel *)db_targetModel { 28 | objc_setAssociatedObject(self, @selector(db_targetModel), db_targetModel, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 29 | } 30 | 31 | - (NSString *)db_ctrl_targetKeyHash { 32 | NSString *targetKeyHash = objc_getAssociatedObject(self, _cmd); 33 | return targetKeyHash ? targetKeyHash : @""; 34 | } 35 | 36 | - (void)setDb_ctrl_targetKeyHash:(NSString *)db_ctrl_targetKeyHash { 37 | objc_setAssociatedObject(self, @selector(db_ctrl_targetKeyHash), db_ctrl_targetKeyHash, OBJC_ASSOCIATION_COPY_NONATOMIC); 38 | } 39 | 40 | - (NSString *)db_Hash { 41 | return [NSString stringWithFormat:@"%lx", (unsigned long)[self hash]]; 42 | } 43 | 44 | - (DBPropertyType)db_propertyType { 45 | if ([self isKindOfClass:[NSNumber class]]) { 46 | NSNumber *num = (NSNumber *)self; 47 | const char *type = num.objCType; 48 | return [self db_getPropertyRealType:type isFree:NO]; 49 | } 50 | else if ([self isKindOfClass:[NSString class]]) { 51 | return DBPropertyType_NSString; 52 | } 53 | else if ([self isKindOfClass:[NSArray class]]) { 54 | return DBPropertyType_NSArray; 55 | } 56 | else if ([self isKindOfClass:[NSDictionary class]]) { 57 | return DBPropertyType_NSArray; 58 | } 59 | else if ([self isKindOfClass:[NSSet class]]) { 60 | return DBPropertyType_NSSet; 61 | } 62 | else if ([self isKindOfClass:[NSObject class]] ) { 63 | return DBPropertyType_NSObject; 64 | } 65 | 66 | return DBPropertyType_Void; 67 | } 68 | 69 | 70 | #pragma mark - <-- Method --> 71 | - (DBPropertyType)db_getDBPropertyTypeWithName:(NSString *)propertyName { 72 | objc_property_t property = class_getProperty([self class], propertyName.UTF8String); 73 | const char *property_attr = property_copyAttributeValue(property, "T"); 74 | 75 | return [self db_getPropertyRealType:property_attr isFree:YES]; 76 | } 77 | 78 | - (DBPropertyType)db_getPropertyRealType:(const char *)property_attr isFree:(BOOL)isFree { 79 | DBPropertyType type = DBPropertyType_Void; 80 | char t = property_attr[0]; 81 | 82 | if (t == '@') { 83 | 84 | NSString *attr = [NSString stringWithUTF8String:property_attr]; 85 | 86 | if ([attr containsString:@"NSString"]) { 87 | type = DBPropertyType_NSString; 88 | } else if ([attr containsString:@"NSNumber"]) { 89 | type = DBPropertyType_NSNumber; 90 | } else if ([attr containsString:@"NSArray"]) { 91 | type = DBPropertyType_NSArray; 92 | } else if ([attr containsString:@"NSDictionary"]) { 93 | type = DBPropertyType_NSDictionary; 94 | } else if ([attr containsString:@"NSSet"]){ 95 | type = DBPropertyType_NSSet; 96 | } else { 97 | type = DBPropertyType_NSObject; 98 | } 99 | 100 | } else if (t == 'q') { 101 | type = DBPropertyType_NSInteger; 102 | } else if (t == 'Q') { 103 | type = DBPropertyType_NSUInteger; 104 | } else if (t == 'i') { 105 | type = DBPropertyType_Int; 106 | } else if (t == 'I') { 107 | type = DBPropertyType_UInt; 108 | } else if (t == 'f') { 109 | type = DBPropertyType_Float; 110 | } else if (t == 'd') { 111 | type = DBPropertyType_Double; 112 | } else if (t == 'B') { 113 | type = DBPropertyType_Bool; 114 | } else if (t == 'c') { 115 | type = DBPropertyType_Char; 116 | } else if (t == 'C') { 117 | type = DBPropertyType_UChar; 118 | } else if (t == 's') { 119 | type = DBPropertyType_Short; 120 | } else if (t == 'S') { 121 | type = DBPropertyType_UShort; 122 | } else if (t == 'v') { 123 | type = DBPropertyType_Void; 124 | } else if (t == '*') { 125 | type = DBPropertyType_Chars; 126 | } else if (t == ':') { 127 | type = DBPropertyType_Sel; 128 | } else if (t == '#') { 129 | type = DBPropertyType_Class; 130 | } 131 | 132 | if (isFree) free(property_attr); 133 | 134 | return type; 135 | } 136 | 137 | @end 138 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/Category/UI/UIViewController+Common.m: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // UIViewController+Common.m 4 | // iOS_Template_Objc 5 | // 6 | // Created by DV on 2018/1/10. 7 | // Copyright © 2018年 iOS. All rights reserved. 8 | // 9 | 10 | #import "UIViewController+Common.h" 11 | 12 | @implementation UIViewController (Common) 13 | 14 | #pragma mark - <-- Setter & Getter --> 15 | - (BOOL)isHiddenNavBar { 16 | return self.navBarAlpha > 0 ? NO : YES; 17 | } 18 | 19 | - (void)setIsHiddenNavBar:(BOOL)isHiddenNavBar { 20 | self.navBarAlpha = (isHiddenNavBar == YES ? 0 : 1); 21 | } 22 | 23 | 24 | 25 | - (CGFloat)navBarAlpha { 26 | UINavigationBar *navBar = self.navigationController.navigationBar; 27 | 28 | if (navBar.subviews.count == 0) return 1; 29 | 30 | if (@available(iOS 13, *)) { 31 | UIView *barBackgroundView = navBar.subviews[0].subviews[1]; 32 | if (navBar.isTranslucent && barBackgroundView) { 33 | return barBackgroundView.alpha; 34 | } 35 | } 36 | else if (@available(iOS 11, *)) { 37 | UIView *barBackgroundView = navBar.subviews[0].subviews[1]; 38 | if (navBar.isTranslucent && barBackgroundView) { 39 | return barBackgroundView.alpha; 40 | } 41 | } 42 | else { 43 | UIView *barBackgroundView = navBar.subviews[0]; 44 | if (navBar.isTranslucent && barBackgroundView) { 45 | return barBackgroundView.alpha; 46 | } 47 | } 48 | return 1.0f; 49 | } 50 | 51 | - (void)setNavBarAlpha:(CGFloat)navBarAlpha { 52 | if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) { 53 | self.edgesForExtendedLayout = navBarAlpha > 0 ? UIRectEdgeNone : UIRectEdgeTop; 54 | } 55 | 56 | UINavigationBar *navBar = self.navigationController.navigationBar; 57 | if (navBar.subviews.count == 0) return; 58 | 59 | if (@available(iOS 13, *)) { 60 | UIView *barBackgroundView = navBar.subviews[0].subviews[1]; 61 | if (navBar.isTranslucent && barBackgroundView) { 62 | barBackgroundView.alpha = navBarAlpha; 63 | for (UIView *subView in barBackgroundView.subviews) { 64 | subView.alpha = navBarAlpha; 65 | } 66 | } 67 | } 68 | else if (@available(iOS 11, *)) { 69 | UIView *barBackgroundView = navBar.subviews[0].subviews[1]; 70 | if (navBar.isTranslucent && barBackgroundView) { 71 | barBackgroundView.alpha = navBarAlpha; 72 | } 73 | } 74 | else { 75 | UIView *barBackgroundView = navBar.subviews[0]; 76 | if (navBar.isTranslucent && barBackgroundView) { 77 | barBackgroundView.alpha = navBarAlpha; 78 | } 79 | } 80 | navBar.clipsToBounds = (navBarAlpha > 0) ? NO : YES; 81 | } 82 | 83 | 84 | #pragma mark - <-- Method --> 85 | + (instancetype)viewControlWithStoryBoard { 86 | NSString *className = NSStringFromClass([self class]); 87 | UIStoryboard *sb = [UIStoryboard storyboardWithName:className bundle:nil]; 88 | UIViewController *vc = [sb instantiateViewControllerWithIdentifier:className]; 89 | return vc; 90 | } 91 | 92 | + (instancetype)storyBoardWithName:(NSString *)storyBoardName identifier:(NSString *)identifier { 93 | UIStoryboard *sb = [UIStoryboard storyboardWithName:storyBoardName bundle:nil]; 94 | UIViewController *vc = [sb instantiateViewControllerWithIdentifier:identifier]; 95 | return vc; 96 | } 97 | 98 | - (void)presentViewControllerWithStoryBoard:(NSString *)storyBoardName 99 | identifier:(NSString *)identifier 100 | animated:(BOOL)flag 101 | completion:(void (^)(void))completion { 102 | UIStoryboard *sb = [UIStoryboard storyboardWithName:storyBoardName bundle:nil]; 103 | UIViewController *vc = [sb instantiateViewControllerWithIdentifier:identifier]; 104 | [self presentViewController:vc animated:flag completion:completion]; 105 | } 106 | 107 | - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated { 108 | viewController.hidesBottomBarWhenPushed = YES; 109 | [self.navigationController pushViewController:viewController animated:animated]; 110 | } 111 | 112 | - (void)pushViewControllerWithClassName:(NSString *)className animated:(BOOL)animated { 113 | Class aClass = NSClassFromString(className); 114 | if (aClass) { 115 | UIViewController *vc = [aClass new]; 116 | vc.hidesBottomBarWhenPushed = YES; 117 | [self pushViewController:vc animated:animated]; 118 | } 119 | } 120 | 121 | - (void)popViewControllerAnimated:(BOOL)animated { 122 | [self.navigationController popViewControllerAnimated:animated]; 123 | } 124 | 125 | - (void)setTabBarItemWithTitle:(NSString *)title fontSize:(CGFloat)fontSize image:(UIImage *)image { 126 | [self.tabBarItem setTitle:title]; 127 | [self.tabBarItem setImage:[image imageWithRenderingMode:(UIImageRenderingModeAutomatic)]]; 128 | } 129 | 130 | 131 | @end 132 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UISegmented 例子/View/SegmentedView.xib: -------------------------------------------------------------------------------- 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 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/UIImageView 例子/View/ImageView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/MVVM实现登录界面 例子/View/LoginView.xib: -------------------------------------------------------------------------------- 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 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /DVDataBindDemo/DVDataBindDemo/UI/普通例子/View/DemoView.xib: -------------------------------------------------------------------------------- 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 | 27 | 28 | 29 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | --------------------------------------------------------------------------------