├── CoreModel.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── Charlin.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── Charlin.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── CoreModel.xcscheme │ └── xcschememanagement.plist ├── CoreModel ├── APP │ ├── Common │ │ ├── CommonVC.h │ │ ├── CommonVC.m │ │ └── CoreSVP │ │ │ ├── CoreSVP.h │ │ │ ├── CoreSVP.m │ │ │ └── Lib │ │ │ ├── SVP.bundle │ │ │ ├── green@2x.png │ │ │ ├── green@3x.png │ │ │ ├── red@2x.png │ │ │ ├── red@3x.png │ │ │ ├── yellow@2x.png │ │ │ └── yellow@3x.png │ │ │ └── SVProgressHUD │ │ │ ├── SVIndefiniteAnimatedView.h │ │ │ ├── SVIndefiniteAnimatedView.m │ │ │ ├── SVProgressHUD-Prefix.pch │ │ │ ├── SVProgressHUD.bundle │ │ │ ├── angle-mask.png │ │ │ ├── angle-mask@2x.png │ │ │ ├── angle-mask@3x.png │ │ │ ├── error.png │ │ │ ├── error@2x.png │ │ │ ├── error@3x.png │ │ │ ├── info.png │ │ │ ├── info@2x.png │ │ │ ├── info@3x.png │ │ │ ├── success.png │ │ │ ├── success@2x.png │ │ │ └── success@3x.png │ │ │ ├── SVProgressHUD.h │ │ │ └── SVProgressHUD.m │ ├── List │ │ ├── ListTVC.h │ │ └── ListTVC.m │ ├── Model │ │ ├── City.h │ │ ├── City.m │ │ ├── Pen.h │ │ ├── Pen.m │ │ ├── Person.h │ │ └── Person.m │ └── Modules │ │ ├── Test10VC.h │ │ ├── Test10VC.m │ │ ├── Test11VC.h │ │ ├── Test11VC.m │ │ ├── Test12VC.h │ │ ├── Test12VC.m │ │ ├── Test12VC.xib │ │ ├── Test13VC.h │ │ ├── Test13VC.m │ │ ├── Test14VC.h │ │ ├── Test14VC.m │ │ ├── Test15VC.h │ │ ├── Test15VC.m │ │ ├── Test15VC.xib │ │ ├── Test16VC.h │ │ ├── Test16VC.m │ │ ├── Test17VC.h │ │ ├── Test17VC.m │ │ ├── Test2VC.h │ │ ├── Test2VC.m │ │ ├── Test3VC.h │ │ ├── Test3VC.m │ │ ├── Test4VC.h │ │ ├── Test4VC.m │ │ ├── Test5VC.h │ │ ├── Test5VC.m │ │ ├── Test6VC.h │ │ ├── Test6VC.m │ │ ├── Test7VC.h │ │ ├── Test7VC.m │ │ ├── Test8VC.h │ │ ├── Test8VC.m │ │ ├── Test9VC.h │ │ └── Test9VC.m ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── p1.imageset │ │ ├── Contents.json │ │ └── p1.png │ ├── p2.imageset │ │ ├── Contents.json │ │ └── p2.png │ └── p3.imageset │ │ ├── Contents.json │ │ └── p3.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── CoreModel │ ├── CoreModel.h │ ├── CoreModel.m │ └── Lib │ │ ├── Category │ │ ├── NSArray │ │ │ ├── NSArray+CoreModel.h │ │ │ └── NSArray+CoreModel.m │ │ ├── NSDictionary │ │ │ ├── NSDictionary+Sqlite.h │ │ │ └── NSDictionary+Sqlite.m │ │ ├── NSObject │ │ │ ├── CoreModel+Cache.h │ │ │ ├── CoreModel+Cache.m │ │ │ ├── NSObject+CoreModelCommon.h │ │ │ ├── NSObject+CoreModelCommon.m │ │ │ ├── NSObject+Create.h │ │ │ ├── NSObject+Create.m │ │ │ ├── NSObject+Delete.h │ │ │ ├── NSObject+Delete.m │ │ │ ├── NSObject+Insert.h │ │ │ ├── NSObject+Insert.m │ │ │ ├── NSObject+Save.h │ │ │ ├── NSObject+Save.m │ │ │ ├── NSObject+Select.h │ │ │ ├── NSObject+Select.m │ │ │ ├── NSObject+Update.h │ │ │ └── NSObject+Update.m │ │ ├── NSOperationQueue │ │ │ ├── NSOperationQueue+Queue.h │ │ │ └── NSOperationQueue+Queue.m │ │ └── NSString │ │ │ ├── NSString+Stackoverflow.h │ │ │ └── NSString+Stackoverflow.m │ │ ├── CoreMoelConst │ │ ├── CoreModelConst.h │ │ └── CoreModelConst.m │ │ ├── Protocol │ │ ├── CoreModelProtocol.h │ │ └── CorePageModelProtocol.h │ │ ├── Reflect │ │ ├── CoreProperty.h │ │ ├── CoreProperty.m │ │ ├── NSObject+Runtime.h │ │ └── NSObject+Runtime.m │ │ └── Type │ │ └── CoreModelType.h ├── FrameWorks │ └── CoreFMDB │ │ ├── CoreFMDB.h │ │ ├── CoreFMDB.m │ │ └── Lib │ │ ├── Category │ │ ├── NSString+CoreFMDB.h │ │ └── NSString+CoreFMDB.m │ │ ├── Singleton │ │ └── CoreFMDBSingleton.h │ │ └── fmdb │ │ ├── FMDB.h │ │ ├── FMDatabase.h │ │ ├── FMDatabase.m │ │ ├── FMDatabaseAdditions.h │ │ ├── FMDatabaseAdditions.m │ │ ├── FMDatabasePool.h │ │ ├── FMDatabasePool.m │ │ ├── FMDatabaseQueue.h │ │ ├── FMDatabaseQueue.m │ │ ├── FMResultSet.h │ │ └── FMResultSet.m ├── Info.plist ├── ViewController.h ├── ViewController.m └── main.m └── README.md /CoreModel.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CoreModel.xcodeproj/project.xcworkspace/xcuserdata/Charlin.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel.xcodeproj/project.xcworkspace/xcuserdata/Charlin.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /CoreModel.xcodeproj/xcuserdata/Charlin.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /CoreModel.xcodeproj/xcuserdata/Charlin.xcuserdatad/xcschemes/CoreModel.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /CoreModel.xcodeproj/xcuserdata/Charlin.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CoreModel.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 89CFA0A11CAFCB1700A280D2 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /CoreModel/APP/Common/CommonVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // CommonVC.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CoreSVP.h" 11 | 12 | #import "Person.h" 13 | 14 | 15 | 16 | @interface CommonVC : UIViewController 17 | 18 | -(void)show:(BOOL)res; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /CoreModel/APP/Common/CommonVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // CommonVC.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CommonVC.h" 10 | 11 | @interface CommonVC () 12 | 13 | @end 14 | 15 | @implementation CommonVC 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | 21 | self.view.backgroundColor = [UIColor whiteColor]; 22 | 23 | 24 | 25 | } 26 | 27 | 28 | 29 | -(void)show:(BOOL)res{ 30 | 31 | if(res){ 32 | 33 | CoreSVPSuccess(@"操作成功") 34 | 35 | }else{ 36 | 37 | CoreSVPError(@"操作失败") 38 | } 39 | 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/CoreSVP.h: -------------------------------------------------------------------------------- 1 | // 2 | // CoreSVP.h 3 | // 4 | // Created by muxi on 14/10/22. 5 | // Copyright (c) 2014年 muxi. All rights reserved. 6 | // 提示工具类 7 | 8 | 9 | 10 | #import 11 | #import 12 | #import "SVProgressHUD.h" 13 | 14 | #define CoreSVPSuccess(msg) [CoreSVP showSVPWithType:CoreSVPTypeSuccess Msg:msg duration:1.5 allowEdit:NO beginBlock:nil completeBlock:nil]; 15 | #define CoreSVPError(msg) [CoreSVP showSVPWithType:CoreSVPTypeError Msg:msg duration:2.0 allowEdit:NO beginBlock:nil completeBlock:nil]; 16 | #define CoreSVPLoading(msg,allow) [CoreSVP showSVPWithType:CoreSVPTypeLoadingInterface Msg:msg duration:0 allowEdit:allow beginBlock:nil completeBlock:nil]; 17 | 18 | 19 | 20 | 21 | 22 | typedef enum { 23 | 24 | CoreSVPTypeNone = 0, //默认无状态 25 | 26 | CoreSVPTypeCenterMsg, //无图片普通提示,显示在屏幕正中间 27 | 28 | CoreSVPTypeBottomMsg, //无图片普通提示,显示在屏幕下方,tabbar之上 29 | 30 | CoreSVPTypeInfo, //Info 31 | 32 | CoreSVPTypeLoadingInterface, //Progress,可以互 33 | 34 | CoreSVPTypeError, //error 35 | 36 | CoreSVPTypeSuccess //success 37 | 38 | }CoreSVPType; 39 | 40 | 41 | 42 | 43 | 44 | @interface CoreSVP : NSObject 45 | 46 | 47 | 48 | 49 | /** 50 | * 展示提示框 51 | * 52 | * @param type 类型 53 | * @param msg 文字 54 | * @param duration 时间(当type=CoreSVPTypeLoadingInterface时无效) 55 | * @param allowEdit 否允许编辑 56 | * @param beginBlock 提示开始时的回调 57 | * @param completeBlock 提示结束时的回调 58 | */ 59 | +(void)showSVPWithType:(CoreSVPType)type Msg:(NSString *)msg duration:(CGFloat)duration allowEdit:(BOOL)allowEdit beginBlock:(void(^)())beginBlock completeBlock:(void(^)())completeBlock; 60 | 61 | 62 | /* 63 | * 进度 64 | */ 65 | +(void)showProgess:(CGFloat)progress Msg:(NSString *)msg maskType:(SVProgressHUDMaskType)maskType; 66 | 67 | 68 | 69 | 70 | /** 71 | * 隐藏提示框 72 | */ 73 | +(void)dismiss; 74 | 75 | 76 | @end 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/CoreSVP.m: -------------------------------------------------------------------------------- 1 | // 2 | // CoreSVP.m 3 | // 新浪微博2014MJ版 4 | // 5 | // Created by muxi on 14/10/22. 6 | // Copyright (c) 2014年 muxi. All rights reserved. 7 | // 8 | 9 | #import "CoreSVP.h" 10 | 11 | static CoreSVPType SVPtype = CoreSVPTypeNone; 12 | 13 | #define rgba(r,g,b,a) [UIColor colorWithRed:r/255.0f green:g/255.0f blue:b/255.0f alpha:a] 14 | 15 | @interface CoreSVP () 16 | 17 | 18 | 19 | @end 20 | 21 | 22 | 23 | @implementation CoreSVP 24 | 25 | 26 | /** 27 | * 展示提示框 28 | * 29 | * @param type 类型 30 | * @param msg 文字 31 | * @param duration 时间(当type=CoreSVPTypeLoadingInterface时无效) 32 | * @param allowEdit 否允许编辑 33 | * @param beginBlock 提示开始时的回调 34 | * @param completeBlock 提示结束时的回调 35 | */ 36 | +(void)showSVPWithType:(CoreSVPType)type Msg:(NSString *)msg duration:(CGFloat)duration allowEdit:(BOOL)allowEdit beginBlock:(void(^)())beginBlock completeBlock:(void(^)())completeBlock{ 37 | 38 | if(CoreSVPTypeLoadingInterface != type && CoreSVPTypeLoadingInterface == SVPtype){ 39 | 40 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.8f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 41 | 42 | SVPtype = type; 43 | 44 | [self showSVPWithType:type Msg:msg duration:duration allowEdit:allowEdit beginBlock:beginBlock completeBlock:completeBlock]; 45 | }); 46 | 47 | return; 48 | } 49 | 50 | //记录状态 51 | SVPtype = type; 52 | 53 | 54 | //无状态直接返回 55 | if (CoreSVPTypeNone == type) return; 56 | 57 | 58 | 59 | dispatch_async(dispatch_get_main_queue(), ^{ 60 | 61 | //基本配置 62 | [self hudSetting]; 63 | 64 | if(CoreSVPTypeBottomMsg == type) [SVProgressHUD setOffsetFromCenter:UIOffsetMake(0, [UIScreen mainScreen].applicationFrame.size.height * .5f-49.0f)]; 65 | 66 | 67 | //设置时间 68 | [SVProgressHUD setDuration:duration]; 69 | 70 | //错误图片 71 | [SVProgressHUD setErrorImage:[UIImage imageNamed:@"SVP.bundle/red"]]; 72 | 73 | //成功图片 74 | [SVProgressHUD setSuccessImage:[UIImage imageNamed:@"SVP.bundle/green"]]; 75 | 76 | //警告图片 77 | [SVProgressHUD setInfoImage:[UIImage imageNamed:@"SVP.bundle/yellow"]]; 78 | 79 | SVProgressHUDMaskType maskType=allowEdit?SVProgressHUDMaskTypeNone:SVProgressHUDMaskTypeClear; 80 | [SVProgressHUD setDefaultMaskType:maskType]; 81 | 82 | //开始回调 83 | if(beginBlock != nil) beginBlock(); 84 | 85 | if(CoreSVPTypeLoadingInterface != type) [SVProgressHUD setCompleteBlock:completeBlock]; 86 | 87 | switch (type) { 88 | 89 | case CoreSVPTypeCenterMsg: 90 | case CoreSVPTypeBottomMsg: 91 | [SVProgressHUD showImage:nil status:msg]; 92 | break; 93 | 94 | case CoreSVPTypeInfo: 95 | [SVProgressHUD showInfoWithStatus:msg]; 96 | break; 97 | 98 | case CoreSVPTypeLoadingInterface: 99 | [SVProgressHUD showWithStatus:msg]; 100 | break; 101 | 102 | case CoreSVPTypeError: 103 | [SVProgressHUD showErrorWithStatus:msg]; 104 | break; 105 | 106 | case CoreSVPTypeSuccess: 107 | [SVProgressHUD showSuccessWithStatus:msg]; 108 | break; 109 | 110 | default: 111 | break; 112 | } 113 | 114 | }); 115 | } 116 | 117 | 118 | /* 119 | * 进度 120 | */ 121 | +(void)showProgess:(CGFloat)progress Msg:(NSString *)msg maskType:(SVProgressHUDMaskType)maskType{ 122 | 123 | if (progress<=0) progress = 0; 124 | 125 | dispatch_async(dispatch_get_main_queue(), ^{ 126 | 127 | //基本配置 128 | [self hudSetting]; 129 | 130 | [SVProgressHUD showProgress:progress status:msg maskType:maskType]; 131 | 132 | if(progress>=1) { 133 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.5f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 134 | [self dismiss]; 135 | }); 136 | } 137 | }); 138 | } 139 | 140 | 141 | /* 142 | * 基本配置 143 | */ 144 | +(void)hudSetting{ 145 | 146 | //设置背景色 147 | [SVProgressHUD setBackgroundColor:rgba(92,93,94,1)]; 148 | 149 | //文字颜色 150 | [SVProgressHUD setForegroundColor:rgba(241, 241, 241, 1)]; 151 | 152 | //字体大小 153 | [SVProgressHUD setFont:[UIFont systemFontOfSize:16.0f]]; 154 | 155 | //设置线宽 156 | [SVProgressHUD setRingThickness:2.f]; 157 | 158 | //边角 159 | [SVProgressHUD setCornerRadius:2.0f]; 160 | } 161 | 162 | 163 | /** 164 | * 隐藏提示框 165 | */ 166 | +(void)dismiss{ 167 | 168 | dispatch_async(dispatch_get_main_queue(), ^{ 169 | [SVProgressHUD dismiss]; 170 | }); 171 | } 172 | 173 | @end 174 | -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVP.bundle/green@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/APP/Common/CoreSVP/Lib/SVP.bundle/green@2x.png -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVP.bundle/green@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/APP/Common/CoreSVP/Lib/SVP.bundle/green@3x.png -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVP.bundle/red@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/APP/Common/CoreSVP/Lib/SVP.bundle/red@2x.png -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVP.bundle/red@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/APP/Common/CoreSVP/Lib/SVP.bundle/red@3x.png -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVP.bundle/yellow@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/APP/Common/CoreSVP/Lib/SVP.bundle/yellow@2x.png -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVP.bundle/yellow@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/APP/Common/CoreSVP/Lib/SVP.bundle/yellow@3x.png -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVIndefiniteAnimatedView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SVIndefiniteAnimatedView.h 3 | // SVProgressHUD 4 | // 5 | // Created by Guillaume Campagna on 2014-12-05. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface SVIndefiniteAnimatedView : UIView 12 | 13 | @property (nonatomic, assign) CGFloat strokeThickness; 14 | @property (nonatomic, assign) CGFloat radius; 15 | @property (nonatomic, strong) UIColor *strokeColor; 16 | 17 | @end 18 | 19 | -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVIndefiniteAnimatedView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SVIndefiniteAnimatedView.m 3 | // SVProgressHUD 4 | // 5 | // Created by Guillaume Campagna on 2014-12-05. 6 | // 7 | // 8 | 9 | #import "SVIndefiniteAnimatedView.h" 10 | 11 | #pragma mark SVIndefiniteAnimatedView 12 | 13 | @interface SVIndefiniteAnimatedView () 14 | 15 | @property (nonatomic, strong) CAShapeLayer *indefiniteAnimatedLayer; 16 | 17 | @end 18 | 19 | @implementation SVIndefiniteAnimatedView 20 | 21 | - (void)willMoveToSuperview:(UIView *)newSuperview { 22 | if (newSuperview) { 23 | [self layoutAnimatedLayer]; 24 | } else { 25 | [_indefiniteAnimatedLayer removeFromSuperlayer]; 26 | _indefiniteAnimatedLayer = nil; 27 | } 28 | } 29 | 30 | - (void)layoutAnimatedLayer { 31 | CALayer *layer = self.indefiniteAnimatedLayer; 32 | [self.layer addSublayer:layer]; 33 | layer.position = CGPointMake(CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds) / 2, CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds) / 2); 34 | } 35 | 36 | - (CAShapeLayer*)indefiniteAnimatedLayer { 37 | if(!_indefiniteAnimatedLayer) { 38 | CGPoint arcCenter = CGPointMake(self.radius+self.strokeThickness/2+5, self.radius+self.strokeThickness/2+5); 39 | CGRect rect = CGRectMake(0.0f, 0.0f, arcCenter.x*2, arcCenter.y*2); 40 | 41 | UIBezierPath* smoothedPath = [UIBezierPath bezierPathWithArcCenter:arcCenter 42 | radius:self.radius 43 | startAngle:M_PI*3/2 44 | endAngle:M_PI/2+M_PI*5 45 | clockwise:YES]; 46 | 47 | _indefiniteAnimatedLayer = [CAShapeLayer layer]; 48 | _indefiniteAnimatedLayer.contentsScale = [[UIScreen mainScreen] scale]; 49 | _indefiniteAnimatedLayer.frame = rect; 50 | _indefiniteAnimatedLayer.fillColor = [UIColor clearColor].CGColor; 51 | _indefiniteAnimatedLayer.strokeColor = self.strokeColor.CGColor; 52 | _indefiniteAnimatedLayer.lineWidth = self.strokeThickness; 53 | _indefiniteAnimatedLayer.lineCap = kCALineCapRound; 54 | _indefiniteAnimatedLayer.lineJoin = kCALineJoinBevel; 55 | _indefiniteAnimatedLayer.path = smoothedPath.CGPath; 56 | 57 | CALayer *maskLayer = [CALayer layer]; 58 | 59 | NSBundle *bundle = [NSBundle bundleForClass:self.class]; 60 | NSURL *url = [bundle URLForResource:@"SVProgressHUD" withExtension:@"bundle"]; 61 | NSBundle *imageBundle = [NSBundle bundleWithURL:url]; 62 | NSString *path = [imageBundle pathForResource:@"angle-mask" ofType:@"png"]; 63 | 64 | maskLayer.contents = (id)[[UIImage imageWithContentsOfFile:path] CGImage];; 65 | maskLayer.frame = _indefiniteAnimatedLayer.bounds; 66 | _indefiniteAnimatedLayer.mask = maskLayer; 67 | 68 | NSTimeInterval animationDuration = 1; 69 | CAMediaTimingFunction *linearCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 70 | 71 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; 72 | animation.fromValue = 0; 73 | animation.toValue = @(M_PI*2); 74 | animation.duration = animationDuration; 75 | animation.timingFunction = linearCurve; 76 | animation.removedOnCompletion = NO; 77 | animation.repeatCount = INFINITY; 78 | animation.fillMode = kCAFillModeForwards; 79 | animation.autoreverses = NO; 80 | [_indefiniteAnimatedLayer.mask addAnimation:animation forKey:@"rotate"]; 81 | 82 | CAAnimationGroup *animationGroup = [CAAnimationGroup animation]; 83 | animationGroup.duration = animationDuration; 84 | animationGroup.repeatCount = INFINITY; 85 | animationGroup.removedOnCompletion = NO; 86 | animationGroup.timingFunction = linearCurve; 87 | 88 | CABasicAnimation *strokeStartAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"]; 89 | strokeStartAnimation.fromValue = @0.015; 90 | strokeStartAnimation.toValue = @0.515; 91 | 92 | CABasicAnimation *strokeEndAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; 93 | strokeEndAnimation.fromValue = @0.485; 94 | strokeEndAnimation.toValue = @0.985; 95 | 96 | animationGroup.animations = @[strokeStartAnimation, strokeEndAnimation]; 97 | [_indefiniteAnimatedLayer addAnimation:animationGroup forKey:@"progress"]; 98 | 99 | } 100 | return _indefiniteAnimatedLayer; 101 | } 102 | 103 | - (void)setFrame:(CGRect)frame { 104 | if(!CGRectEqualToRect(frame, super.frame)){ 105 | [super setFrame:frame]; 106 | 107 | if (self.superview) { 108 | [self layoutAnimatedLayer]; 109 | } 110 | } 111 | 112 | } 113 | 114 | - (void)setRadius:(CGFloat)radius { 115 | if(radius != _radius){ 116 | _radius = radius; 117 | 118 | [_indefiniteAnimatedLayer removeFromSuperlayer]; 119 | _indefiniteAnimatedLayer = nil; 120 | 121 | if (self.superview) { 122 | [self layoutAnimatedLayer]; 123 | } 124 | } 125 | } 126 | 127 | - (void)setStrokeColor:(UIColor *)strokeColor { 128 | _strokeColor = strokeColor; 129 | _indefiniteAnimatedLayer.strokeColor = strokeColor.CGColor; 130 | } 131 | 132 | - (void)setStrokeThickness:(CGFloat)strokeThickness { 133 | _strokeThickness = strokeThickness; 134 | _indefiniteAnimatedLayer.lineWidth = _strokeThickness; 135 | } 136 | 137 | - (CGSize)sizeThatFits:(CGSize)size { 138 | return CGSizeMake((self.radius+self.strokeThickness/2+5)*2, (self.radius+self.strokeThickness/2+5)*2); 139 | } 140 | 141 | @end 142 | -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'SVProgressHUD' target in the 'SVProgressHUD' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/angle-mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/angle-mask.png -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/angle-mask@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/angle-mask@2x.png -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/angle-mask@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/angle-mask@3x.png -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/error.png -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/error@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/error@2x.png -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/error@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/error@3x.png -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/info.png -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/info@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/info@2x.png -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/info@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/info@3x.png -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/success.png -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/success@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/success@2x.png -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/success@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.bundle/success@3x.png -------------------------------------------------------------------------------- /CoreModel/APP/Common/CoreSVP/Lib/SVProgressHUD/SVProgressHUD.h: -------------------------------------------------------------------------------- 1 | // 2 | // SVProgressHUD.h 3 | // 4 | // Copyright 2011-2014 Sam Vermette. All rights reserved. 5 | // 6 | // https://github.com/samvermette/SVProgressHUD 7 | // 8 | 9 | #import 10 | #import 11 | 12 | extern NSString * const SVProgressHUDDidReceiveTouchEventNotification; 13 | extern NSString * const SVProgressHUDDidTouchDownInsideNotification; 14 | extern NSString * const SVProgressHUDWillDisappearNotification; 15 | extern NSString * const SVProgressHUDDidDisappearNotification; 16 | extern NSString * const SVProgressHUDWillAppearNotification; 17 | extern NSString * const SVProgressHUDDidAppearNotification; 18 | 19 | extern NSString * const SVProgressHUDStatusUserInfoKey; 20 | 21 | typedef NS_ENUM(NSUInteger, SVProgressHUDMaskType) { 22 | SVProgressHUDMaskTypeNone = 1, // allow user interactions while HUD is displayed 23 | SVProgressHUDMaskTypeClear, // don't allow user interactions 24 | SVProgressHUDMaskTypeBlack, // don't allow user interactions and dim the UI in the back of the HUD 25 | SVProgressHUDMaskTypeGradient // don't allow user interactions and dim the UI with a a-la-alert-view background gradient 26 | }; 27 | 28 | @interface SVProgressHUD : UIView 29 | 30 | #pragma mark - Customization 31 | 32 | + (void)setBackgroundColor:(UIColor*)color; // default is [UIColor whiteColor] 33 | + (void)setForegroundColor:(UIColor*)color; // default is [UIColor blackColor] 34 | + (void)setCornerRadius:(CGFloat)cornerRadius; // default is 14 pt 35 | + (void)setRingThickness:(CGFloat)width; // default is 4 pt 36 | + (void)setFont:(UIFont*)font; // default is [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline] 37 | + (void)setInfoImage:(UIImage*)image; // default is the bundled info image provided by Freepik 38 | + (void)setSuccessImage:(UIImage*)image; // default is the bundled success image provided by Freepik 39 | + (void)setErrorImage:(UIImage*)image; // default is the bundled error image provided by Freepik 40 | + (void)setDefaultMaskType:(SVProgressHUDMaskType)maskType; // default is SVProgressHUDMaskTypeNone 41 | + (void)setViewForExtension:(UIView*)view; // default is nil, only used if #define SV_APP_EXTENSIONS is set 42 | 43 | #pragma mark - Show Methods 44 | 45 | + (void)show; 46 | + (void)showWithMaskType:(SVProgressHUDMaskType)maskType; 47 | + (void)showWithStatus:(NSString*)status; 48 | + (void)showWithStatus:(NSString*)status maskType:(SVProgressHUDMaskType)maskType; 49 | 50 | + (void)showProgress:(float)progress; 51 | + (void)showProgress:(float)progress maskType:(SVProgressHUDMaskType)maskType; 52 | + (void)showProgress:(float)progress status:(NSString*)status; 53 | + (void)showProgress:(float)progress status:(NSString*)status maskType:(SVProgressHUDMaskType)maskType; 54 | 55 | + (void)setStatus:(NSString*)string; // change the HUD loading status while it's showing 56 | 57 | // stops the activity indicator, shows a glyph + status, and dismisses HUD a little bit later 58 | + (void)showInfoWithStatus:(NSString *)string; 59 | + (void)showInfoWithStatus:(NSString *)string maskType:(SVProgressHUDMaskType)maskType; 60 | 61 | + (void)showSuccessWithStatus:(NSString*)string; 62 | + (void)showSuccessWithStatus:(NSString*)string maskType:(SVProgressHUDMaskType)maskType; 63 | 64 | + (void)showErrorWithStatus:(NSString *)string; 65 | + (void)showErrorWithStatus:(NSString *)string maskType:(SVProgressHUDMaskType)maskType; 66 | 67 | // use 28x28 white pngs 68 | + (void)showImage:(UIImage*)image status:(NSString*)status; 69 | + (void)showImage:(UIImage*)image status:(NSString*)status maskType:(SVProgressHUDMaskType)maskType; 70 | 71 | + (void)setOffsetFromCenter:(UIOffset)offset; 72 | + (void)resetOffsetFromCenter; 73 | 74 | + (void)popActivity; // decrease activity count, if activity count == 0 the HUD is dismissed 75 | + (void)dismiss; 76 | 77 | + (BOOL)isVisible; 78 | 79 | 80 | 81 | 82 | 83 | /** 对HUB进行扩展 */ 84 | +(void)setDuration:(NSTimeInterval)duration; 85 | 86 | /** 完成时回调 */ 87 | +(void)setCompleteBlock:(void(^)())completeBlock; 88 | 89 | @end 90 | 91 | -------------------------------------------------------------------------------- /CoreModel/APP/List/ListTVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // ListTableView.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ListTVC : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreModel/APP/List/ListTVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // ListTableView.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "ListTVC.h" 10 | #import "Test2VC.h" 11 | #import "Test3VC.h" 12 | #import "Test4VC.h" 13 | #import "Test5VC.h" 14 | #import "Test6VC.h" 15 | #import "Test7VC.h" 16 | #import "Test8VC.h" 17 | #import "Test9VC.h" 18 | #import "Test10VC.h" 19 | #import "Test11VC.h" 20 | #import "Test12VC.h" 21 | #import "Test13VC.h" 22 | #import "Test14VC.h" 23 | #import "Test15VC.h" 24 | #import "Test16VC.h" 25 | #import "Test17VC.h" 26 | 27 | 28 | 29 | 30 | 31 | @interface ListTVC () 32 | 33 | @property (nonatomic,strong) NSArray *dataList; 34 | 35 | 36 | @end 37 | 38 | @implementation ListTVC 39 | 40 | - (void)viewDidLoad { 41 | [super viewDidLoad]; 42 | 43 | self.title = @"成都时点软件原创出品"; 44 | 45 | self.dataList = @[ 46 | 47 | @[[Test2VC class],@"子线程全自动创表"], 48 | @[[Test3VC class],@"无hostID自动处理"], 49 | @[[Test4VC class],@"基本模型 + 单条数据插入"], 50 | @[[Test5VC class],@"基本模型 + 批量数据插入"], 51 | @[[Test6VC class],@"基本模型 + 单条数据修改"], 52 | @[[Test7VC class],@"基本模型 + 批量数据修改"], 53 | @[[Test8VC class],@"基本模型 + 单条/批量/模糊保存"], 54 | @[[Test9VC class],@"基本模型 + 条件删除"], 55 | @[[Test10VC class],@"基本模型 + 条件查询"], 56 | @[[Test11VC class],@"基本模型 + 清空所有表记录"], 57 | @[[Test12VC class],@"NSData的支持"], 58 | @[[Test13VC class],@"属性为单模型级联:数据插入"], 59 | @[[Test14VC class],@"数组支持:基本类型数组"], 60 | @[[Test15VC class],@"数组支持:NSData类型数组"], 61 | @[[Test16VC class],@"数组支持:自定义模型数组"], 62 | @[[Test17VC class],@"大数量调整并发"], 63 | ]; 64 | 65 | } 66 | 67 | 68 | -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 69 | return self.dataList.count; 70 | 71 | 72 | } 73 | 74 | 75 | -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 76 | 77 | static NSString *ListTVCRid = @"ListTVC"; 78 | 79 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ListTVCRid]; 80 | 81 | if(cell == nil) cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ListTVCRid]; 82 | 83 | cell.textLabel.text = [NSString stringWithFormat:@"%@. %@",@(indexPath.row+1),((NSArray *)self.dataList[indexPath.row])[1]]; 84 | 85 | return cell; 86 | } 87 | 88 | 89 | -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 90 | 91 | Class Cls = ((NSArray *)self.dataList[indexPath.row])[0]; 92 | 93 | UIViewController *vc = [[Cls alloc] init]; 94 | vc.title = ((NSArray *)self.dataList[indexPath.row])[1]; 95 | 96 | [self.navigationController pushViewController:vc animated:YES]; 97 | } 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /CoreModel/APP/Model/City.h: -------------------------------------------------------------------------------- 1 | // 2 | // City.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CoreModel.h" 10 | 11 | @interface City : CoreModel 12 | 13 | @property (nonatomic,copy) NSString *cityName; 14 | 15 | @property (nonatomic,copy) NSString *spell; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /CoreModel/APP/Model/City.m: -------------------------------------------------------------------------------- 1 | // 2 | // City.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "City.h" 10 | 11 | @implementation City 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreModel/APP/Model/Pen.h: -------------------------------------------------------------------------------- 1 | // 2 | // Pen.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/10. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CoreModel.h" 10 | #import 11 | 12 | @interface Pen : CoreModel 13 | 14 | @property (nonatomic,copy) NSString *color; 15 | 16 | @property (nonatomic,assign) CGFloat price; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /CoreModel/APP/Model/Pen.m: -------------------------------------------------------------------------------- 1 | // 2 | // Pen.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/10. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "Pen.h" 10 | 11 | @implementation Pen 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreModel/APP/Model/Person.h: -------------------------------------------------------------------------------- 1 | // 2 | // Person.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CoreModel.h" 10 | #import "City.h" 11 | #import "Pen.h" 12 | #import 13 | 14 | @interface Person : CoreModel 15 | 16 | @property (nonatomic,copy) NSString *name; 17 | 18 | @property (nonatomic,assign) NSInteger age; 19 | 20 | @property (nonatomic,assign) CGFloat height; 21 | 22 | @property (nonatomic,strong) NSData *photoData; 23 | 24 | @property (nonatomic,strong) City *city; 25 | 26 | @property (nonatomic,strong) Person *teacher; 27 | 28 | @property (nonatomic,strong) NSArray *tags; 29 | 30 | @property (nonatomic,strong) NSArray *dreams; 31 | 32 | @property (nonatomic,strong) NSArray *pens; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /CoreModel/APP/Model/Person.m: -------------------------------------------------------------------------------- 1 | // 2 | // Person.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "Person.h" 10 | 11 | 12 | @implementation Person 13 | 14 | +(NSDictionary *)statementForNSArrayProperties{ 15 | return @{@"tags":NSStringFromClass([NSString class]),@"dreams":NSStringFromClass([NSData class]),@"pens":NSStringFromClass([Pen class])}; 16 | } 17 | 18 | +(NSDictionary *)objectClassInArray{ 19 | return @{@"tags":NSStringFromClass([NSString class]),@"pens":NSStringFromClass([Pen class])}; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test10VC.h: -------------------------------------------------------------------------------- 1 | // 2 | // Test10VC.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CommonVC.h" 10 | 11 | @interface Test10VC : CommonVC 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test10VC.m: -------------------------------------------------------------------------------- 1 | // 2 | // Test10VC.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "Test10VC.h" 10 | 11 | @interface Test10VC () 12 | 13 | @end 14 | 15 | @implementation Test10VC 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | [Person selectWhere:nil groupBy:nil orderBy:nil limit:nil selectResultsBlock:^(NSArray *selectResults) { 21 | 22 | NSString *msg = [NSString stringWithFormat:@"查到%@条记录",@(selectResults.count)]; 23 | 24 | CoreSVPSuccess(msg) 25 | 26 | NSLog(@"%@",selectResults); 27 | }]; 28 | 29 | 30 | 31 | } 32 | 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test11VC.h: -------------------------------------------------------------------------------- 1 | // 2 | // Test11VC.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CommonVC.h" 10 | 11 | @interface Test11VC : CommonVC 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test11VC.m: -------------------------------------------------------------------------------- 1 | // 2 | // Test11VC.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "Test11VC.h" 10 | 11 | @interface Test11VC () 12 | 13 | @end 14 | 15 | @implementation Test11VC 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | 21 | [Person truncateTable:^(BOOL res) { 22 | [self show:res]; 23 | }]; 24 | 25 | 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test12VC.h: -------------------------------------------------------------------------------- 1 | // 2 | // Test12VC.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CommonVC.h" 10 | 11 | @interface Test12VC : CommonVC 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test12VC.m: -------------------------------------------------------------------------------- 1 | // 2 | // Test12VC.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "Test12VC.h" 10 | 11 | @interface Test12VC () 12 | 13 | @property (weak, nonatomic) IBOutlet UIImageView *imageV; 14 | 15 | @property (weak, nonatomic) IBOutlet UILabel *label; 16 | 17 | @end 18 | 19 | @implementation Test12VC 20 | 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | 24 | } 25 | 26 | - (IBAction)saveModelAction:(id)sender { 27 | 28 | Person *charlin = [[Person alloc] init]; 29 | charlin.hostID = 1; 30 | charlin.name = @"冯成林"; 31 | charlin.age = 28; 32 | charlin.photoData = UIImagePNGRepresentation([UIImage imageNamed:@"1"]); 33 | 34 | [Person save:charlin resBlock:^(BOOL res) { 35 | [self show:res]; 36 | }]; 37 | } 38 | 39 | - (IBAction)readModelAction:(id)sender { 40 | 41 | __weak typeof(self) weakSelf=self; 42 | 43 | [Person find:1 selectResultBlock:^(Person *selectResult) { 44 | 45 | [weakSelf show:selectResult != nil]; 46 | 47 | dispatch_async(dispatch_get_main_queue(), ^{ 48 | 49 | weakSelf.imageV.image = [[UIImage alloc] initWithData:selectResult.photoData]; 50 | 51 | weakSelf.label.text = [NSString stringWithFormat:@"%@%@",selectResult.name,@(selectResult.age)]; 52 | }); 53 | 54 | }]; 55 | } 56 | 57 | 58 | 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test12VC.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 30 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test13VC.h: -------------------------------------------------------------------------------- 1 | // 2 | // Test13VC.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CommonVC.h" 10 | 11 | @interface Test13VC : CommonVC 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test13VC.m: -------------------------------------------------------------------------------- 1 | // 2 | // Test13VC.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "Test13VC.h" 10 | 11 | @interface Test13VC () 12 | 13 | @end 14 | 15 | @implementation Test13VC 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | City *city = [[City alloc] init]; 21 | city.hostID = 1; 22 | city.cityName = @"成都"; 23 | city.spell = @"ChengDu"; 24 | 25 | Person *p5 = [[Person alloc] init]; 26 | p5.hostID=5; 27 | p5.name = @"张三"; 28 | p5.city=city; 29 | [Person save:p5 resBlock:^(BOOL res) { 30 | 31 | [self show:res]; 32 | }]; 33 | 34 | } 35 | 36 | 37 | 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test14VC.h: -------------------------------------------------------------------------------- 1 | // 2 | // Test14VC.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CommonVC.h" 10 | 11 | @interface Test14VC : CommonVC 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test14VC.m: -------------------------------------------------------------------------------- 1 | // 2 | // Test14VC.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "Test14VC.h" 10 | 11 | @interface Test14VC () 12 | 13 | @end 14 | 15 | @implementation Test14VC 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | Person *p = [[Person alloc] init]; 21 | p.hostID=6; 22 | p.name = @"冯成林"; 23 | p.tags = @[@"工作狂",@"电影迷",@"成都范",@"梦想青年"]; 24 | 25 | [Person insert:p resBlock:^(BOOL res) { 26 | [self show:res]; 27 | }]; 28 | 29 | } 30 | 31 | 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test15VC.h: -------------------------------------------------------------------------------- 1 | // 2 | // Test15VC.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CommonVC.h" 10 | 11 | @interface Test15VC : CommonVC 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test15VC.m: -------------------------------------------------------------------------------- 1 | // 2 | // Test15VC.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "Test15VC.h" 10 | 11 | @interface Test15VC () 12 | 13 | @property (strong, nonatomic) IBOutletCollection(UIImageView) NSArray *imgVs; 14 | 15 | 16 | @end 17 | 18 | @implementation Test15VC 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | 23 | 24 | } 25 | 26 | 27 | - (IBAction)saveAction:(id)sender { 28 | 29 | Person *p = [[Person alloc] init]; 30 | p.hostID=7; 31 | p.name = @"大雄"; 32 | p.dreams = @[ 33 | [self dataWithImageName:@"p1"], 34 | [self dataWithImageName:@"p2"], 35 | [self dataWithImageName:@"p3"], 36 | ]; 37 | 38 | [Person save:p resBlock:^(BOOL res) { 39 | [self show:res]; 40 | }]; 41 | 42 | } 43 | 44 | - (IBAction)readAction:(id)sender { 45 | 46 | [Person find:7 selectResultBlock:^(Person *p) { 47 | 48 | 49 | CoreSVPSuccess(@"读取成功") 50 | 51 | [p.dreams enumerateObjectsUsingBlock:^(NSData *data, NSUInteger idx, BOOL *stop) { 52 | 53 | dispatch_async(dispatch_get_main_queue(), ^{ 54 | ((UIImageView *)self.imgVs[idx]).image = [[UIImage alloc] initWithData:data]; 55 | }); 56 | 57 | }]; 58 | 59 | 60 | }]; 61 | 62 | 63 | } 64 | 65 | 66 | -(NSData *)dataWithImageName:(NSString *)name{ 67 | return UIImagePNGRepresentation([UIImage imageNamed:name]); 68 | } 69 | 70 | 71 | 72 | 73 | 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test15VC.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 | 45 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test16VC.h: -------------------------------------------------------------------------------- 1 | // 2 | // Test16VC.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CommonVC.h" 10 | 11 | @interface Test16VC : CommonVC 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test16VC.m: -------------------------------------------------------------------------------- 1 | // 2 | // Test16VC.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "Test16VC.h" 10 | 11 | @interface Test16VC () 12 | 13 | @end 14 | 15 | @implementation Test16VC 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | Pen *pen1=[[Pen alloc] init]; 21 | pen1.hostID=1; 22 | pen1.color = @"red"; 23 | pen1.price = 12.5; 24 | Pen *pen2=[[Pen alloc] init]; 25 | pen2.hostID=2; 26 | pen2.color = @"blue"; 27 | pen2.price = 9.8; 28 | Person *p = [[Person alloc] init]; 29 | p.hostID = 8; 30 | p.name = @"静香"; 31 | p.pens=@[pen1,pen2]; 32 | 33 | 34 | [Person save:p resBlock:^(BOOL res) { 35 | [self show:res]; 36 | }]; 37 | } 38 | 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test17VC.h: -------------------------------------------------------------------------------- 1 | // 2 | // Test17VC.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 16/4/3. 6 | // Copyright © 2016年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "Test2VC.h" 10 | 11 | @interface Test17VC : Test2VC 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test17VC.m: -------------------------------------------------------------------------------- 1 | // 2 | // Test17VC.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 16/4/3. 6 | // Copyright © 2016年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "Test17VC.h" 10 | 11 | @implementation Test17VC 12 | 13 | 14 | 15 | - (void)viewDidLoad { 16 | [super viewDidLoad]; 17 | 18 | Person *person = [[Person alloc] init]; 19 | person.name = @"冯成林"; 20 | person.age = 28; 21 | person.height = 174.0; 22 | person.hostID = 100; 23 | 24 | __block NSInteger num = 0; 25 | 26 | for (NSUInteger i = 0; i< 100; i++) { 27 | 28 | [Person insert:person resBlock:^(BOOL res) { 29 | 30 | num++; 31 | }]; 32 | } 33 | 34 | } 35 | 36 | 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test2VC.h: -------------------------------------------------------------------------------- 1 | // 2 | // Test2VC.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CommonVC.h" 11 | 12 | @interface Test2VC : CommonVC 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test2VC.m: -------------------------------------------------------------------------------- 1 | // 2 | // Test2VC.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "Test2VC.h" 10 | 11 | 12 | @interface Test2VC () 13 | 14 | @end 15 | 16 | @implementation Test2VC 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | 21 | 22 | /** 全自动创表 */ 23 | Person *person = [[Person alloc] init]; 24 | 25 | } 26 | 27 | 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test3VC.h: -------------------------------------------------------------------------------- 1 | // 2 | // Test3VC.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CommonVC.h" 10 | 11 | @interface Test3VC : CommonVC 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test3VC.m: -------------------------------------------------------------------------------- 1 | // 2 | // Test3VC.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "Test3VC.h" 10 | 11 | @interface Test3VC () 12 | 13 | @end 14 | 15 | @implementation Test3VC 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | Person *person = [[Person alloc] init]; 21 | person.name = @"冯成林"; 22 | person.age = 28; 23 | person.height = 174.0; 24 | 25 | [Person insert:person resBlock:^(BOOL res) { 26 | 27 | [self show:res]; 28 | }]; 29 | 30 | } 31 | 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test4VC.h: -------------------------------------------------------------------------------- 1 | // 2 | // Test4VC.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CommonVC.h" 10 | 11 | @interface Test4VC : CommonVC 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test4VC.m: -------------------------------------------------------------------------------- 1 | // 2 | // Test4VC.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "Test4VC.h" 10 | 11 | @interface Test4VC () 12 | 13 | @end 14 | 15 | @implementation Test4VC 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | Person *person = [[Person alloc] init]; 21 | person.hostID = 12; 22 | person.name = @"冯成林"; 23 | person.age = 28; 24 | person.height = 174.0; 25 | 26 | /** Insert */ 27 | [Person insert:person resBlock:^(BOOL res) { 28 | 29 | [self show:res]; 30 | }]; 31 | 32 | } 33 | 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test5VC.h: -------------------------------------------------------------------------------- 1 | // 2 | // Test5VC.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CommonVC.h" 10 | 11 | @interface Test5VC : CommonVC 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test5VC.m: -------------------------------------------------------------------------------- 1 | // 2 | // Test5VC.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "Test5VC.h" 10 | 11 | @interface Test5VC () 12 | 13 | @end 14 | 15 | @implementation Test5VC 16 | 17 | 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | 22 | Person *p1 = [[Person alloc] init]; 23 | p1.hostID = 2; 24 | p1.name = @"jack"; 25 | p1.age = 25; 26 | p1.height = 180; 27 | 28 | Person *p2 = [[Person alloc] init]; 29 | p2.hostID = 3; 30 | p2.name = @"jim"; 31 | p2.age = 22; 32 | p2.height = 172; 33 | 34 | 35 | [Person inserts:@[p1,p2] resBlock:^(BOOL res) { 36 | [self show:res]; 37 | }]; 38 | } 39 | 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test6VC.h: -------------------------------------------------------------------------------- 1 | // 2 | // Test6VC.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CommonVC.h" 10 | 11 | @interface Test6VC : CommonVC 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test6VC.m: -------------------------------------------------------------------------------- 1 | // 2 | // Test6VC.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "Test6VC.h" 10 | 11 | @interface Test6VC () 12 | 13 | @end 14 | 15 | @implementation Test6VC 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | 21 | Person *person = [[Person alloc] init]; 22 | person.hostID = 1; 23 | person.name = @"Charlin Feng"; 24 | person.age = 28; 25 | person.height = 173.5; 26 | 27 | 28 | [Person update:person resBlock:^(BOOL res) { 29 | [self show:res]; 30 | }]; 31 | 32 | 33 | 34 | } 35 | 36 | 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test7VC.h: -------------------------------------------------------------------------------- 1 | // 2 | // Test7VC.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CommonVC.h" 10 | 11 | @interface Test7VC : CommonVC 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test7VC.m: -------------------------------------------------------------------------------- 1 | // 2 | // Test7VC.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "Test7VC.h" 10 | 11 | @interface Test7VC () 12 | 13 | @end 14 | 15 | @implementation Test7VC 16 | 17 | - (void)viewDidLoad { 18 | 19 | [super viewDidLoad]; 20 | 21 | Person *p1 = [[Person alloc] init]; 22 | p1.hostID = 2; 23 | p1.name = @"杰克"; 24 | p1.age = 25; 25 | p1.height = 180; 26 | 27 | Person *p2 = [[Person alloc] init]; 28 | p2.hostID = 3; 29 | p2.name = @"吉姆"; 30 | p2.age = 22; 31 | p2.height = 172; 32 | 33 | 34 | [Person updateModels:@[p1,p2] resBlock:^(BOOL res) { 35 | [self show:res]; 36 | }]; 37 | 38 | 39 | } 40 | 41 | 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test8VC.h: -------------------------------------------------------------------------------- 1 | // 2 | // Test8VC.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CommonVC.h" 10 | 11 | @interface Test8VC : CommonVC 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test8VC.m: -------------------------------------------------------------------------------- 1 | // 2 | // Test8VC.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "Test8VC.h" 10 | 11 | @interface Test8VC () 12 | 13 | @end 14 | 15 | @implementation Test8VC 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | Person *p1 = [[Person alloc] init]; 21 | p1.hostID = 2; 22 | p1.name = @"杰克先生"; 23 | p1.age = 40; 24 | p1.height = 180; 25 | 26 | Person *p2 = [[Person alloc] init]; 27 | p2.hostID = 3; 28 | p2.name = @"吉姆先生"; 29 | p2.age = 38; 30 | p2.height = 172; 31 | 32 | 33 | [Person saveModels:@[p1,p2] resBlock:^(BOOL res) { 34 | [self show:res]; 35 | }]; 36 | 37 | 38 | 39 | 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test9VC.h: -------------------------------------------------------------------------------- 1 | // 2 | // Test9VC.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CommonVC.h" 10 | 11 | @interface Test9VC : CommonVC 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreModel/APP/Modules/Test9VC.m: -------------------------------------------------------------------------------- 1 | // 2 | // Test9VC.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/9. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "Test9VC.h" 10 | 11 | @interface Test9VC () 12 | 13 | @end 14 | 15 | @implementation Test9VC 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | [Person deleteWhere:@"age >= 40" resBlock:^(BOOL res) { 21 | [self show:res]; 22 | }]; 23 | 24 | } 25 | 26 | 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /CoreModel/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 16/4/2. 6 | // Copyright © 2016年 冯成林. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /CoreModel/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 16/4/2. 6 | // Copyright © 2016年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /CoreModel/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /CoreModel/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /CoreModel/Assets.xcassets/p1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "p1.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /CoreModel/Assets.xcassets/p1.imageset/p1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/Assets.xcassets/p1.imageset/p1.png -------------------------------------------------------------------------------- /CoreModel/Assets.xcassets/p2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "p2.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /CoreModel/Assets.xcassets/p2.imageset/p2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/Assets.xcassets/p2.imageset/p2.png -------------------------------------------------------------------------------- /CoreModel/Assets.xcassets/p3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "p3.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /CoreModel/Assets.xcassets/p3.imageset/p3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlinFeng/CoreModel/587ec368f997bc24db654cdfe759fe956c358d9d/CoreModel/Assets.xcassets/p3.imageset/p3.png -------------------------------------------------------------------------------- /CoreModel/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 | 27 | 28 | -------------------------------------------------------------------------------- /CoreModel/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/CoreModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // CoreModel.h 3 | // 4s 4 | // 5 | // Created by muxi on 15/3/11. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CoreModelProtocol.h" 11 | #import "CorePageModelProtocol.h" 12 | #import "NSObject+Insert.h" 13 | #import "NSObject+Save.h" 14 | #import "NSObject+Delete.h" 15 | #import "NSObject+Update.h" 16 | #import "NSObject+Select.h" 17 | #import "NSObject+CoreModelCommon.h" 18 | 19 | 20 | @interface CoreModel : NSObject 21 | 22 | 23 | /** 服务器数据的ID:字符串化 */ 24 | @property (nonatomic,assign) NSInteger hostID; 25 | 26 | 27 | /** 父级模型名称:此属性用于完成级联添加以及查询,框架将自动处理,请不要手动修改! */ 28 | @property (nonatomic,copy,readonly) NSString *pModel; 29 | 30 | 31 | /** 父模型的hostID:此属性用于完成级联添加以及查询,框架将自动处理,请不要手动修改! */ 32 | @property (nonatomic,assign,readonly) NSInteger pid; 33 | 34 | 35 | 36 | 37 | 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/CoreModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // CoreModel.m 3 | // 4s 4 | // 5 | // Created by muxi on 15/3/11. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import "CoreModel.h" 10 | #import "NSObject+Create.h" 11 | 12 | 13 | @implementation CoreModel 14 | 15 | 16 | +(void)initialize{ 17 | 18 | if([[self modelName] isEqualToString:@"CoreModel"]) return; 19 | 20 | if(![self CoreModel_NeedFMDB]) return; 21 | 22 | //自动创表 23 | [self tableCreate]; 24 | } 25 | 26 | 27 | +(NSDictionary *)replacedKeyFromPropertyName{ 28 | return @{@"hostID":@"id"}; 29 | } 30 | 31 | 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSArray/NSArray+CoreModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+CoreModel.h 3 | // CoreClass 4 | // 5 | // Created by 成林 on 15/9/1. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSArray (CoreModel) 12 | 13 | @property (nonatomic,copy,readonly) NSString *toString; 14 | 15 | @property (nonatomic,strong,readonly) NSArray *descSortedArray; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSArray/NSArray+CoreModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+CoreModel.m 3 | // CoreClass 4 | // 5 | // Created by 成林 on 15/9/1. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import "NSArray+CoreModel.h" 10 | #import "CoreModelConst.h" 11 | #import "CoreModel.h" 12 | 13 | @implementation NSArray (CoreModel) 14 | 15 | -(NSString *)toString{ 16 | 17 | __block NSMutableString *strM = [NSMutableString string]; 18 | 19 | __block NSInteger length = 0; 20 | 21 | [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 22 | 23 | if([obj isKindOfClass:[NSString class]]){ 24 | 25 | if(length == 0) length = 1; 26 | 27 | [strM appendFormat:@"%@,",obj]; 28 | 29 | }else if ([obj isKindOfClass:[NSData class]]){ 30 | 31 | if(length == 0) length = SymbolString.length; 32 | 33 | [strM appendFormat:@"%@%@",[(NSData *)obj base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength],SymbolString]; 34 | } 35 | 36 | 37 | 38 | }]; 39 | 40 | return [[strM substringToIndex:strM.length-length] copy]; 41 | } 42 | 43 | -(NSArray *)descSortedArray{ 44 | 45 | NSArray *sortedArray = [self sortedArrayUsingComparator:^NSComparisonResult(CoreModel *m1, CoreModel *m2) { 46 | 47 | if (m1.hostIDm2.hostID) return NSOrderedAscending; 49 | return NSOrderedSame; 50 | }]; 51 | 52 | return sortedArray; 53 | } 54 | 55 | 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSDictionary/NSDictionary+Sqlite.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+Sqlite.h 3 | // CoreClass 4 | // 5 | // Created by 冯成林 on 15/5/28. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSDictionary (Sqlite) 12 | 13 | @property (nonatomic,copy,readonly) NSString *sqlWhere; 14 | 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSDictionary/NSDictionary+Sqlite.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+Sqlite.m 3 | // CoreClass 4 | // 5 | // Created by 冯成林 on 15/5/28. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import "NSDictionary+Sqlite.h" 10 | 11 | @implementation NSDictionary (Sqlite) 12 | 13 | 14 | /** 15 | * 字典转为sql条件中的where条件字符串 16 | */ 17 | -(NSString *)sqlWhere{ 18 | 19 | if(![self isKindOfClass:[NSDictionary class]] || self.count == 0) return nil; 20 | 21 | NSMutableString *strM=[NSMutableString string]; 22 | 23 | [self enumerateKeysAndObjectsUsingBlock:^(NSString *key,NSString *obj, BOOL *stop) { 24 | 25 | if([key isEqualToString:@"id"]) key=@"mid"; 26 | 27 | if([obj isKindOfClass:[NSString class]]){ 28 | [strM appendFormat:@"%@='%@' and ",key,obj]; 29 | }else{ 30 | [strM appendFormat:@"%@=%@ and ",key,obj]; 31 | } 32 | }]; 33 | 34 | //删除最后的 and 35 | NSString *where= [strM substringToIndex:strM.length-5]; 36 | 37 | return where; 38 | } 39 | 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSObject/CoreModel+Cache.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Cache.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/10. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CoreModel.h" 11 | #import "CoreModelType.h" 12 | 13 | @interface CoreModel (Cache) 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSObject/CoreModel+Cache.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Cache.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 15/9/10. 6 | // Copyright (c) 2015年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CoreModel+Cache.h" 10 | 11 | @implementation CoreModel (Cache) 12 | 13 | /** 模型对比时需要忽略的字段 */ 14 | +(NSArray *)constrastIgnorFields{ 15 | return @[@"pModel",@"pid"]; 16 | } 17 | 18 | /** 是否需要本地缓存:此处为CoreModel本身 */ 19 | +(BOOL)CoreModel_NeedFMDB{return YES;} 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSObject/NSObject+CoreModelCommon.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+CoreModelCommon.h 3 | // CoreModel 4 | // 5 | // Created by muxi on 15/3/30. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NSString+Stackoverflow.h" 11 | #import "NSOperationQueue+Queue.h" 12 | #import "CoreProperty.h" 13 | 14 | 15 | @interface NSObject (CoreModelCommon) 16 | 17 | 18 | +(NSString *)fieldSql:(CoreProperty *)ivar; 19 | 20 | +(BOOL)skipField:(CoreProperty *)ivar; 21 | 22 | + (NSArray *)ignoredPropertyNamesForSqlTransform; 23 | 24 | +(NSString *)deleteLastChar:(NSString *)str; 25 | 26 | +(BOOL)checkTableExists; 27 | 28 | +(void)checkUsage:(id)model; 29 | 30 | +(NSString *)sqliteType:(NSString *)fieldType; 31 | 32 | +(NSString *)modelName; 33 | 34 | +(BOOL)isBasicTypeInNSArray:(CoreProperty *)property; 35 | 36 | /** 模型对比时需要忽略的字段 */ 37 | +(NSArray *)constrastIgnorFields; 38 | 39 | /** 当模型中含有NSArray数组成员属性时,需要明确指明NSArray内部数据类型key:属性名,value: 数据类型NSString版 */ 40 | +(NSDictionary *)statementForNSArrayProperties; 41 | 42 | /** 封装 */ 43 | +(void)enumNSObjectProperties:(void(^)(CoreProperty *property, BOOL *stop))properties; 44 | 45 | 46 | 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSObject/NSObject+CoreModelCommon.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+CoreModelCommon.m 3 | // CoreModel 4 | // 5 | // Created by muxi on 15/3/30. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import "NSObject+CoreModelCommon.h" 10 | #import "CoreModelConst.h" 11 | #import "CoreFMDB.h" 12 | #import "NSObject+Runtime.h" 13 | 14 | 15 | @implementation NSObject (CoreModelCommon) 16 | 17 | 18 | +(NSString *)fieldSql:(CoreProperty *)ivar{ 19 | 20 | NSString *fieldName = ivar.name; 21 | 22 | NSString *fieldType = ivar.code; 23 | 24 | NSString *sqliteTye=[self sqliteType:fieldType]; 25 | 26 | if([ivar.typeString isEqualToString:CoreNSArray]){ 27 | 28 | if([self isBasicTypeInNSArray:[self statementForNSArrayProperties][ivar.name]]){ 29 | sqliteTye = TEXT_TYPE; 30 | } 31 | } 32 | 33 | if([sqliteTye isEqualToString:EmptyString]){ 34 | 35 | return EmptyString; 36 | } 37 | 38 | NSString *fieldSql=[NSString stringWithFormat:@"%@ %@,",fieldName,sqliteTye]; 39 | 40 | return fieldSql; 41 | } 42 | 43 | 44 | +(BOOL)skipField:(CoreProperty *)ivar{ 45 | 46 | NSArray *ignoredPropertyNames = nil; 47 | if ([[self class] respondsToSelector:@selector(ignoredPropertyNamesForSqlTransform)]) { 48 | ignoredPropertyNames = [[self class] ignoredPropertyNamesForSqlTransform]; 49 | } 50 | BOOL skip=ignoredPropertyNames!=nil && [ignoredPropertyNames containsObject:ivar.name]; 51 | 52 | return skip; 53 | } 54 | 55 | 56 | + (NSArray *)ignoredPropertyNamesForSqlTransform{return @[@"hash",@"superclass",@"description",@"debugDescription"];} 57 | 58 | 59 | +(NSString *)sqliteType:(NSString *)fieldType{ 60 | 61 | NSDictionary *map=@{ 62 | INTEGER_TYPE:@[CoreNSInteger,CoreNSUInteger,CoreEnum_int,CoreBOOL], 63 | TEXT_TYPE:@[CoreNSString], 64 | REAL_TYPE:@[CoreCGFloat], 65 | BLOB_TYPE:@[CoreNSData] 66 | }; 67 | 68 | __block NSString *sqliteType=EmptyString; 69 | 70 | [map enumerateKeysAndObjectsUsingBlock:^(NSString *blockSqliteType, NSArray *blockFieldTypes, BOOL *stop) { 71 | 72 | [blockFieldTypes enumerateObjectsUsingBlock:^(NSString *typeStringConst, NSUInteger idx, BOOL *stop) { 73 | 74 | NSRange range = [typeStringConst rangeOfString:fieldType]; 75 | 76 | if(range.length>0){ 77 | sqliteType = blockSqliteType; 78 | } 79 | }]; 80 | }]; 81 | 82 | return sqliteType; 83 | } 84 | 85 | 86 | +(BOOL)checkTableExists{ 87 | 88 | NSString *alias=@"tableCount"; 89 | 90 | NSString *sql=[NSString stringWithFormat:@"SELECT COUNT(*) %@ FROM sqlite_master WHERE type='table' AND name='%@';",alias,[self modelName]]; 91 | 92 | __block BOOL res=NO; 93 | 94 | [CoreFMDB executeQuery:sql queryResBlock:^(FMResultSet *set) { 95 | 96 | while ([set next]) { 97 | 98 | NSUInteger count = [[set stringForColumn:alias] integerValue]; 99 | 100 | res=count==1; 101 | } 102 | }]; 103 | 104 | return res; 105 | } 106 | 107 | 108 | +(void)checkUsage:(id)model{ 109 | NSAssert([NSStringFromClass(self) isEqualToString:NSStringFromClass([model class])], @"错误:请使用模型%@所属类(而不是%@类)的静态方法来执行您的操作",NSStringFromClass([model class]),NSStringFromClass(self)); 110 | } 111 | 112 | 113 | +(NSString *)deleteLastChar:(NSString *)str{ 114 | if(str.length == 0) return @""; 115 | return [str substringToIndex:str.length - 1]; 116 | } 117 | 118 | 119 | +(BOOL)isBasicTypeInNSArray:(NSString *)statement{ 120 | 121 | return [NSArrayNorlMalTypes containsObject:statement]; 122 | } 123 | 124 | 125 | 126 | +(NSString *)modelName{ 127 | return [NSStringFromClass(self) componentsSeparatedByString:@"."].lastObject; 128 | } 129 | 130 | 131 | +(NSDictionary *)statementForNSArrayProperties{return nil;} 132 | 133 | 134 | //-(NSString *)description{ 135 | // 136 | // NSMutableString *strM = [NSMutableString stringWithString:[NSString stringWithFormat:@"[%@]<%p>: \r",NSStringFromClass([self class]), self]]; 137 | // 138 | // [[self class] enumNSObjectProperties:^(CoreProperty *property, BOOL *stop) { 139 | // BOOL skip=[[self class] skipField:property]; 140 | // 141 | // if(!skip){ 142 | // [strM appendFormat:@" %@: %@, \r",property.name, [self valueForKeyPath:property.name]]; 143 | // } 144 | // }]; 145 | // 146 | // return [strM copy]; 147 | //} 148 | 149 | 150 | /** 封装 */ 151 | 152 | +(void)enumNSObjectProperties:(void(^)(CoreProperty *property, BOOL *stop))properties{ 153 | [self enumeratePropertiesUsingBlock:^(CoreProperty *p) { 154 | 155 | properties(p,NO); 156 | 157 | }]; 158 | } 159 | 160 | @end 161 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSObject/NSObject+Create.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Create.h 3 | // CoreModel 4 | // 5 | // Created by muxi on 15/3/30. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 创表 8 | 9 | #import 10 | 11 | @interface NSObject (Create) 12 | 13 | 14 | +(void)tableCreate; 15 | 16 | 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSObject/NSObject+Create.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Create.m 3 | // CoreModel 4 | // 5 | // Created by muxi on 15/3/30. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import "NSObject+Create.h" 10 | #import "NSObject+CoreModelCommon.h" 11 | #import "CoreModelConst.h" 12 | #import "CoreFMDB.h" 13 | 14 | 15 | @implementation NSObject (Create) 16 | 17 | 18 | +(void)tableCreate{ 19 | 20 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 21 | [self tableCreate_thread]; 22 | }); 23 | } 24 | 25 | 26 | 27 | +(void)tableCreate_thread{ 28 | 29 | NSString *modelName = [self modelName]; 30 | 31 | if([modelName isEqualToString:@"CoreModel"]) return; 32 | 33 | NSMutableString *sql=[NSMutableString string]; 34 | 35 | [sql appendFormat:@"CREATE TABLE IF NOT EXISTS %@ (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL DEFAULT 0,",modelName]; 36 | 37 | NSMutableArray *ivarsM=[NSMutableArray array]; 38 | 39 | [self enumNSObjectProperties:^(CoreProperty *property, BOOL *stop) { 40 | 41 | NSString *sql_field = [self fieldSql:property]; 42 | 43 | if([property.typeString isEqualToString:CoreNSArray]){ 44 | 45 | NSDictionary *dict = [self statementForNSArrayProperties]; 46 | 47 | NSString *errorMsg = [NSString stringWithFormat:@"错误:请在%@类中为您的NSArray类型的%@属性增加说明信息,实现statementForNSArrayProperties静态方法!",[self modelName],property.name]; 48 | 49 | NSAssert(dict[property.name] != nil, errorMsg); 50 | NSAssert(![dict[property.name] isEqualToString:@"NSInteger"], @"错误:OC数组内不可能存放NSInteger"); 51 | NSAssert(![dict[property.name] isEqualToString:@"NSUInteger"], @"错误:OC数组内不可能存放NSUInteger"); 52 | NSAssert(![dict[property.name] isEqualToString:@"BOOL"], @"错误:OC数组内不可能存放BOOL"); 53 | NSAssert(![dict[property.name] isEqualToString:@"CGFloat"], @"错误:OC数组内不可能存放CGFloat"); 54 | NSAssert(![dict[property.name] isEqualToString:@"double"], @"错误:OC数组内不可能存放double"); 55 | 56 | 57 | if([self isBasicTypeInNSArray:[self statementForNSArrayProperties][property.name]]){ 58 | sql_field = [NSString stringWithFormat:@"%@ %@ ,",property.name,TEXT_TYPE]; 59 | } 60 | } 61 | 62 | BOOL skip=[self skipField:property]; 63 | 64 | if(![sql_field isEqualToString:EmptyString] && !skip){ 65 | 66 | [sql appendString:sql_field]; 67 | 68 | [ivarsM addObject:property]; 69 | } 70 | }]; 71 | 72 | NSString *subSql = [self deleteLastChar:sql]; 73 | 74 | NSString *sql_Create = [NSString stringWithFormat:@"%@);",subSql]; 75 | 76 | BOOL createRes = [CoreFMDB executeUpdate:sql_Create]; 77 | 78 | if(!createRes){ 79 | if(CoreModelDeBug) NSLog(@"%@ 创表失败",modelName); 80 | return; 81 | } 82 | if(CoreModelDeBug) NSLog(@"表创建完毕%@",[NSThread currentThread]); 83 | 84 | [self fieldsCheck:modelName ivars:ivarsM]; 85 | 86 | ThreadShow(创表) 87 | } 88 | 89 | +(void)fieldsCheck:(NSString *)table ivars:(NSArray *)ivars{ 90 | 91 | ThreadShow(字段检查) 92 | 93 | NSArray *columns=[CoreFMDB executeQueryColumnsInTable:table]; 94 | 95 | NSMutableArray *columnsM=[NSMutableArray arrayWithArray:columns]; 96 | [columnsM removeObject:@"id"]; 97 | if(CoreModelDeBug) NSLog(@"字段也检查完毕%@",[NSThread currentThread]); 98 | 99 | if(columnsM.count>=ivars.count) return; 100 | 101 | for (CoreProperty *ivar in ivars) { 102 | 103 | if([columnsM containsObject:ivar.name]) continue; 104 | 105 | NSMutableString *sql_addM=[NSMutableString stringWithFormat:@"ALTER TABLE '%@' ADD COLUMN %@",table,[self fieldSql:ivar]]; 106 | 107 | NSString *sql_add=[self deleteLastChar:sql_addM]; 108 | 109 | NSString *sql=[NSString stringWithFormat:@"%@;",sql_add]; 110 | 111 | BOOL addRes = [CoreFMDB executeUpdate:sql]; 112 | 113 | if(!addRes){ 114 | if(CoreModelDeBug) NSLog(@"模型%@字段新增失败!",table); 115 | return; 116 | } 117 | 118 | if(CoreModelDeBug) NSLog(@"注意:模型 %@ 有新增加的字段 %@,已经实时添加到数据库中!",table,ivar.name); 119 | } 120 | } 121 | 122 | 123 | @end 124 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSObject/NSObject+Delete.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Delete.h 3 | // CoreModel 4 | // 5 | // Created by muxi on 15/3/30. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 删除数据 8 | // 请在主线程中执行 9 | 10 | #import 11 | 12 | @interface NSObject (Delete) 13 | 14 | 15 | +(void)deleteWhere:(NSString *)where resBlock:(void(^)(BOOL res))resBlock; 16 | 17 | 18 | +(void)delete:(NSUInteger)hostID resBlock:(void(^)(BOOL res))resBlock; 19 | 20 | 21 | +(void)truncateTable:(void(^)(BOOL res))resBlock; 22 | 23 | 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSObject/NSObject+Delete.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Delete.m 3 | // CoreModel 4 | // 5 | // Created by muxi on 15/3/30. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import "NSObject+Delete.h" 10 | #import "NSObject+CoreModelCommon.h" 11 | #import "CoreFMDB.h" 12 | #import "NSObject+Select.h" 13 | #import "CoreModel.h" 14 | #import "CoreModelConst.h" 15 | 16 | @implementation NSObject (Delete) 17 | 18 | 19 | +(void)deleteWhere:(NSString *)where resBlock:(void(^)(BOOL res))resBlock{ 20 | [self deleteWhere:where resBlock:resBlock needThread:YES]; 21 | } 22 | 23 | 24 | +(void)deleteWhere:(NSString *)where resBlock:(void(^)(BOOL res))resBlock needThread:(BOOL)needThread{ 25 | 26 | if(needThread){ 27 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 28 | [self deleteWhereAction:where resBlock:resBlock]; 29 | }); 30 | }else{ 31 | [self deleteWhereAction:where resBlock:resBlock]; 32 | } 33 | } 34 | 35 | +(void)deleteWhereAction:(NSString *)where resBlock:(void(^)(BOOL res))resBlock{ 36 | 37 | if(![self checkTableExists]){ 38 | 39 | if(CoreModelDeBug) NSLog(@"错误:你操作的模型%@在数据库中没有对应的数据表!%@",[self modelName],AutoMsg); 40 | if(resBlock != nil) resBlock(NO); 41 | return; 42 | } 43 | 44 | NSString *sql=[NSString stringWithFormat:@"DELETE FROM %@",[self modelName]]; 45 | 46 | if(where != nil) sql = [NSString stringWithFormat:@"%@ WHERE %@",sql,where]; 47 | 48 | sql = [NSString stringWithFormat:@"%@;",sql]; 49 | 50 | [self selectWhere:where groupBy:nil orderBy:nil limit:nil selectResultsBlock:^(NSArray *deleteModels) { 51 | if(deleteModels==nil || deleteModels.count==0){ 52 | if (resBlock != nil) resBlock(YES);return; 53 | } 54 | 55 | for (CoreModel *baseModle in deleteModels) { 56 | 57 | [baseModle.class enumNSObjectProperties:^(CoreProperty *property, BOOL *stop) { 58 | 59 | BOOL skip=[self skipField:property]; 60 | 61 | if(!skip){ 62 | 63 | NSString *sqliteTye=[self sqliteType:property.code]; 64 | 65 | if([property.typeString isEqualToString:CoreNSArray]){ 66 | 67 | if([self isBasicTypeInNSArray:[self statementForNSArrayProperties][property.name]]){ 68 | sqliteTye = TEXT_TYPE; 69 | } 70 | } 71 | 72 | 73 | if([sqliteTye isEqualToString:EmptyString]){ 74 | 75 | if([property.typeString isEqualToString:CoreNSArray]){ 76 | 77 | NSArray *CoreModels = (NSArray *)[baseModle valueForKeyPath:property.name]; 78 | 79 | [CoreModels enumerateObjectsUsingBlock:^(CoreModel *sub, NSUInteger idx, BOOL *stop) { 80 | 81 | NSString *where=[NSString stringWithFormat:@"pModel='%@' AND pid=%@",NSStringFromClass(sub.class),@(sub.hostID)]; 82 | 83 | [[sub class] deleteWhere:where resBlock:resBlock]; 84 | }]; 85 | 86 | }else{ 87 | 88 | Class ModelClass=NSClassFromString(property.code); 89 | 90 | NSString *where=[NSString stringWithFormat:@"pModel='%@' AND pid=%@",NSStringFromClass(baseModle.class),@(baseModle.hostID)]; 91 | 92 | [ModelClass deleteWhere:where resBlock:resBlock]; 93 | } 94 | 95 | } 96 | } 97 | }]; 98 | } 99 | 100 | BOOL res = [CoreFMDB executeUpdate:sql]; 101 | 102 | if(CoreModelDeBug) {if(!res) NSLog(@"错误:执行删除失败,sql语句为:%@",sql);}; 103 | 104 | ThreadShow(删除数据) 105 | 106 | TriggerBlock(resBlock, res) 107 | }]; 108 | } 109 | 110 | 111 | 112 | +(void)delete:(NSUInteger)hostID resBlock:(void(^)(BOOL res))resBlock{ 113 | 114 | NSString *where=[NSString stringWithFormat:@"hostID=%@",@(hostID)]; 115 | 116 | [self deleteWhere:where resBlock:resBlock needThread:YES]; 117 | } 118 | 119 | +(void)truncateTable:(void(^)(BOOL res))resBlock{ 120 | 121 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 122 | if(![self checkTableExists]){ 123 | 124 | if(CoreModelDeBug) NSLog(@"错误:你操作的模型%@在数据库中没有对应的数据表!%@",[self modelName],AutoMsg); 125 | if(resBlock != nil) resBlock(NO); 126 | return; 127 | } 128 | 129 | BOOL res = [CoreFMDB truncateTable:[self modelName]]; 130 | 131 | TriggerBlock(resBlock, res) 132 | }); 133 | 134 | } 135 | 136 | @end 137 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSObject/NSObject+Insert.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Insert.h 3 | // CoreModel 4 | // 5 | // Created by muxi on 15/3/30. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | 8 | 9 | #import 10 | 11 | @interface NSObject (Insert) 12 | 13 | 14 | +(void)insert:(id)model resBlock:(void(^)(BOOL res))resBlock; 15 | 16 | 17 | +(void)inserts:(NSArray *)models resBlock:(void(^)(BOOL res))resBlock; 18 | 19 | 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSObject/NSObject+Insert.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Insert.m 3 | // CoreModel 4 | // 5 | // Created by muxi on 15/3/30. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import "NSObject+Insert.h" 10 | #import "CoreModel.h" 11 | #import "NSObject+CoreModelCommon.h" 12 | #import "CoreModelConst.h" 13 | #import "CoreFMDB.h" 14 | #import "NSObject+Select.h" 15 | #import "NSArray+CoreModel.h" 16 | #import "CoreProperty.h" 17 | 18 | @implementation NSObject (Insert) 19 | 20 | 21 | 22 | 23 | +(void)insertAction:(id)model resBlock:(void(^)(BOOL res))resBlock { 24 | 25 | [self checkUsage:model]; 26 | 27 | if(![self checkTableExists]){ 28 | 29 | if(CoreModelDeBug) NSLog(@"注意:单条数据插入时,你操作的模型%@在数据库中没有对应的数据表!%@",[self modelName],AutoMsg); 30 | 31 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(AutoTry * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 32 | [self insertAction:model resBlock:resBlock]; 33 | }); 34 | 35 | return; 36 | } 37 | 38 | CoreModel *coreModel=(CoreModel *)model; 39 | 40 | if (coreModel.hostID == 0){ 41 | 42 | NSLog(@"错误:数据插入失败,无hostID的数据插入都是耍流氓,你必须设置模型的模型hostID!框架自动生成合理的hostID,不过模型含有服务器的hostID将更可可靠,否则或能出现大量重复数据。"); 43 | 44 | [self selectWhere:nil groupBy:nil orderBy:@"hostID desc" limit:@"0,1" selectResultsBlock:^(NSArray *selectResults) { 45 | 46 | if (selectResults.count == 0) { 47 | 48 | coreModel.hostID = 1; 49 | 50 | }else { 51 | 52 | CoreModel *lastCoreModel = (CoreModel *)selectResults.lastObject; 53 | 54 | coreModel.hostID = lastCoreModel.hostID + 1; 55 | } 56 | 57 | [self insertAction_Real:model resBlock:resBlock]; 58 | }]; 59 | 60 | }else{ 61 | 62 | [self insertAction_Real:model resBlock:resBlock]; 63 | } 64 | } 65 | 66 | +(void)insertAction_Real:(id)model resBlock:(void(^)(BOOL res))resBlock { 67 | 68 | CoreModel *coreModel=(CoreModel *)model; 69 | 70 | if(CoreModelDeBug) NSLog(@"数据插入开始%@",[NSThread currentThread]); 71 | 72 | [self find:coreModel.hostID selectResultBlock:^(id dbModel) { 73 | 74 | if(dbModel!=nil){ 75 | 76 | if(CoreModelDeBug) NSLog(@"错误:%@表中hostID=%@的数据记录已经存在!",[self modelName],@(coreModel.hostID)); 77 | [self deleteModel:model]; 78 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 79 | [self insertAction_Real:model resBlock:resBlock]; 80 | }); 81 | if(resBlock != nil) resBlock(NO);return; 82 | } 83 | 84 | NSMutableString *fields=[NSMutableString string]; 85 | NSMutableString *values=[NSMutableString string]; 86 | 87 | [self enumNSObjectProperties:^(CoreProperty *property, BOOL *stop) { 88 | 89 | BOOL skip=[self skipField:property]; 90 | 91 | if(!skip){ 92 | 93 | NSString *sqliteTye=[self sqliteType:property.code]; 94 | 95 | id value =[model valueForKeyPath:property.name]; 96 | 97 | if([property.typeString isEqualToString:CoreNSArray]){ 98 | 99 | if([self isBasicTypeInNSArray:[self statementForNSArrayProperties][property.name]]){ 100 | sqliteTye = TEXT_TYPE; 101 | } 102 | } 103 | 104 | if(![sqliteTye isEqualToString:EmptyString]){ 105 | 106 | [fields appendFormat:@"%@,",property.name]; 107 | 108 | if([property.typeString isEqualToString:CoreNSString]){ 109 | 110 | if(value == nil) value=@""; 111 | 112 | value=[NSString stringWithFormat:@"'%@'",value]; 113 | 114 | }else if ([property.typeString isEqualToString:CoreNSData]){ 115 | 116 | if(value != nil) { 117 | 118 | value =[NSString stringWithFormat:@"'%@'",[(NSData *)value base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]]; 119 | }else{ 120 | value = @"''"; 121 | } 122 | } 123 | 124 | if([property.typeString isEqualToString:CoreNSArray]){ 125 | 126 | 127 | if([self isBasicTypeInNSArray:[self statementForNSArrayProperties][property.name]]){ 128 | 129 | NSString *valueStr = nil; 130 | 131 | if(value == nil){ 132 | valueStr = @""; 133 | }else{ 134 | valueStr = ((NSArray *)value).toString; 135 | } 136 | 137 | value = [NSString stringWithFormat:@"'%@'",valueStr]; 138 | } 139 | } 140 | 141 | if(value != nil) { 142 | [values appendFormat:@"%@,",value]; 143 | } 144 | 145 | }else{ 146 | 147 | if(property.name!=nil && value!=nil){ 148 | 149 | 150 | if(![property.typeString isEqualToString:CoreNSArray]){ 151 | 152 | CoreModel *childModel=(CoreModel *)value; 153 | 154 | [childModel setValue:[self modelName] forKey:@"pModel"]; 155 | 156 | [childModel setValue:@(coreModel.hostID) forKey:@"pid"]; 157 | 158 | [NSClassFromString(property.code) insert:value resBlock:resBlock]; 159 | 160 | }else{ 161 | 162 | if(![self isBasicTypeInNSArray:[self statementForNSArrayProperties][property.name]]){ 163 | 164 | NSArray *modelsArray = (NSArray *)value; 165 | [modelsArray enumerateObjectsUsingBlock:^(CoreModel *i, NSUInteger idx, BOOL *stop) { 166 | [i setValue:NSStringFromClass([self class]) forKeyPath:@"pModel"]; 167 | [i setValue:@(coreModel.hostID) forKeyPath:@"pid"]; 168 | }]; 169 | 170 | Class Cls = NSClassFromString([self statementForNSArrayProperties][property.name]); 171 | 172 | [Cls inserts:modelsArray resBlock:resBlock]; 173 | 174 | } 175 | } 176 | 177 | } 178 | } 179 | } 180 | }]; 181 | 182 | NSString *fields_sub=[self deleteLastChar:fields]; 183 | NSString *values_sub=[self deleteLastChar:values]; 184 | 185 | NSString *sql=[NSString stringWithFormat:@"INSERT INTO %@ (%@) VALUES (%@);",[self modelName],fields_sub,values_sub]; 186 | 187 | BOOL insertRes = [CoreFMDB executeUpdate:sql]; 188 | 189 | if(CoreModelDeBug) {if(!insertRes) NSLog(@"错误:添加对象失败%@",coreModel);}; 190 | if(CoreModelDeBug) NSLog(@"数据插入结束%@",[NSThread currentThread]); 191 | TriggerBlock(resBlock, insertRes) 192 | }]; 193 | } 194 | 195 | +(void)deleteModel:(id)model{ 196 | 197 | NSString *sql = [NSString stringWithFormat:@"DELETE FROM %@ WHERE hostID = %@",[self modelName],@([model hostID])]; 198 | 199 | [CoreFMDB executeUpdate:sql]; 200 | } 201 | 202 | 203 | +(void)insert:(id)model resBlock:(void(^)(BOOL res))resBlock newThread:(BOOL)newThread{ 204 | 205 | if (newThread){ 206 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 207 | [self insertAction:model resBlock:resBlock]; 208 | }); 209 | }else{ 210 | [self insertAction:model resBlock:resBlock]; 211 | } 212 | } 213 | 214 | +(void)insert:(id)model resBlock:(void(^)(BOOL res))resBlock{ 215 | [self insert:model resBlock:resBlock newThread:YES]; 216 | } 217 | 218 | 219 | +(void)inserts:(NSArray *)models resBlock:(void(^)(BOOL res))resBlock{ 220 | 221 | if(![self checkTableExists]){ 222 | 223 | if(CoreModelDeBug)NSLog(@"注意:批量数据插入时,你操作的模型%@在数据库中没有对应的数据表!%@",[self modelName],AutoMsg); 224 | 225 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(AutoTry * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 226 | [self inserts:models resBlock:resBlock]; 227 | }); 228 | 229 | return; 230 | } 231 | 232 | if(CoreModelDeBug)NSLog(@"表创建成功,开始批量数据插入!"); 233 | 234 | [self insertsActon:models resBlock:resBlock]; 235 | 236 | } 237 | 238 | +(void)insertsActon:(NSArray *)models resBlock:(void(^)(BOOL res))resBlock{ 239 | 240 | if(models == nil || models.count == 0){resBlock(NO);return;} 241 | 242 | if(![self checkTableExists]){ 243 | 244 | if(CoreModelDeBug) NSLog(@"注意:单条数据插入时,你操作的模型%@在数据库中没有对应的数据表!%@",[self modelName],AutoMsg); 245 | 246 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(AutoTry * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 247 | [self insertsActon:models resBlock:resBlock]; 248 | }); 249 | 250 | return; 251 | } 252 | 253 | NSOperationQueue *queue = [NSOperationQueue queue]; 254 | 255 | if(CoreModelDeBug)NSLog(@"批量插入开始%@",[NSThread currentThread]); 256 | 257 | for (CoreModel *CoreModel in models) { 258 | 259 | NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ 260 | [self insert:CoreModel resBlock:resBlock newThread:NO];ThreadShow(批量插入操作) 261 | }]; 262 | 263 | [queue addOperation:operation]; 264 | } 265 | } 266 | 267 | @end 268 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSObject/NSObject+Save.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Save.h 3 | // CoreModel 4 | // 5 | // Created by muxi on 15/3/30. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 保存数据,如果数据不存在,则执行添加操作;如果数据已经存在,则执行更新操作,总之数据一定会记录到数据库中并成为最新的数据记录。 8 | 9 | 10 | #import 11 | 12 | @interface NSObject (Save) 13 | 14 | 15 | 16 | 17 | +(void)save:(id)model resBlock:(void(^)(BOOL res))resBlock; 18 | 19 | 20 | 21 | +(void)saveModels:(NSArray *)models resBlock:(void(^)(BOOL res))resBlock; 22 | 23 | 24 | +(void)saveDirect:(id)obj resBlock:(void(^)(BOOL res))resBlock; 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSObject/NSObject+Save.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Save.m 3 | // CoreModel 4 | // 5 | // Created by muxi on 15/3/30. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import "NSObject+Save.h" 10 | #import "CoreModel.h" 11 | #import "NSObject+Select.h" 12 | #import "NSObject+CoreModelCommon.h" 13 | #import "NSObject+Insert.h" 14 | #import "NSObject+Update.h" 15 | #import "CoreModelConst.h" 16 | 17 | @implementation NSObject (Save) 18 | 19 | +(void)save:(id)model resBlock:(void(^)(BOOL res))resBlock{ 20 | [self save:model resBlock:resBlock needThread:YES]; 21 | } 22 | 23 | +(void)save:(id)model resBlock:(void(^)(BOOL res))resBlock needThread:(BOOL)needThread{ 24 | if (needThread) { 25 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 26 | [self saveAction:model resBlock:resBlock]; 27 | }); 28 | }else{ 29 | [self saveAction:model resBlock:resBlock]; 30 | } 31 | } 32 | 33 | +(void)saveAction:(id)model resBlock:(void(^)(BOOL res))resBlock{ 34 | 35 | [self checkUsage:model]; 36 | 37 | if(![self checkTableExists]){ 38 | if(CoreModelDeBug) NSLog(@"注意:你操作的模型%@在数据库中没有对应的数据表,%@",[self modelName],AutoMsg); 39 | 40 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(AutoTry * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 41 | [self saveAction:model resBlock:resBlock]; 42 | }); 43 | 44 | return; 45 | } 46 | 47 | if(![model isKindOfClass:[self class]]){ 48 | if(CoreModelDeBug) NSLog(@"错误:插入数据请使用%@模型类对象,您使用的是%@类型",[self modelName],[model class]); 49 | resBlock(NO);return; 50 | } 51 | 52 | CoreModel *coreModel = (CoreModel *)model; 53 | 54 | [self find:coreModel.hostID selectResultBlock:^(id selectResult) { 55 | 56 | if(selectResult==nil){ 57 | if(CoreModelDeBug)NSLog(@"现在是新增"); 58 | [self insert:coreModel resBlock:resBlock]; 59 | 60 | }else{ 61 | if(CoreModelDeBug)NSLog(@"现在是更新"); 62 | [self update:coreModel resBlock:resBlock]; 63 | } 64 | }]; 65 | } 66 | 67 | 68 | 69 | +(void)saveModels:(NSArray *)models resBlock:(void(^)(BOOL res))resBlock{ 70 | 71 | if(![self checkTableExists]){ 72 | 73 | if(CoreModelDeBug) NSLog(@"注意:单条数据保存时,你操作的模型%@在数据库中没有对应的数据表!%@",[self modelName],AutoMsg); 74 | 75 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(AutoTry * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 76 | [self saveModels:models resBlock:resBlock]; 77 | }); 78 | 79 | return; 80 | } 81 | 82 | 83 | if(models==nil || models.count==0) {if (resBlock !=nil) resBlock(NO);return;}; 84 | 85 | NSOperationQueue *queue = [NSOperationQueue queue]; 86 | 87 | [models enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 88 | 89 | NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{ 90 | [self save:obj resBlock:resBlock needThread:NO]; 91 | ThreadShow("批量保存") 92 | }]; 93 | [queue addOperation:op]; 94 | }]; 95 | } 96 | 97 | 98 | 99 | +(void)saveDirect:(id)obj resBlock:(void(^)(BOOL res))resBlock{ 100 | 101 | return [obj isKindOfClass:[NSArray class]]?[self saveModels:obj resBlock:resBlock]:[self save:obj resBlock:resBlock]; 102 | } 103 | 104 | 105 | @end 106 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSObject/NSObject+Select.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Select.h 3 | // CoreModel 4 | // 5 | // Created by muxi on 15/3/30. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 查询数据 8 | 9 | #import 10 | 11 | @interface NSObject (Select) 12 | 13 | 14 | 15 | +(void)selectWhere:(NSString *)where groupBy:(NSString *)groupBy orderBy:(NSString *)orderBy limit:(NSString *)limit selectResultsBlock:(void(^)(NSArray *selectResults))selectResultsBlock; 16 | 17 | 18 | +(void)find:(NSUInteger)hostID selectResultBlock:(void(^)(id selectResult))selectResultBlock; 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSObject/NSObject+Select.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Select.m 3 | // CoreModel 4 | // 5 | // Created by muxi on 15/3/30. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import "NSObject+Select.h" 10 | #import "CoreFMDB.h" 11 | #import "CoreModel.h" 12 | #import "NSObject+CoreModelCommon.h" 13 | #import "CoreModelConst.h" 14 | #import "NSString+Stackoverflow.h" 15 | 16 | @implementation NSObject (Select) 17 | 18 | 19 | +(void)selectWhere:(NSString *)where groupBy:(NSString *)groupBy orderBy:(NSString *)orderBy limit:(NSString *)limit selectResultsBlock:(void(^)(NSArray *selectResults))selectResultsBlock{ 20 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 21 | [self selectWhereAction:where groupBy:groupBy orderBy:orderBy limit:limit selectResultsBlock:selectResultsBlock]; 22 | }); 23 | } 24 | 25 | +(void)selectWhereAction:(NSString *)where groupBy:(NSString *)groupBy orderBy:(NSString *)orderBy limit:(NSString *)limit selectResultsBlock:(void(^)(NSArray *selectResults))selectResultsBlock{ 26 | 27 | 28 | if(![self checkTableExists]){ 29 | if(CoreModelDeBug) NSLog(@"错误:你操作的模型%@在数据库中没有对应的数据表!",[self modelName]); 30 | if(selectResultsBlock != nil) selectResultsBlock(nil);return; 31 | } 32 | 33 | if(CoreModelDeBug) NSLog(@"查询开始:%@",[NSThread currentThread]); 34 | 35 | NSMutableString *sqlM=[NSMutableString stringWithFormat:@"SELECT * FROM %@",[self modelName]]; 36 | 37 | if(where != nil) [sqlM appendFormat:@" WHERE %@",where]; 38 | 39 | if(groupBy != nil){[sqlM appendFormat:@" GROUP BY hostID,%@",groupBy];}else{[sqlM appendString:@" GROUP BY hostID"];}; 40 | 41 | if(orderBy != nil) [sqlM appendFormat:@" ORDER BY %@",orderBy]; 42 | 43 | if(limit != nil) [sqlM appendFormat:@" LIMIT %@",limit]; 44 | 45 | NSString *sql=[NSString stringWithFormat:@"%@;",sqlM]; 46 | 47 | NSMutableArray *resultsM=[NSMutableArray array]; 48 | 49 | NSMutableArray *fieldsArrayM=[NSMutableArray array]; 50 | 51 | [CoreFMDB executeQuery:sql queryResBlock:^(FMResultSet *set) { 52 | 53 | while ([set next]) { 54 | 55 | CoreModel *model=[[self alloc] init]; 56 | 57 | [self enumNSObjectProperties:^(CoreProperty *property, BOOL *stop) { 58 | 59 | BOOL skip=[self skipField:property]; 60 | 61 | if(!skip){ 62 | 63 | NSString *code = property.code; 64 | 65 | NSString *sqliteTye=[self sqliteType:code]; 66 | 67 | if([property.typeString isEqualToString:CoreNSArray]){ 68 | 69 | if([self isBasicTypeInNSArray:[self statementForNSArrayProperties][property.name]]){ 70 | sqliteTye = TEXT_TYPE; 71 | } 72 | } 73 | 74 | if(![sqliteTye isEqualToString:EmptyString]){ 75 | 76 | NSString *propertyName = property.name; 77 | NSString *value=[set stringForColumn:propertyName]; 78 | 79 | if([CoreBOOL rangeOfString:code].length>0){ 80 | 81 | NSNumber *boolValue = @(value.integerValue); 82 | 83 | [model setValue:boolValue forKey:propertyName]; 84 | 85 | }else{ 86 | 87 | if([code isEqualToString:CoreNSData]){ 88 | value = [[NSData alloc] initWithBase64EncodedString:value options:NSDataBase64DecodingIgnoreUnknownCharacters]; 89 | } 90 | 91 | [model setValue:value forKey:propertyName]; 92 | } 93 | 94 | 95 | if([property.typeString isEqualToString:CoreNSArray]){ 96 | 97 | if([self isBasicTypeInNSArray:[self statementForNSArrayProperties][property.name]]){ 98 | 99 | 100 | NSArray *normalArr = [value toArray:[[self statementForNSArrayProperties][property.name] isEqualToString:CoreNSString]]; 101 | 102 | [model setValue:normalArr forKey:propertyName]; 103 | } 104 | } 105 | 106 | }else{ 107 | if(![fieldsArrayM containsObject:property]) [fieldsArrayM addObject:property]; 108 | } 109 | } 110 | }]; 111 | 112 | [resultsM addObject:model]; 113 | } 114 | }]; 115 | 116 | __block BOOL hasChildrendArrayProperty = NO; 117 | 118 | if(fieldsArrayM.count!=0){ 119 | 120 | [resultsM enumerateObjectsUsingBlock:^(CoreModel *model, NSUInteger idx, BOOL *stop) { 121 | 122 | [fieldsArrayM enumerateObjectsUsingBlock:^(CoreProperty *ivar, NSUInteger idx, BOOL *stop) { 123 | 124 | if(![ivar.typeString isEqualToString:CoreNSArray]){ 125 | 126 | NSString *where_childModelField=[NSString stringWithFormat:@"pModel='%@' AND pid=%@",NSStringFromClass(model.class),@(model.hostID)]; 127 | 128 | NSString *limit=@"1"; 129 | 130 | [NSClassFromString(ivar.typeString) selectWhere:where_childModelField groupBy:nil orderBy:nil limit:limit selectResultsBlock:^(NSArray *selectResults) { 131 | 132 | if(selectResults.count>0){ 133 | [model setValue:selectResults.firstObject forKey:ivar.name]; 134 | } 135 | 136 | }]; 137 | 138 | }else{ 139 | 140 | hasChildrendArrayProperty = YES; 141 | 142 | NSString *where_childModelField=[NSString stringWithFormat:@"pModel='%@' AND pid=%@",NSStringFromClass(model.class),@(model.hostID)]; 143 | 144 | Class Cls = NSClassFromString([self statementForNSArrayProperties][ivar.name]); 145 | 146 | 147 | [Cls selectWhere:where_childModelField groupBy:nil orderBy:nil limit:nil selectResultsBlock:^(NSArray *selectResults) { 148 | 149 | if(selectResults.count>0){ 150 | [model setValue:selectResults forKey:ivar.name]; 151 | } 152 | 153 | if(selectResultsBlock != nil) selectResultsBlock(resultsM); 154 | 155 | }]; 156 | 157 | } 158 | 159 | }]; 160 | 161 | }]; 162 | } 163 | 164 | if(!hasChildrendArrayProperty){if(selectResultsBlock != nil) selectResultsBlock(resultsM);} 165 | 166 | ThreadShow(数据查询) 167 | } 168 | 169 | 170 | 171 | 172 | +(void)find:(NSUInteger)hostID selectResultBlock:(void(^)(id selectResult))selectResultBlock{ 173 | 174 | if(![self checkTableExists]){ 175 | 176 | if(CoreModelDeBug) NSLog(@"错误:你操作的模型%@在数据库中没有对应的数据表!",[self modelName]); 177 | if (selectResultBlock != nil) selectResultBlock(nil);return; 178 | } 179 | 180 | NSString *where=[NSString stringWithFormat:@"hostID=%@",@(hostID)]; 181 | 182 | NSString *limit=@"1"; 183 | 184 | [self selectWhere:where groupBy:nil orderBy:nil limit:limit selectResultsBlock:^(NSArray *selectResults) { 185 | 186 | if (selectResultBlock != nil) selectResultBlock(selectResults.firstObject); 187 | }]; 188 | 189 | } 190 | 191 | 192 | @end 193 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSObject/NSObject+Update.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Update.h 3 | // CoreModel 4 | // 5 | // Created by muxi on 15/3/30. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 更新数据:如果数据不存在,则自动忽略,不会自动添加 8 | // 请在线程中执行 9 | 10 | #import 11 | 12 | @interface NSObject (Update) 13 | 14 | 15 | 16 | +(void)update:(id)model resBlock:(void(^)(BOOL res))resBlock; 17 | 18 | +(void)updateModels:(NSArray *)models resBlock:(void(^)(BOOL res))resBlock; 19 | 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSObject/NSObject+Update.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Update.m 3 | // CoreModel 4 | // 5 | // Created by muxi on 15/3/30. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import "NSObject+Update.h" 10 | #import "NSObject+CoreModelCommon.h" 11 | #import "CoreModel.h" 12 | #import "CoreModelConst.h" 13 | #import "CoreFMDB.h" 14 | #import "NSArray+CoreModel.h" 15 | 16 | 17 | @implementation NSObject (Update) 18 | 19 | 20 | +(void)update:(id)model resBlock:(void(^)(BOOL res))resBlock{ 21 | [self update:model resBlock:resBlock needThead:YES]; 22 | } 23 | 24 | +(void)update:(id)model resBlock:(void(^)(BOOL res))resBlock needThead:(BOOL)needThead{ 25 | 26 | if (needThead) { 27 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 28 | [self updateAction:model resBlock:resBlock]; 29 | }); 30 | }else{ 31 | [self updateAction:model resBlock:resBlock]; 32 | } 33 | } 34 | 35 | 36 | +(void)updateAction:(id)model resBlock:(void(^)(BOOL res))resBlock{ 37 | 38 | [self checkUsage:model]; 39 | 40 | if(![self checkTableExists]){ 41 | 42 | if(CoreModelDeBug) NSLog(@"错误:你操作的模型%@在数据库中没有对应的数据表!",[self modelName]); 43 | 44 | if(resBlock != nil) resBlock(NO); 45 | 46 | return; 47 | } 48 | 49 | if(![model isKindOfClass:[self class]]){ 50 | if(CoreModelDeBug) NSLog(@"错误:插入数据请使用%@模型类对象,您使用的是%@类型",[self modelName],[model class]); 51 | if (resBlock != nil) resBlock(NO); 52 | } 53 | 54 | CoreModel *coreModel=(CoreModel *)model; 55 | 56 | [self find:coreModel.hostID selectResultBlock:^(id selectResult) { 57 | 58 | if(selectResult==nil) {if (resBlock != nil) resBlock(NO);return;}; 59 | 60 | NSMutableString *keyValueString=[NSMutableString string]; 61 | 62 | [self enumNSObjectProperties:^(CoreProperty *property, BOOL *stop) { 63 | 64 | BOOL skip=[self skipField:property]; 65 | 66 | if(!skip){ 67 | 68 | NSString *sqliteTye=[self sqliteType:property.code]; 69 | 70 | id value =[model valueForKeyPath:property.name]; 71 | 72 | if([property.typeString isEqualToString:CoreNSArray]){ 73 | 74 | if([self isBasicTypeInNSArray:[self statementForNSArrayProperties][property.name]]){ 75 | sqliteTye = TEXT_TYPE; 76 | } 77 | } 78 | 79 | if(![sqliteTye isEqualToString:EmptyString]){ 80 | 81 | if([property.typeString isEqualToString:CoreNSString]){ 82 | 83 | if(value == nil) value=@""; 84 | 85 | value=[NSString stringWithFormat:@"'%@'",value]; 86 | }else if ([property.typeString isEqualToString:CoreNSData]){ 87 | 88 | if(value != nil) { 89 | 90 | value =[NSString stringWithFormat:@"'%@'",[(NSData *)value base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]]; 91 | }else{ 92 | value = @"''"; 93 | } 94 | } 95 | 96 | if([property.typeString isEqualToString:CoreNSArray]){ 97 | 98 | if([self isBasicTypeInNSArray:[self statementForNSArrayProperties][property.name]]){ 99 | 100 | NSString *valueStr = nil; 101 | 102 | if(value == nil){ 103 | valueStr = @""; 104 | }else{ 105 | valueStr = ((NSArray *)value).toString; 106 | } 107 | 108 | value = [NSString stringWithFormat:@"'%@'",valueStr]; 109 | } 110 | } 111 | 112 | 113 | [keyValueString appendFormat:@"%@=%@,",property.name,value]; 114 | 115 | }else{ 116 | 117 | if(property.name!=nil && value!=nil){ 118 | 119 | if(![property.typeString isEqualToString:CoreNSArray]){ 120 | 121 | CoreModel *childModel=(CoreModel *)value; 122 | 123 | [childModel setValue:[self modelName] forKey:@"pModel"]; 124 | 125 | [childModel setValue:@(coreModel.hostID) forKey:@"pid"]; 126 | 127 | [NSClassFromString(property.code) update:childModel resBlock:^(BOOL res) { 128 | if(CoreModelDeBug) {if(!res) NSLog(@"错误:级联保存数据失败!级联父类:%@,子属性为:%@",NSStringFromClass(CoreModel.class),value);}; 129 | }]; 130 | 131 | }else{ 132 | 133 | 134 | NSArray *modelsArray = (NSArray *)value; 135 | 136 | [modelsArray enumerateObjectsUsingBlock:^(CoreModel *i, NSUInteger idx, BOOL *stop) { 137 | [i setValue:NSStringFromClass([self class]) forKeyPath:@"pModel"]; 138 | [i setValue:@(coreModel.hostID) forKeyPath:@"pid"]; 139 | }]; 140 | 141 | Class Cls = NSClassFromString([self statementForNSArrayProperties][property.name]); 142 | 143 | [Cls saveModels:modelsArray resBlock:resBlock]; 144 | } 145 | 146 | } 147 | } 148 | } 149 | 150 | }]; 151 | 152 | NSString *keyValues_sub=[self deleteLastChar:keyValueString]; 153 | 154 | NSString *sql=[NSString stringWithFormat:@"UPDATE %@ SET %@ WHERE hostID=%@;",[self modelName],keyValues_sub,@(coreModel.hostID)]; 155 | 156 | BOOL updateRes = [CoreFMDB executeUpdate:sql]; 157 | 158 | if(CoreModelDeBug) {if(!updateRes) NSLog(@"错误:数据更新出错,出错模型数据为:%@",model);}; 159 | 160 | TriggerBlock(resBlock, updateRes) 161 | 162 | }]; 163 | } 164 | 165 | 166 | 167 | +(void)updateModels:(NSArray *)models resBlock:(void(^)(BOOL res))resBlock{ 168 | 169 | if(![self checkTableExists]){ 170 | 171 | if(CoreModelDeBug) NSLog(@"注意:单条数据更新时,你操作的模型%@在数据库中没有对应的数据表!%@",[self modelName],AutoMsg); 172 | 173 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(AutoTry * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 174 | [self updateModels:models resBlock:resBlock]; 175 | }); 176 | 177 | return; 178 | } 179 | 180 | if(models==nil || models.count==0) {if (resBlock != nil) resBlock(NO);}; 181 | 182 | NSOperationQueue *queue = [NSOperationQueue queue]; 183 | 184 | for (id obj in models) { 185 | NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{ 186 | [self update:obj resBlock:resBlock needThead:NO];ThreadShow(更新数据) 187 | }]; 188 | [queue addOperation:op]; 189 | } 190 | } 191 | 192 | 193 | 194 | @end 195 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSOperationQueue/NSOperationQueue+Queue.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSOperationQueue+Queue.h 3 | // CoreClass 4 | // 5 | // Created by 成林 on 15/8/30. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSOperationQueue (Queue) 12 | 13 | 14 | +(instancetype)queue; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSOperationQueue/NSOperationQueue+Queue.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSOperationQueue+Queue.m 3 | // CoreClass 4 | // 5 | // Created by 成林 on 15/8/30. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import "NSOperationQueue+Queue.h" 10 | 11 | @implementation NSOperationQueue (Queue) 12 | 13 | +(instancetype)queue{ 14 | NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 15 | queue.maxConcurrentOperationCount = 3; 16 | return queue; 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSString/NSString+Stackoverflow.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Stackoverflow.h 3 | // CoreModel 4 | // 5 | // Created by 成林 on 15/3/29. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (Stackoverflow) 12 | 13 | 14 | 15 | -(NSArray *)toArray:(BOOL)isString; 16 | 17 | 18 | -(unsigned long long)unsignedLongLongValue; 19 | 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Category/NSString/NSString+Stackoverflow.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Stackoverflow.m 3 | // CoreModel 4 | // 5 | // Created by 成林 on 15/3/29. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import "NSString+Stackoverflow.h" 10 | #import "CoreModelConst.h" 11 | 12 | @implementation NSString (Stackoverflow) 13 | 14 | 15 | -(NSArray *)toArray:(BOOL)isString{ 16 | 17 | NSString *seperator = @","; 18 | 19 | if(!isString) seperator = SymbolString; 20 | 21 | NSArray *arr = [self componentsSeparatedByString:seperator]; 22 | 23 | if(isString) return arr; 24 | 25 | NSMutableArray *arrM = [NSMutableArray arrayWithCapacity:arr.count]; 26 | 27 | if(arr == nil || arr.count == 0) return nil; 28 | 29 | [arr enumerateObjectsUsingBlock:^(NSString *str, NSUInteger idx, BOOL *stop) { 30 | 31 | NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters]; 32 | 33 | [arrM addObject:data]; 34 | }]; 35 | 36 | return arrM; 37 | } 38 | 39 | 40 | 41 | 42 | 43 | -(unsigned long long)unsignedLongLongValue{ 44 | 45 | return self.longLongValue; 46 | } 47 | 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/CoreMoelConst/CoreModelConst.h: -------------------------------------------------------------------------------- 1 | // 2 | // CoreModelConst.h 3 | // CoreModel 4 | // 5 | // Created by muxi on 15/3/27. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #ifndef _BaseMoelConst_H_ 10 | #define _BaseMoelConst_H_ 11 | 12 | /** Debug */ 13 | #define CoreModelDeBug 1 14 | 15 | 16 | 17 | #import 18 | #import 19 | 20 | #define NSArrayNorlMalTypes @[@"NSString",@"NSData"] 21 | 22 | #define ThreadShow(msg) if(CoreModelDeBug){NSLog(@"%@所在线程:%@",@#msg,[NSThread currentThread]);}; 23 | #define TriggerBlock(block,res) if(block != nil ) block(res); 24 | #define AutoMsg @"框架正在全自动创表,并稍后自动重新执行您的操作,请放心!" 25 | #define AutoTry 0.1 26 | 27 | 28 | /** 29 | * NSString 30 | */ 31 | UIKIT_EXTERN NSString *const CoreNSString; 32 | 33 | 34 | 35 | /** 36 | * NSInteger 37 | */ 38 | UIKIT_EXTERN NSString *const CoreNSInteger; 39 | 40 | 41 | 42 | /** 43 | * NSUInteger 44 | */ 45 | UIKIT_EXTERN NSString *const CoreNSUInteger; 46 | 47 | 48 | 49 | /** 50 | * CGFloat 51 | */ 52 | UIKIT_EXTERN NSString *const CoreCGFloat; 53 | 54 | 55 | 56 | /** 57 | * Enum、int 58 | */ 59 | UIKIT_EXTERN NSString *const CoreEnum_int; 60 | 61 | 62 | 63 | /** 64 | * BOOL:BOOL类型的变量对应sqlite中的integer方便扩展 65 | */ 66 | UIKIT_EXTERN NSString *const CoreBOOL; 67 | 68 | 69 | 70 | 71 | /** 72 | * NSData 73 | */ 74 | UIKIT_EXTERN NSString *const CoreNSData; 75 | 76 | 77 | 78 | /** 79 | * NSArray 80 | */ 81 | UIKIT_EXTERN NSString *const CoreNSArray; 82 | 83 | 84 | 85 | 86 | 87 | 88 | /** 89 | * SQL语句Const 90 | */ 91 | 92 | /** 93 | * INTEGER 94 | */ 95 | UIKIT_EXTERN NSString *const INTEGER_TYPE; 96 | 97 | 98 | /** 99 | * TEXT 100 | */ 101 | UIKIT_EXTERN NSString *const TEXT_TYPE; 102 | 103 | 104 | /** 105 | * REAL 106 | */ 107 | UIKIT_EXTERN NSString *const REAL_TYPE; 108 | 109 | 110 | /** 111 | * BLOB 112 | */ 113 | UIKIT_EXTERN NSString *const BLOB_TYPE; 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | /** 122 | * 其他定义 123 | */ 124 | 125 | /** 126 | * 空字符串 127 | */ 128 | UIKIT_EXTERN NSString *const EmptyString; 129 | 130 | 131 | /** 132 | * 标识字符串 133 | */ 134 | UIKIT_EXTERN NSString *const SymbolString; 135 | 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/CoreMoelConst/CoreModelConst.m: -------------------------------------------------------------------------------- 1 | // 2 | // CoreModelConst.m 3 | // CoreModel 4 | // 5 | // Created by muxi on 15/3/27. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #ifndef _BaseMoelConst_M_ 10 | #define _BaseMoelConst_M_ 11 | 12 | 13 | #import 14 | #import 15 | 16 | 17 | 18 | 19 | /** 20 | * 字符串 21 | */ 22 | NSString *const CoreNSString = @"NSString"; 23 | 24 | 25 | 26 | 27 | /** 28 | * NSInteger 29 | */ 30 | NSString *const CoreNSInteger = @"q,i"; 31 | 32 | 33 | 34 | /** 35 | * NSUInteger 36 | */ 37 | NSString *const CoreNSUInteger = @"Q,I"; 38 | 39 | 40 | 41 | 42 | /** 43 | * CGFloat 44 | */ 45 | NSString *const CoreCGFloat = @"d,f"; 46 | 47 | 48 | 49 | /** 50 | * float 51 | */ 52 | NSString *const Corefloat = @"f"; 53 | 54 | 55 | 56 | /** 57 | * double 58 | */ 59 | NSString *const Coredouble = @"d"; 60 | 61 | 62 | 63 | /** 64 | * Enum、int 65 | */ 66 | NSString *const CoreEnum_int = @"i"; 67 | 68 | 69 | 70 | /** 71 | * BOOL 72 | */ 73 | NSString *const CoreBOOL = @"B,c"; 74 | 75 | 76 | 77 | /** 78 | * NSData 79 | */ 80 | NSString *const CoreNSData = @"NSData"; 81 | 82 | 83 | 84 | /** 85 | * NSArray 86 | */ 87 | NSString *const CoreNSArray = @"NSArray"; 88 | 89 | 90 | 91 | 92 | /** 93 | * SQL语句Const 94 | */ 95 | 96 | /** 97 | * INTEGER 98 | */ 99 | NSString *const INTEGER_TYPE = @"INTEGER NOT NULL DEFAULT 0"; 100 | 101 | 102 | /** 103 | * TEXT 104 | */ 105 | NSString *const TEXT_TYPE = @"TEXT NOT NULL DEFAULT ''"; 106 | 107 | 108 | /** 109 | * REAL 110 | */ 111 | NSString *const REAL_TYPE = @"REAL NOT NULL DEFAULT 0.0"; 112 | 113 | 114 | 115 | /** 116 | * BLOB 117 | */ 118 | NSString *const BLOB_TYPE = @"BLOB"; 119 | 120 | 121 | 122 | 123 | /** 124 | * 其他定义 125 | */ 126 | 127 | /** 128 | * 空字符串 129 | */ 130 | NSString *const EmptyString = @""; 131 | 132 | 133 | /** 134 | * 标识字符串 135 | */ 136 | NSString *const SymbolString = @"SymbolString"; 137 | 138 | 139 | 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Protocol/CoreModelProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // CoreModelProtocol.h 3 | // CoreClass 4 | // 5 | // Created by 冯成林 on 15/5/28. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CoreModelType.h" 11 | 12 | 13 | 14 | 15 | 16 | 17 | @protocol CoreModelProtocol 18 | 19 | @required 20 | 21 | 22 | /** 接口地址 */ 23 | +(NSString *)CoreModel_UrlString; 24 | 25 | /** 请求方式 */ 26 | +(CoreModelHttpType)CoreModel_HttpType; 27 | 28 | /** 是否需要本地缓存 */ 29 | +(BOOL)CoreModel_NeedFMDB; 30 | 31 | /** 缓存周期:单位秒 */ 32 | +(NSTimeInterval)CoreModel_Duration; 33 | 34 | 35 | /** 36 | * 错误数据解析:请求成功,但服务器返回的接口状态码抛出错误 37 | * 38 | * @param hostData 服务器数据 39 | * 40 | * @return 如果为nil,表示无错误;如果不为空表示有错误,并且为错误信息。 41 | */ 42 | +(NSString *)CoreModel_parseErrorData:(id)hostData; 43 | 44 | 45 | /** 服务器真正有用数据体:此时只是找到对应的key,还没有字典转模型 */ 46 | +(id)CoreModel_findUsefullData:(id)hostData; 47 | 48 | 49 | /** 返回数据格式 */ 50 | +(CoreModelHostDataType)CoreModel_hostDataType; 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Protocol/CorePageModelProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // BasePageModelProtocol.h 3 | // CoreClass 4 | // 5 | // Created by 冯成林 on 15/6/5. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CoreModelType.h" 11 | 12 | 13 | 14 | 15 | 16 | 17 | @protocol CorePageModelProtocol 18 | 19 | @required 20 | 21 | 22 | /** 23 | * 是否为分页数据 24 | * 25 | * @return 如果为分页模型请返回YES,否则返回NO 26 | */ 27 | +(BOOL)CoreModel_isPageEnable; 28 | 29 | 30 | /** page字段 */ 31 | +(NSString *)CoreModel_PageKey; 32 | 33 | 34 | /** pagesize字段 */ 35 | +(NSString *)CoreModel_PageSizeKey; 36 | 37 | 38 | /** 页码起点 */ 39 | +(NSUInteger)CoreModel_StartPage; 40 | 41 | 42 | /** 每页数据量 */ 43 | +(NSUInteger)CoreModel_PageSize; 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | @end -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Reflect/CoreProperty.h: -------------------------------------------------------------------------------- 1 | // 2 | // CoreProperty.h 3 | // test 4 | // 5 | // Created by 冯成林 on 16/3/31. 6 | // Copyright © 2016年 冯成林. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum { 12 | 13 | /** Unknown */ 14 | CorePropertyTypeUnknown = 0, 15 | 16 | /** Bool */ 17 | CorePropertyTypeBool, 18 | 19 | /** Int */ 20 | CorePropertyTypeNSInteger, 21 | 22 | /** CGFloat */ 23 | CorePropertyTypeCGFloat, 24 | 25 | /** double */ 26 | CorePropertyTypeDouble, 27 | 28 | /** NSString */ 29 | CorePropertyTypeNSString, 30 | 31 | /** NSArray */ 32 | CorePropertyTypeNSArray, 33 | 34 | /** NSDictionary */ 35 | CorePropertyTypeNSDictionary, 36 | 37 | /** UIImage */ 38 | CorePropertyTypeUIImage, 39 | 40 | /** NSData */ 41 | CorePropertyTypeNSData, 42 | 43 | /** CustomObj */ 44 | CorePropertyTypeCustomObj, 45 | 46 | } CorePropertyType; 47 | 48 | 49 | 50 | 51 | 52 | 53 | @interface CoreProperty : NSObject 54 | 55 | @property (nonatomic,copy) NSString *name; 56 | 57 | @property (nonatomic,copy) NSString *code; 58 | 59 | @property (nonatomic,assign) CorePropertyType type; 60 | 61 | @property (nonatomic,copy) NSString *typeString; 62 | 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Reflect/CoreProperty.m: -------------------------------------------------------------------------------- 1 | // 2 | // CoreProperty.m 3 | // test 4 | // 5 | // Created by 冯成林 on 16/3/31. 6 | // Copyright © 2016年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "CoreProperty.h" 10 | 11 | 12 | @interface CoreProperty () 13 | 14 | @property (nonatomic,strong) NSArray *typeNames; 15 | 16 | @end 17 | 18 | 19 | 20 | 21 | @implementation CoreProperty 22 | 23 | -(void)setCode:(NSString *)code{ 24 | 25 | //去除@ 26 | code = [code stringByReplacingOccurrencesOfString:@"@" withString:@""]; 27 | //去除" 28 | code = [code stringByReplacingOccurrencesOfString:@"\"" withString:@""]; 29 | 30 | //记录code 31 | _code = code; 32 | 33 | /** Unknown */ 34 | self.type = CorePropertyTypeUnknown; 35 | 36 | /** Bool */ 37 | if ([code isEqualToString:@"c"] || [code isEqualToString:@"B"]) { 38 | 39 | self.type = CorePropertyTypeBool; return; 40 | } 41 | 42 | /** Int */ 43 | if ([code isEqualToString:@"i"] || [code isEqualToString:@"q"] || [code isEqualToString:@"Q"] || [code isEqualToString:@"I"]) { 44 | 45 | self.type = CorePropertyTypeNSInteger; return; 46 | } 47 | 48 | /** CGFloat */ 49 | if ([code isEqualToString:@"f"]) { 50 | 51 | self.type = CorePropertyTypeCGFloat; return; 52 | } 53 | 54 | 55 | /** double */ 56 | if ([code isEqualToString:@"d"]) { 57 | 58 | self.type = CorePropertyTypeDouble; return; 59 | } 60 | 61 | 62 | /** NSString */ 63 | if ([code isEqualToString:@"NSString"]) { 64 | 65 | self.type = CorePropertyTypeNSString; return; 66 | } 67 | 68 | 69 | /** NSArray */ 70 | if ([code isEqualToString:@"NSArray"]) { 71 | 72 | self.type = CorePropertyTypeNSArray; return; 73 | } 74 | 75 | 76 | /** NSDictionary */ 77 | if ([code isEqualToString:@"NSDictionary"]) { 78 | 79 | self.type = CorePropertyTypeNSDictionary; return; 80 | } 81 | 82 | /** UIImage */ 83 | if ([code isEqualToString:@"UIImage"]) { 84 | 85 | self.type = CorePropertyTypeUIImage; return; 86 | } 87 | 88 | /** NSData */ 89 | if ([code isEqualToString:@"NSData"]) { 90 | 91 | self.type = CorePropertyTypeNSData; return; 92 | } 93 | 94 | /** CustomObj */ 95 | Class cls = NSClassFromString(code); 96 | 97 | if(cls == nil) {return;} 98 | 99 | if(![[cls new] isKindOfClass:[NSObject class]]) {return;} 100 | 101 | self.type = CorePropertyTypeCustomObj; 102 | 103 | } 104 | 105 | 106 | -(NSArray *)typeNames{ 107 | 108 | if(_typeNames == nil){ 109 | 110 | 111 | _typeNames = @[@"Unknown",@"Bool",@"Int",@"CGFloat",@"double",@"NSString",@"NSArray",@"NSDictionary",@"UIImage",@"NSData",@"CustomObj"]; 112 | } 113 | 114 | return _typeNames; 115 | } 116 | 117 | 118 | -(NSString *)typeString{ 119 | 120 | if(_typeString == nil){ 121 | 122 | _typeString = self.typeNames[self.type]; 123 | } 124 | 125 | return _typeString; 126 | } 127 | 128 | @end 129 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Reflect/NSObject+Runtime.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Runtime.h 3 | // test 4 | // 5 | // Created by 冯成林 on 16/3/31. 6 | // Copyright © 2016年 冯成林. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CoreProperty.h" 11 | 12 | @interface NSObject (Runtime) 13 | 14 | 15 | /** 成员变量遍历 */ 16 | +(void)enumeratePropertiesUsingBlock:(void(^)(CoreProperty *p))propertyBlock; 17 | 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Reflect/NSObject+Runtime.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Runtime.m 3 | // test 4 | // 5 | // Created by 冯成林 on 16/3/31. 6 | // Copyright © 2016年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "NSObject+Runtime.h" 10 | #import 11 | 12 | @implementation NSObject (Runtime) 13 | 14 | /** 成员变量遍历 */ 15 | +(void)enumeratePropertiesUsingBlock:(void(^)(CoreProperty *p))propertyBlock{ 16 | 17 | Class cls = self; 18 | 19 | do { 20 | 21 | [self enumerateCls:cls propertyBlock:propertyBlock]; 22 | 23 | cls = class_getSuperclass(cls); 24 | 25 | }while (cls != [NSObject class]); 26 | 27 | } 28 | 29 | 30 | +(void)enumerateCls:(Class)cls propertyBlock:(void(^)(CoreProperty *p))propertyBlock{ 31 | 32 | unsigned int numIvars; //成员变量个数 33 | 34 | Ivar *vars = class_copyIvarList(cls, &numIvars); 35 | 36 | //Ivar *vars = class_copyIvarList([UIView class], &numIvars); 37 | 38 | NSString *key=nil; 39 | NSString *type = nil; 40 | 41 | for(int i = 0; i < numIvars; i++) { 42 | 43 | //创建CoreProperty 44 | CoreProperty *p =[CoreProperty new]; 45 | 46 | Ivar thisIvar = vars[i]; 47 | key = [NSString stringWithUTF8String:ivar_getName(thisIvar)]; //获取成员变量的名字 48 | 49 | //记录变量名 50 | p.name = [key stringByReplacingOccurrencesOfString:@"_" withString:@""]; 51 | 52 | type = [NSString stringWithUTF8String:ivar_getTypeEncoding(thisIvar)]; //获取成员变量的数据类型 53 | 54 | //处理并记录变量类型 55 | p.code = type; 56 | 57 | propertyBlock(p); 58 | } 59 | 60 | free(vars); 61 | } 62 | 63 | 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /CoreModel/CoreModel/Lib/Type/CoreModelType.h: -------------------------------------------------------------------------------- 1 | // 2 | // CoreModelType.h 3 | // CoreClass 4 | // 5 | // Created by 冯成林 on 15/5/28. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #ifndef CoreClass_CoreModelType_h 10 | #define CoreClass_CoreModelType_h 11 | 12 | 13 | /** 请求方式 */ 14 | typedef enum{ 15 | 16 | //GET 17 | CoreModelHttpTypeGET=0, 18 | 19 | //POST 20 | CoreModelHttpTypePOST 21 | 22 | }CoreModelHttpType; 23 | 24 | 25 | 26 | /** 返回数据格式 */ 27 | typedef enum{ 28 | 29 | //模型:单个 30 | CoreModelHostDataTypeModelSingle=0, 31 | 32 | //数组:数组 33 | CoreModelHostDataTypeModelArray 34 | 35 | }CoreModelHostDataType; 36 | 37 | 38 | 39 | /** 模型数据来源 */ 40 | typedef enum{ 41 | 42 | //默认值:无来源 43 | CoreModelDataSourceTypeNone, 44 | 45 | //本地数据库 46 | CoreModelDataSourceTypeSqlite, 47 | 48 | //服务器数据,且本地数据库无数据 49 | CoreModelDataSourceHostType_Sqlite_Nil, 50 | 51 | //服务器数据,本地数据库有数据,但本地数据过期 52 | CoreModelDataSourceHostType_Sqlite_Deprecated, 53 | 54 | }CoreModelDataSourceType; 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /CoreModel/FrameWorks/CoreFMDB/CoreFMDB.h: -------------------------------------------------------------------------------- 1 | // 2 | // CoreFMDB.h 3 | // CoreFMDB 4 | // 5 | // Created by muxi on 15/3/27. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CoreFMDBSingleton.h" 11 | #import "FMResultSet.h" 12 | 13 | @interface CoreFMDB : NSObject 14 | HMSingletonH(CoreFMDB) 15 | 16 | 17 | /** 18 | * 执行一个更新语句 19 | * 20 | * @param sql 更新语句的sql 21 | * 22 | * @return 更新语句的执行结果 23 | */ 24 | +(BOOL)executeUpdate:(NSString *)sql; 25 | 26 | 27 | /** 28 | * 执行一个查询语句 29 | * 30 | * @param sql 查询语句sql 31 | * @param queryResBlock 查询语句的执行结果 32 | */ 33 | +(void)executeQuery:(NSString *)sql queryResBlock:(void(^)(FMResultSet *set))queryResBlock; 34 | 35 | 36 | /** 37 | * 查询出指定表的列 38 | * 39 | * @param table table 40 | * 41 | * @return 查询出指定表的列的执行结果 42 | */ 43 | +(NSArray *)executeQueryColumnsInTable:(NSString *)table; 44 | 45 | 46 | /** 47 | * 表记录数计算 48 | * 49 | * @param table 表 50 | * 51 | * @return 记录数 52 | */ 53 | +(NSUInteger)countTable:(NSString *)table; 54 | 55 | 56 | /** 57 | * 清空表(但不清除表结构) 58 | * 59 | * @param table 表名 60 | * 61 | * @return 操作结果 62 | */ 63 | +(BOOL)truncateTable:(NSString *)table; 64 | 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /CoreModel/FrameWorks/CoreFMDB/CoreFMDB.m: -------------------------------------------------------------------------------- 1 | // 2 | // CoreFMDB.m 3 | // CoreFMDB 4 | // 5 | // Created by muxi on 15/3/27. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import "CoreFMDB.h" 10 | #import "FMDB.h" 11 | #import "NSString+CoreFMDB.h" 12 | 13 | @interface CoreFMDB () 14 | 15 | 16 | /** 17 | * 具有线程安全的数据队列 18 | */ 19 | @property (nonatomic,strong) FMDatabaseQueue *queue; 20 | 21 | 22 | 23 | @end 24 | 25 | 26 | 27 | 28 | 29 | @implementation CoreFMDB 30 | HMSingletonM(CoreFMDB) 31 | 32 | 33 | /** 34 | * 数据库队列的初始化:本操作一个 35 | */ 36 | +(void)initialize{ 37 | 38 | //取出实例 39 | CoreFMDB *coreFMDB=[CoreFMDB sharedCoreFMDB]; 40 | 41 | //获取项目info文件 42 | NSDictionary *infoDict=[[NSBundle mainBundle] infoDictionary]; 43 | 44 | //获取项目Bundle Name:英文(CFBundleName) 45 | NSString *key=(NSString *)kCFBundleNameKey; 46 | NSString *bundleName=infoDict[key]; 47 | //拼接数据库名 48 | NSString *dbName=[NSString stringWithFormat:@"%@%@",bundleName,@".sql"]; 49 | 50 | //在沙盒中存入数据库文件 51 | NSString *dbPath=[bundleName.documentsSubFolder stringByAppendingPathComponent:dbName]; 52 | 53 | const BOOL needLogSqlFilePath=YES; 54 | 55 | if(needLogSqlFilePath) NSLog(@"dbPath:%@",dbPath); 56 | 57 | //创建队列 58 | FMDatabaseQueue *queue =[FMDatabaseQueue databaseQueueWithPath:dbPath]; 59 | 60 | if(queue==nil)NSLog(@"code=1:创建数据库失败,请检查"); 61 | 62 | coreFMDB.queue = queue; 63 | } 64 | 65 | 66 | 67 | 68 | /** 69 | * 执行一个更新语句 70 | * 71 | * @param sql 更新语句的sql 72 | * 73 | * @return 更新语句的执行结果 74 | */ 75 | +(BOOL)executeUpdate:(NSString *)sql{ 76 | 77 | __block BOOL updateRes = NO; 78 | 79 | CoreFMDB *coreFMDB=[CoreFMDB sharedCoreFMDB]; 80 | 81 | [coreFMDB.queue inDatabase:^(FMDatabase *db) { 82 | 83 | updateRes = [db executeUpdate:sql]; 84 | }]; 85 | 86 | return updateRes; 87 | } 88 | 89 | 90 | 91 | 92 | 93 | /** 94 | * 执行一个查询语句 95 | * 96 | * @param sql 查询语句sql 97 | * @param queryResBlock 查询语句的执行结果 98 | */ 99 | +(void)executeQuery:(NSString *)sql queryResBlock:(void(^)(FMResultSet *set))queryResBlock{ 100 | 101 | CoreFMDB *coreFMDB=[CoreFMDB sharedCoreFMDB]; 102 | 103 | [coreFMDB.queue inDatabase:^(FMDatabase *db) { 104 | 105 | FMResultSet *set = [db executeQuery:sql]; 106 | 107 | if(queryResBlock != nil) queryResBlock(set); 108 | 109 | NSLog(@"%@",[NSThread currentThread]); 110 | }]; 111 | } 112 | 113 | 114 | 115 | 116 | /** 117 | * 查询出指定表的列 118 | * 119 | * @param table table 120 | * 121 | * @return 查询出指定表的列的执行结果 122 | */ 123 | +(NSArray *)executeQueryColumnsInTable:(NSString *)table{ 124 | 125 | NSMutableArray *columnsM=[NSMutableArray array]; 126 | 127 | NSString *sql=[NSString stringWithFormat:@"PRAGMA table_info (%@);",table]; 128 | 129 | [self executeQuery:sql queryResBlock:^(FMResultSet *set) { 130 | 131 | //循环取出数据 132 | while ([set next]) { 133 | NSString *column = [set stringForColumn:@"name"]; 134 | [columnsM addObject:column]; 135 | } 136 | 137 | if(columnsM.count==0) NSLog(@"code=2:您指定的表:%@,没有字段信息,可能是表尚未创建!",table); 138 | }]; 139 | 140 | return [columnsM copy]; 141 | } 142 | 143 | 144 | /** 145 | * 表记录数计算 146 | * 147 | * @param table 表 148 | * 149 | * @return 记录数 150 | */ 151 | +(NSUInteger)countTable:(NSString *)table{ 152 | 153 | NSString *alias=@"count"; 154 | 155 | NSString *sql=[NSString stringWithFormat:@"SELECT COUNT(*) AS %@ FROM %@;",alias,table]; 156 | 157 | __block NSUInteger count=0; 158 | 159 | [self executeQuery:sql queryResBlock:^(FMResultSet *set) { 160 | 161 | while ([set next]) { 162 | 163 | count = [[set stringForColumn:alias] integerValue]; 164 | } 165 | }]; 166 | 167 | return count; 168 | } 169 | 170 | 171 | /** 172 | * 清空表(但不清除表结构) 173 | * 174 | * @param table 表名 175 | * 176 | * @return 操作结果 177 | */ 178 | +(BOOL)truncateTable:(NSString *)table{ 179 | 180 | BOOL res = [self executeUpdate:[NSString stringWithFormat:@"DELETE FROM '%@'", table]]; 181 | [self executeUpdate:[NSString stringWithFormat:@"DELETE FROM sqlite_sequence WHERE name='%@';", table]]; 182 | return res; 183 | } 184 | 185 | 186 | 187 | @end 188 | -------------------------------------------------------------------------------- /CoreModel/FrameWorks/CoreFMDB/Lib/Category/NSString+CoreFMDB.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+CoreFMDB.h 3 | // CoreFMDB 4 | // 5 | // Created by muxi on 15/3/27. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (CoreFMDB) 12 | 13 | 14 | 15 | /** 16 | * 转为documents下的子文件夹 17 | */ 18 | @property (nonatomic,copy,readonly) NSString *documentsSubFolder; 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /CoreModel/FrameWorks/CoreFMDB/Lib/Category/NSString+CoreFMDB.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+CoreFMDB.m 3 | // CoreFMDB 4 | // 5 | // Created by muxi on 15/3/27. 6 | // Copyright (c) 2015年 muxi. All rights reserved. 7 | // 8 | 9 | #import "NSString+CoreFMDB.h" 10 | 11 | @implementation NSString (CoreFMDB) 12 | 13 | 14 | 15 | /** 16 | * 转为documents下的子文件夹 17 | */ 18 | -(NSString *)documentsSubFolder{ 19 | 20 | NSString *documentFolder=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; 21 | 22 | return [NSString makeSubFolderInSuperFolder:documentFolder subFloder:self]; 23 | 24 | } 25 | 26 | 27 | 28 | /** 29 | * 文件夹处理 30 | */ 31 | +(NSString *)makeSubFolderInSuperFolder:(NSString *)superFolder subFloder:(NSString *)subFloder{ 32 | 33 | NSString *folder=[NSString stringWithFormat:@"%@/%@",superFolder,subFloder]; 34 | 35 | BOOL isDir = NO; 36 | 37 | NSFileManager *fileManager = [NSFileManager defaultManager]; 38 | 39 | BOOL existed = [fileManager fileExistsAtPath:folder isDirectory:&isDir]; 40 | 41 | if ( !(isDir == YES && existed == YES) ) 42 | { 43 | [fileManager createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:nil error:nil]; 44 | } 45 | 46 | return folder; 47 | } 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /CoreModel/FrameWorks/CoreFMDB/Lib/Singleton/CoreFMDBSingleton.h: -------------------------------------------------------------------------------- 1 | // .h文件 2 | #define HMSingletonH(name) + (instancetype)shared##name; 3 | 4 | // .m文件 5 | #if __has_feature(objc_arc) 6 | 7 | #define HMSingletonM(name) \ 8 | static id _instace; \ 9 | \ 10 | + (id)allocWithZone:(struct _NSZone *)zone \ 11 | { \ 12 | static dispatch_once_t onceToken; \ 13 | dispatch_once(&onceToken, ^{ \ 14 | _instace = [super allocWithZone:zone]; \ 15 | }); \ 16 | return _instace; \ 17 | } \ 18 | \ 19 | + (instancetype)shared##name \ 20 | { \ 21 | static dispatch_once_t onceToken; \ 22 | dispatch_once(&onceToken, ^{ \ 23 | _instace = [[self alloc] init]; \ 24 | }); \ 25 | return _instace; \ 26 | } \ 27 | \ 28 | - (id)copyWithZone:(NSZone *)zone \ 29 | { \ 30 | return _instace; \ 31 | } 32 | 33 | #else 34 | 35 | #define HMSingletonM(name) \ 36 | static id _instace; \ 37 | \ 38 | + (id)allocWithZone:(struct _NSZone *)zone \ 39 | { \ 40 | static dispatch_once_t onceToken; \ 41 | dispatch_once(&onceToken, ^{ \ 42 | _instace = [super allocWithZone:zone]; \ 43 | }); \ 44 | return _instace; \ 45 | } \ 46 | \ 47 | + (instancetype)shared##name \ 48 | { \ 49 | static dispatch_once_t onceToken; \ 50 | dispatch_once(&onceToken, ^{ \ 51 | _instace = [[self alloc] init]; \ 52 | }); \ 53 | return _instace; \ 54 | } \ 55 | \ 56 | - (id)copyWithZone:(NSZone *)zone \ 57 | { \ 58 | return _instace; \ 59 | } \ 60 | \ 61 | - (oneway void)release { } \ 62 | - (id)retain { return self; } \ 63 | - (NSUInteger)retainCount { return 1;} \ 64 | - (id)autorelease { return self;} 65 | 66 | #endif -------------------------------------------------------------------------------- /CoreModel/FrameWorks/CoreFMDB/Lib/fmdb/FMDB.h: -------------------------------------------------------------------------------- 1 | #import "FMDatabase.h" 2 | #import "FMResultSet.h" 3 | #import "FMDatabaseAdditions.h" 4 | #import "FMDatabaseQueue.h" 5 | #import "FMDatabasePool.h" 6 | -------------------------------------------------------------------------------- /CoreModel/FrameWorks/CoreFMDB/Lib/fmdb/FMDatabaseAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabaseAdditions.h 3 | // fmdb 4 | // 5 | // Created by August Mueller on 10/30/05. 6 | // Copyright 2005 Flying Meat Inc.. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "FMDatabase.h" 11 | 12 | 13 | /** Category of additions for `` class. 14 | 15 | ### See also 16 | 17 | - `` 18 | */ 19 | 20 | @interface FMDatabase (FMDatabaseAdditions) 21 | 22 | ///---------------------------------------- 23 | /// @name Return results of SQL to variable 24 | ///---------------------------------------- 25 | 26 | /** Return `int` value for query 27 | 28 | @param query The SQL query to be performed. 29 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 30 | 31 | @return `int` value. 32 | 33 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project. 34 | */ 35 | 36 | - (int)intForQuery:(NSString*)query, ...; 37 | 38 | /** Return `long` value for query 39 | 40 | @param query The SQL query to be performed. 41 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 42 | 43 | @return `long` value. 44 | 45 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project. 46 | */ 47 | 48 | - (long)longForQuery:(NSString*)query, ...; 49 | 50 | /** Return `BOOL` value for query 51 | 52 | @param query The SQL query to be performed. 53 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 54 | 55 | @return `BOOL` value. 56 | 57 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project. 58 | */ 59 | 60 | - (BOOL)boolForQuery:(NSString*)query, ...; 61 | 62 | /** Return `double` value for query 63 | 64 | @param query The SQL query to be performed. 65 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 66 | 67 | @return `double` value. 68 | 69 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project. 70 | */ 71 | 72 | - (double)doubleForQuery:(NSString*)query, ...; 73 | 74 | /** Return `NSString` value for query 75 | 76 | @param query The SQL query to be performed. 77 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 78 | 79 | @return `NSString` value. 80 | 81 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project. 82 | */ 83 | 84 | - (NSString*)stringForQuery:(NSString*)query, ...; 85 | 86 | /** Return `NSData` value for query 87 | 88 | @param query The SQL query to be performed. 89 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 90 | 91 | @return `NSData` value. 92 | 93 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project. 94 | */ 95 | 96 | - (NSData*)dataForQuery:(NSString*)query, ...; 97 | 98 | /** Return `NSDate` value for query 99 | 100 | @param query The SQL query to be performed. 101 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 102 | 103 | @return `NSDate` value. 104 | 105 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project. 106 | */ 107 | 108 | - (NSDate*)dateForQuery:(NSString*)query, ...; 109 | 110 | 111 | // Notice that there's no dataNoCopyForQuery:. 112 | // That would be a bad idea, because we close out the result set, and then what 113 | // happens to the data that we just didn't copy? Who knows, not I. 114 | 115 | 116 | ///-------------------------------- 117 | /// @name Schema related operations 118 | ///-------------------------------- 119 | 120 | /** Does table exist in database? 121 | 122 | @param tableName The name of the table being looked for. 123 | 124 | @return `YES` if table found; `NO` if not found. 125 | */ 126 | 127 | - (BOOL)tableExists:(NSString*)tableName; 128 | 129 | /** The schema of the database. 130 | 131 | This will be the schema for the entire database. For each entity, each row of the result set will include the following fields: 132 | 133 | - `type` - The type of entity (e.g. table, index, view, or trigger) 134 | - `name` - The name of the object 135 | - `tbl_name` - The name of the table to which the object references 136 | - `rootpage` - The page number of the root b-tree page for tables and indices 137 | - `sql` - The SQL that created the entity 138 | 139 | @return `FMResultSet` of schema; `nil` on error. 140 | 141 | @see [SQLite File Format](http://www.sqlite.org/fileformat.html) 142 | */ 143 | 144 | - (FMResultSet*)getSchema; 145 | 146 | /** The schema of the database. 147 | 148 | This will be the schema for a particular table as report by SQLite `PRAGMA`, for example: 149 | 150 | PRAGMA table_info('employees') 151 | 152 | This will report: 153 | 154 | - `cid` - The column ID number 155 | - `name` - The name of the column 156 | - `type` - The data type specified for the column 157 | - `notnull` - whether the field is defined as NOT NULL (i.e. values required) 158 | - `dflt_value` - The default value for the column 159 | - `pk` - Whether the field is part of the primary key of the table 160 | 161 | @param tableName The name of the table for whom the schema will be returned. 162 | 163 | @return `FMResultSet` of schema; `nil` on error. 164 | 165 | @see [table_info](http://www.sqlite.org/pragma.html#pragma_table_info) 166 | */ 167 | 168 | - (FMResultSet*)getTableSchema:(NSString*)tableName; 169 | 170 | /** Test to see if particular column exists for particular table in database 171 | 172 | @param columnName The name of the column. 173 | 174 | @param tableName The name of the table. 175 | 176 | @return `YES` if column exists in table in question; `NO` otherwise. 177 | */ 178 | 179 | - (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName; 180 | 181 | /** Test to see if particular column exists for particular table in database 182 | 183 | @param columnName The name of the column. 184 | 185 | @param tableName The name of the table. 186 | 187 | @return `YES` if column exists in table in question; `NO` otherwise. 188 | 189 | @see columnExists:inTableWithName: 190 | 191 | @warning Deprecated - use `` instead. 192 | */ 193 | 194 | - (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated)); 195 | 196 | 197 | /** Validate SQL statement 198 | 199 | This validates SQL statement by performing `sqlite3_prepare_v2`, but not returning the results, but instead immediately calling `sqlite3_finalize`. 200 | 201 | @param sql The SQL statement being validated. 202 | 203 | @param error This is a pointer to a `NSError` object that will receive the autoreleased `NSError` object if there was any error. If this is `nil`, no `NSError` result will be returned. 204 | 205 | @return `YES` if validation succeeded without incident; `NO` otherwise. 206 | 207 | */ 208 | 209 | - (BOOL)validateSQL:(NSString*)sql error:(NSError**)error; 210 | 211 | 212 | #if SQLITE_VERSION_NUMBER >= 3007017 213 | 214 | ///----------------------------------- 215 | /// @name Application identifier tasks 216 | ///----------------------------------- 217 | 218 | /** Retrieve application ID 219 | 220 | @return The `uint32_t` numeric value of the application ID. 221 | 222 | @see setApplicationID: 223 | */ 224 | 225 | - (uint32_t)applicationID; 226 | 227 | /** Set the application ID 228 | 229 | @param appID The `uint32_t` numeric value of the application ID. 230 | 231 | @see applicationID 232 | */ 233 | 234 | - (void)setApplicationID:(uint32_t)appID; 235 | 236 | #if TARGET_OS_MAC && !TARGET_OS_IPHONE 237 | /** Retrieve application ID string 238 | 239 | @return The `NSString` value of the application ID. 240 | 241 | @see setApplicationIDString: 242 | */ 243 | 244 | 245 | - (NSString*)applicationIDString; 246 | 247 | /** Set the application ID string 248 | 249 | @param string The `NSString` value of the application ID. 250 | 251 | @see applicationIDString 252 | */ 253 | 254 | - (void)setApplicationIDString:(NSString*)string; 255 | #endif 256 | 257 | #endif 258 | 259 | ///----------------------------------- 260 | /// @name user version identifier tasks 261 | ///----------------------------------- 262 | 263 | /** Retrieve user version 264 | 265 | @return The `uint32_t` numeric value of the user version. 266 | 267 | @see setUserVersion: 268 | */ 269 | 270 | - (uint32_t)userVersion; 271 | 272 | /** Set the user-version 273 | 274 | @param version The `uint32_t` numeric value of the user version. 275 | 276 | @see userVersion 277 | */ 278 | 279 | - (void)setUserVersion:(uint32_t)version; 280 | 281 | @end 282 | -------------------------------------------------------------------------------- /CoreModel/FrameWorks/CoreFMDB/Lib/fmdb/FMDatabaseAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabaseAdditions.m 3 | // fmdb 4 | // 5 | // Created by August Mueller on 10/30/05. 6 | // Copyright 2005 Flying Meat Inc.. All rights reserved. 7 | // 8 | 9 | #import "FMDatabase.h" 10 | #import "FMDatabaseAdditions.h" 11 | #import "TargetConditionals.h" 12 | 13 | @interface FMDatabase (PrivateStuff) 14 | - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args; 15 | @end 16 | 17 | @implementation FMDatabase (FMDatabaseAdditions) 18 | 19 | #define RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(type, sel) \ 20 | va_list args; \ 21 | va_start(args, query); \ 22 | FMResultSet *resultSet = [self executeQuery:query withArgumentsInArray:0x00 orDictionary:0x00 orVAList:args]; \ 23 | va_end(args); \ 24 | if (![resultSet next]) { return (type)0; } \ 25 | type ret = [resultSet sel:0]; \ 26 | [resultSet close]; \ 27 | [resultSet setParentDB:nil]; \ 28 | return ret; 29 | 30 | 31 | - (NSString*)stringForQuery:(NSString*)query, ... { 32 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSString *, stringForColumnIndex); 33 | } 34 | 35 | - (int)intForQuery:(NSString*)query, ... { 36 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(int, intForColumnIndex); 37 | } 38 | 39 | - (long)longForQuery:(NSString*)query, ... { 40 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(long, longForColumnIndex); 41 | } 42 | 43 | - (BOOL)boolForQuery:(NSString*)query, ... { 44 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(BOOL, boolForColumnIndex); 45 | } 46 | 47 | - (double)doubleForQuery:(NSString*)query, ... { 48 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(double, doubleForColumnIndex); 49 | } 50 | 51 | - (NSData*)dataForQuery:(NSString*)query, ... { 52 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSData *, dataForColumnIndex); 53 | } 54 | 55 | - (NSDate*)dateForQuery:(NSString*)query, ... { 56 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSDate *, dateForColumnIndex); 57 | } 58 | 59 | 60 | - (BOOL)tableExists:(NSString*)tableName { 61 | 62 | tableName = [tableName lowercaseString]; 63 | 64 | FMResultSet *rs = [self executeQuery:@"select [sql] from sqlite_master where [type] = 'table' and lower(name) = ?", tableName]; 65 | 66 | //if at least one next exists, table exists 67 | BOOL returnBool = [rs next]; 68 | 69 | //close and free object 70 | [rs close]; 71 | 72 | return returnBool; 73 | } 74 | 75 | /* 76 | get table with list of tables: result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING] 77 | check if table exist in database (patch from OZLB) 78 | */ 79 | - (FMResultSet*)getSchema { 80 | 81 | //result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING] 82 | FMResultSet *rs = [self executeQuery:@"SELECT type, name, tbl_name, rootpage, sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type != 'meta' AND name NOT LIKE 'sqlite_%' ORDER BY tbl_name, type DESC, name"]; 83 | 84 | return rs; 85 | } 86 | 87 | /* 88 | get table schema: result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER] 89 | */ 90 | - (FMResultSet*)getTableSchema:(NSString*)tableName { 91 | 92 | //result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER] 93 | FMResultSet *rs = [self executeQuery:[NSString stringWithFormat: @"pragma table_info('%@')", tableName]]; 94 | 95 | return rs; 96 | } 97 | 98 | - (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName { 99 | 100 | BOOL returnBool = NO; 101 | 102 | tableName = [tableName lowercaseString]; 103 | columnName = [columnName lowercaseString]; 104 | 105 | FMResultSet *rs = [self getTableSchema:tableName]; 106 | 107 | //check if column is present in table schema 108 | while ([rs next]) { 109 | if ([[[rs stringForColumn:@"name"] lowercaseString] isEqualToString:columnName]) { 110 | returnBool = YES; 111 | break; 112 | } 113 | } 114 | 115 | //If this is not done FMDatabase instance stays out of pool 116 | [rs close]; 117 | 118 | return returnBool; 119 | } 120 | 121 | 122 | #if SQLITE_VERSION_NUMBER >= 3007017 123 | 124 | - (uint32_t)applicationID { 125 | 126 | uint32_t r = 0; 127 | 128 | FMResultSet *rs = [self executeQuery:@"pragma application_id"]; 129 | 130 | if ([rs next]) { 131 | r = (uint32_t)[rs longLongIntForColumnIndex:0]; 132 | } 133 | 134 | [rs close]; 135 | 136 | return r; 137 | } 138 | 139 | - (void)setApplicationID:(uint32_t)appID { 140 | NSString *query = [NSString stringWithFormat:@"pragma application_id=%d", appID]; 141 | FMResultSet *rs = [self executeQuery:query]; 142 | [rs next]; 143 | [rs close]; 144 | } 145 | 146 | 147 | #if TARGET_OS_MAC && !TARGET_OS_IPHONE 148 | - (NSString*)applicationIDString { 149 | NSString *s = NSFileTypeForHFSTypeCode([self applicationID]); 150 | 151 | assert([s length] == 6); 152 | 153 | s = [s substringWithRange:NSMakeRange(1, 4)]; 154 | 155 | 156 | return s; 157 | 158 | } 159 | 160 | - (void)setApplicationIDString:(NSString*)s { 161 | 162 | if ([s length] != 4) { 163 | NSLog(@"setApplicationIDString: string passed is not exactly 4 chars long. (was %ld)", [s length]); 164 | } 165 | 166 | [self setApplicationID:NSHFSTypeCodeFromFileType([NSString stringWithFormat:@"'%@'", s])]; 167 | } 168 | 169 | 170 | #endif 171 | 172 | #endif 173 | 174 | - (uint32_t)userVersion { 175 | uint32_t r = 0; 176 | 177 | FMResultSet *rs = [self executeQuery:@"pragma user_version"]; 178 | 179 | if ([rs next]) { 180 | r = (uint32_t)[rs longLongIntForColumnIndex:0]; 181 | } 182 | 183 | [rs close]; 184 | return r; 185 | } 186 | 187 | - (void)setUserVersion:(uint32_t)version { 188 | NSString *query = [NSString stringWithFormat:@"pragma user_version = %d", version]; 189 | FMResultSet *rs = [self executeQuery:query]; 190 | [rs next]; 191 | [rs close]; 192 | } 193 | 194 | #pragma clang diagnostic push 195 | #pragma clang diagnostic ignored "-Wdeprecated-implementations" 196 | 197 | - (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated)) { 198 | return [self columnExists:columnName inTableWithName:tableName]; 199 | } 200 | 201 | #pragma clang diagnostic pop 202 | 203 | 204 | - (BOOL)validateSQL:(NSString*)sql error:(NSError**)error { 205 | sqlite3_stmt *pStmt = NULL; 206 | BOOL validationSucceeded = YES; 207 | 208 | int rc = sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pStmt, 0); 209 | if (rc != SQLITE_OK) { 210 | validationSucceeded = NO; 211 | if (error) { 212 | *error = [NSError errorWithDomain:NSCocoaErrorDomain 213 | code:[self lastErrorCode] 214 | userInfo:[NSDictionary dictionaryWithObject:[self lastErrorMessage] 215 | forKey:NSLocalizedDescriptionKey]]; 216 | } 217 | } 218 | 219 | sqlite3_finalize(pStmt); 220 | 221 | return validationSucceeded; 222 | } 223 | 224 | @end 225 | -------------------------------------------------------------------------------- /CoreModel/FrameWorks/CoreFMDB/Lib/fmdb/FMDatabasePool.h: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabasePool.h 3 | // fmdb 4 | // 5 | // Created by August Mueller on 6/22/11. 6 | // Copyright 2011 Flying Meat Inc. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "sqlite3.h" 11 | 12 | @class FMDatabase; 13 | 14 | /** Pool of `` objects. 15 | 16 | ### See also 17 | 18 | - `` 19 | - `` 20 | 21 | @warning Before using `FMDatabasePool`, please consider using `` instead. 22 | 23 | If you really really really know what you're doing and `FMDatabasePool` is what 24 | you really really need (ie, you're using a read only database), OK you can use 25 | it. But just be careful not to deadlock! 26 | 27 | For an example on deadlocking, search for: 28 | `ONLY_USE_THE_POOL_IF_YOU_ARE_DOING_READS_OTHERWISE_YOULL_DEADLOCK_USE_FMDATABASEQUEUE_INSTEAD` 29 | in the main.m file. 30 | */ 31 | 32 | @interface FMDatabasePool : NSObject { 33 | NSString *_path; 34 | 35 | dispatch_queue_t _lockQueue; 36 | 37 | NSMutableArray *_databaseInPool; 38 | NSMutableArray *_databaseOutPool; 39 | 40 | __unsafe_unretained id _delegate; 41 | 42 | NSUInteger _maximumNumberOfDatabasesToCreate; 43 | int _openFlags; 44 | } 45 | 46 | /** Database path */ 47 | 48 | @property (atomic, retain) NSString *path; 49 | 50 | /** Delegate object */ 51 | 52 | @property (atomic, assign) id delegate; 53 | 54 | /** Maximum number of databases to create */ 55 | 56 | @property (atomic, assign) NSUInteger maximumNumberOfDatabasesToCreate; 57 | 58 | /** Open flags */ 59 | 60 | @property (atomic, readonly) int openFlags; 61 | 62 | 63 | ///--------------------- 64 | /// @name Initialization 65 | ///--------------------- 66 | 67 | /** Create pool using path. 68 | 69 | @param aPath The file path of the database. 70 | 71 | @return The `FMDatabasePool` object. `nil` on error. 72 | */ 73 | 74 | + (instancetype)databasePoolWithPath:(NSString*)aPath; 75 | 76 | /** Create pool using path and specified flags 77 | 78 | @param aPath The file path of the database. 79 | @param openFlags Flags passed to the openWithFlags method of the database 80 | 81 | @return The `FMDatabasePool` object. `nil` on error. 82 | */ 83 | 84 | + (instancetype)databasePoolWithPath:(NSString*)aPath flags:(int)openFlags; 85 | 86 | /** Create pool using path. 87 | 88 | @param aPath The file path of the database. 89 | 90 | @return The `FMDatabasePool` object. `nil` on error. 91 | */ 92 | 93 | - (instancetype)initWithPath:(NSString*)aPath; 94 | 95 | /** Create pool using path and specified flags. 96 | 97 | @param aPath The file path of the database. 98 | @param openFlags Flags passed to the openWithFlags method of the database 99 | 100 | @return The `FMDatabasePool` object. `nil` on error. 101 | */ 102 | 103 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags; 104 | 105 | ///------------------------------------------------ 106 | /// @name Keeping track of checked in/out databases 107 | ///------------------------------------------------ 108 | 109 | /** Number of checked-in databases in pool 110 | 111 | @returns Number of databases 112 | */ 113 | 114 | - (NSUInteger)countOfCheckedInDatabases; 115 | 116 | /** Number of checked-out databases in pool 117 | 118 | @returns Number of databases 119 | */ 120 | 121 | - (NSUInteger)countOfCheckedOutDatabases; 122 | 123 | /** Total number of databases in pool 124 | 125 | @returns Number of databases 126 | */ 127 | 128 | - (NSUInteger)countOfOpenDatabases; 129 | 130 | /** Release all databases in pool */ 131 | 132 | - (void)releaseAllDatabases; 133 | 134 | ///------------------------------------------ 135 | /// @name Perform database operations in pool 136 | ///------------------------------------------ 137 | 138 | /** Synchronously perform database operations in pool. 139 | 140 | @param block The code to be run on the `FMDatabasePool` pool. 141 | */ 142 | 143 | - (void)inDatabase:(void (^)(FMDatabase *db))block; 144 | 145 | /** Synchronously perform database operations in pool using transaction. 146 | 147 | @param block The code to be run on the `FMDatabasePool` pool. 148 | */ 149 | 150 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block; 151 | 152 | /** Synchronously perform database operations in pool using deferred transaction. 153 | 154 | @param block The code to be run on the `FMDatabasePool` pool. 155 | */ 156 | 157 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block; 158 | 159 | #if SQLITE_VERSION_NUMBER >= 3007000 160 | 161 | /** Synchronously perform database operations in pool using save point. 162 | 163 | @param block The code to be run on the `FMDatabasePool` pool. 164 | 165 | @return `NSError` object if error; `nil` if successful. 166 | 167 | @warning You can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock. If you need to nest, use `<[FMDatabase startSavePointWithName:error:]>` instead. 168 | */ 169 | 170 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block; 171 | #endif 172 | 173 | @end 174 | 175 | 176 | /** FMDatabasePool delegate category 177 | 178 | This is a category that defines the protocol for the FMDatabasePool delegate 179 | */ 180 | 181 | @interface NSObject (FMDatabasePoolDelegate) 182 | 183 | /** Asks the delegate whether database should be added to the pool. 184 | 185 | @param pool The `FMDatabasePool` object. 186 | @param database The `FMDatabase` object. 187 | 188 | @return `YES` if it should add database to pool; `NO` if not. 189 | 190 | */ 191 | 192 | - (BOOL)databasePool:(FMDatabasePool*)pool shouldAddDatabaseToPool:(FMDatabase*)database; 193 | 194 | /** Tells the delegate that database was added to the pool. 195 | 196 | @param pool The `FMDatabasePool` object. 197 | @param database The `FMDatabase` object. 198 | 199 | */ 200 | 201 | - (void)databasePool:(FMDatabasePool*)pool didAddDatabase:(FMDatabase*)database; 202 | 203 | @end 204 | 205 | -------------------------------------------------------------------------------- /CoreModel/FrameWorks/CoreFMDB/Lib/fmdb/FMDatabasePool.m: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabasePool.m 3 | // fmdb 4 | // 5 | // Created by August Mueller on 6/22/11. 6 | // Copyright 2011 Flying Meat Inc. All rights reserved. 7 | // 8 | 9 | #import "FMDatabasePool.h" 10 | #import "FMDatabase.h" 11 | 12 | @interface FMDatabasePool() 13 | 14 | - (void)pushDatabaseBackInPool:(FMDatabase*)db; 15 | - (FMDatabase*)db; 16 | 17 | @end 18 | 19 | 20 | @implementation FMDatabasePool 21 | @synthesize path=_path; 22 | @synthesize delegate=_delegate; 23 | @synthesize maximumNumberOfDatabasesToCreate=_maximumNumberOfDatabasesToCreate; 24 | @synthesize openFlags=_openFlags; 25 | 26 | 27 | + (instancetype)databasePoolWithPath:(NSString*)aPath { 28 | return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath]); 29 | } 30 | 31 | + (instancetype)databasePoolWithPath:(NSString*)aPath flags:(int)openFlags { 32 | return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath flags:openFlags]); 33 | } 34 | 35 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags { 36 | 37 | self = [super init]; 38 | 39 | if (self != nil) { 40 | _path = [aPath copy]; 41 | _lockQueue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL); 42 | _databaseInPool = FMDBReturnRetained([NSMutableArray array]); 43 | _databaseOutPool = FMDBReturnRetained([NSMutableArray array]); 44 | _openFlags = openFlags; 45 | } 46 | 47 | return self; 48 | } 49 | 50 | - (instancetype)initWithPath:(NSString*)aPath 51 | { 52 | // default flags for sqlite3_open 53 | return [self initWithPath:aPath flags:SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE]; 54 | } 55 | 56 | - (instancetype)init { 57 | return [self initWithPath:nil]; 58 | } 59 | 60 | 61 | - (void)dealloc { 62 | 63 | _delegate = 0x00; 64 | FMDBRelease(_path); 65 | FMDBRelease(_databaseInPool); 66 | FMDBRelease(_databaseOutPool); 67 | 68 | if (_lockQueue) { 69 | FMDBDispatchQueueRelease(_lockQueue); 70 | _lockQueue = 0x00; 71 | } 72 | #if ! __has_feature(objc_arc) 73 | [super dealloc]; 74 | #endif 75 | } 76 | 77 | 78 | - (void)executeLocked:(void (^)(void))aBlock { 79 | dispatch_sync(_lockQueue, aBlock); 80 | } 81 | 82 | - (void)pushDatabaseBackInPool:(FMDatabase*)db { 83 | 84 | if (!db) { // db can be null if we set an upper bound on the # of databases to create. 85 | return; 86 | } 87 | 88 | [self executeLocked:^() { 89 | 90 | if ([self->_databaseInPool containsObject:db]) { 91 | [[NSException exceptionWithName:@"Database already in pool" reason:@"The FMDatabase being put back into the pool is already present in the pool" userInfo:nil] raise]; 92 | } 93 | 94 | [self->_databaseInPool addObject:db]; 95 | [self->_databaseOutPool removeObject:db]; 96 | 97 | }]; 98 | } 99 | 100 | - (FMDatabase*)db { 101 | 102 | __block FMDatabase *db; 103 | 104 | 105 | [self executeLocked:^() { 106 | db = [self->_databaseInPool lastObject]; 107 | 108 | BOOL shouldNotifyDelegate = NO; 109 | 110 | if (db) { 111 | [self->_databaseOutPool addObject:db]; 112 | [self->_databaseInPool removeLastObject]; 113 | } 114 | else { 115 | 116 | if (self->_maximumNumberOfDatabasesToCreate) { 117 | NSUInteger currentCount = [self->_databaseOutPool count] + [self->_databaseInPool count]; 118 | 119 | if (currentCount >= self->_maximumNumberOfDatabasesToCreate) { 120 | NSLog(@"Maximum number of databases (%ld) has already been reached!", (long)currentCount); 121 | return; 122 | } 123 | } 124 | 125 | db = [FMDatabase databaseWithPath:self->_path]; 126 | shouldNotifyDelegate = YES; 127 | } 128 | 129 | //This ensures that the db is opened before returning 130 | #if SQLITE_VERSION_NUMBER >= 3005000 131 | BOOL success = [db openWithFlags:self->_openFlags]; 132 | #else 133 | BOOL success = [db open]; 134 | #endif 135 | if (success) { 136 | if ([self->_delegate respondsToSelector:@selector(databasePool:shouldAddDatabaseToPool:)] && ![self->_delegate databasePool:self shouldAddDatabaseToPool:db]) { 137 | [db close]; 138 | db = 0x00; 139 | } 140 | else { 141 | //It should not get added in the pool twice if lastObject was found 142 | if (![self->_databaseOutPool containsObject:db]) { 143 | [self->_databaseOutPool addObject:db]; 144 | 145 | if (shouldNotifyDelegate && [self->_delegate respondsToSelector:@selector(databasePool:didAddDatabase:)]) { 146 | [self->_delegate databasePool:self didAddDatabase:db]; 147 | } 148 | } 149 | } 150 | } 151 | else { 152 | NSLog(@"Could not open up the database at path %@", self->_path); 153 | db = 0x00; 154 | } 155 | }]; 156 | 157 | return db; 158 | } 159 | 160 | - (NSUInteger)countOfCheckedInDatabases { 161 | 162 | __block NSUInteger count; 163 | 164 | [self executeLocked:^() { 165 | count = [self->_databaseInPool count]; 166 | }]; 167 | 168 | return count; 169 | } 170 | 171 | - (NSUInteger)countOfCheckedOutDatabases { 172 | 173 | __block NSUInteger count; 174 | 175 | [self executeLocked:^() { 176 | count = [self->_databaseOutPool count]; 177 | }]; 178 | 179 | return count; 180 | } 181 | 182 | - (NSUInteger)countOfOpenDatabases { 183 | __block NSUInteger count; 184 | 185 | [self executeLocked:^() { 186 | count = [self->_databaseOutPool count] + [self->_databaseInPool count]; 187 | }]; 188 | 189 | return count; 190 | } 191 | 192 | - (void)releaseAllDatabases { 193 | [self executeLocked:^() { 194 | [self->_databaseOutPool removeAllObjects]; 195 | [self->_databaseInPool removeAllObjects]; 196 | }]; 197 | } 198 | 199 | - (void)inDatabase:(void (^)(FMDatabase *db))block { 200 | 201 | FMDatabase *db = [self db]; 202 | 203 | block(db); 204 | 205 | [self pushDatabaseBackInPool:db]; 206 | } 207 | 208 | - (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block { 209 | 210 | BOOL shouldRollback = NO; 211 | 212 | FMDatabase *db = [self db]; 213 | 214 | if (useDeferred) { 215 | [db beginDeferredTransaction]; 216 | } 217 | else { 218 | [db beginTransaction]; 219 | } 220 | 221 | 222 | block(db, &shouldRollback); 223 | 224 | if (shouldRollback) { 225 | [db rollback]; 226 | } 227 | else { 228 | [db commit]; 229 | } 230 | 231 | [self pushDatabaseBackInPool:db]; 232 | } 233 | 234 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { 235 | [self beginTransaction:YES withBlock:block]; 236 | } 237 | 238 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { 239 | [self beginTransaction:NO withBlock:block]; 240 | } 241 | #if SQLITE_VERSION_NUMBER >= 3007000 242 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block { 243 | 244 | static unsigned long savePointIdx = 0; 245 | 246 | NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++]; 247 | 248 | BOOL shouldRollback = NO; 249 | 250 | FMDatabase *db = [self db]; 251 | 252 | NSError *err = 0x00; 253 | 254 | if (![db startSavePointWithName:name error:&err]) { 255 | [self pushDatabaseBackInPool:db]; 256 | return err; 257 | } 258 | 259 | block(db, &shouldRollback); 260 | 261 | if (shouldRollback) { 262 | // We need to rollback and release this savepoint to remove it 263 | [db rollbackToSavePointWithName:name error:&err]; 264 | } 265 | [db releaseSavePointWithName:name error:&err]; 266 | 267 | [self pushDatabaseBackInPool:db]; 268 | 269 | return err; 270 | } 271 | #endif 272 | 273 | @end 274 | -------------------------------------------------------------------------------- /CoreModel/FrameWorks/CoreFMDB/Lib/fmdb/FMDatabaseQueue.h: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabaseQueue.h 3 | // fmdb 4 | // 5 | // Created by August Mueller on 6/22/11. 6 | // Copyright 2011 Flying Meat Inc. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "sqlite3.h" 11 | 12 | @class FMDatabase; 13 | 14 | /** To perform queries and updates on multiple threads, you'll want to use `FMDatabaseQueue`. 15 | 16 | Using a single instance of `` from multiple threads at once is a bad idea. It has always been OK to make a `` object *per thread*. Just don't share a single instance across threads, and definitely not across multiple threads at the same time. 17 | 18 | Instead, use `FMDatabaseQueue`. Here's how to use it: 19 | 20 | First, make your queue. 21 | 22 | FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath]; 23 | 24 | Then use it like so: 25 | 26 | [queue inDatabase:^(FMDatabase *db) { 27 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; 28 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; 29 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; 30 | 31 | FMResultSet *rs = [db executeQuery:@"select * from foo"]; 32 | while ([rs next]) { 33 | //… 34 | } 35 | }]; 36 | 37 | An easy way to wrap things up in a transaction can be done like this: 38 | 39 | [queue inTransaction:^(FMDatabase *db, BOOL *rollback) { 40 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; 41 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; 42 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; 43 | 44 | if (whoopsSomethingWrongHappened) { 45 | *rollback = YES; 46 | return; 47 | } 48 | // etc… 49 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]]; 50 | }]; 51 | 52 | `FMDatabaseQueue` will run the blocks on a serialized queue (hence the name of the class). So if you call `FMDatabaseQueue`'s methods from multiple threads at the same time, they will be executed in the order they are received. This way queries and updates won't step on each other's toes, and every one is happy. 53 | 54 | ### See also 55 | 56 | - `` 57 | 58 | @warning Do not instantiate a single `` object and use it across multiple threads. Use `FMDatabaseQueue` instead. 59 | 60 | @warning The calls to `FMDatabaseQueue`'s methods are blocking. So even though you are passing along blocks, they will **not** be run on another thread. 61 | 62 | */ 63 | 64 | @interface FMDatabaseQueue : NSObject { 65 | NSString *_path; 66 | dispatch_queue_t _queue; 67 | FMDatabase *_db; 68 | int _openFlags; 69 | } 70 | 71 | /** Path of database */ 72 | 73 | @property (atomic, retain) NSString *path; 74 | 75 | /** Open flags */ 76 | 77 | @property (atomic, readonly) int openFlags; 78 | 79 | ///---------------------------------------------------- 80 | /// @name Initialization, opening, and closing of queue 81 | ///---------------------------------------------------- 82 | 83 | /** Create queue using path. 84 | 85 | @param aPath The file path of the database. 86 | 87 | @return The `FMDatabaseQueue` object. `nil` on error. 88 | */ 89 | 90 | + (instancetype)databaseQueueWithPath:(NSString*)aPath; 91 | 92 | /** Create queue using path and specified flags. 93 | 94 | @param aPath The file path of the database. 95 | @param openFlags Flags passed to the openWithFlags method of the database 96 | 97 | @return The `FMDatabaseQueue` object. `nil` on error. 98 | */ 99 | + (instancetype)databaseQueueWithPath:(NSString*)aPath flags:(int)openFlags; 100 | 101 | /** Create queue using path. 102 | 103 | @param aPath The file path of the database. 104 | 105 | @return The `FMDatabaseQueue` object. `nil` on error. 106 | */ 107 | 108 | - (instancetype)initWithPath:(NSString*)aPath; 109 | 110 | /** Create queue using path and specified flags. 111 | 112 | @param aPath The file path of the database. 113 | @param openFlags Flags passed to the openWithFlags method of the database 114 | 115 | @return The `FMDatabaseQueue` object. `nil` on error. 116 | */ 117 | 118 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags; 119 | 120 | /** Returns the Class of 'FMDatabase' subclass, that will be used to instantiate database object. 121 | 122 | Subclasses can override this method to return specified Class of 'FMDatabase' subclass. 123 | 124 | @return The Class of 'FMDatabase' subclass, that will be used to instantiate database object. 125 | */ 126 | 127 | + (Class)databaseClass; 128 | 129 | /** Close database used by queue. */ 130 | 131 | - (void)close; 132 | 133 | ///----------------------------------------------- 134 | /// @name Dispatching database operations to queue 135 | ///----------------------------------------------- 136 | 137 | /** Synchronously perform database operations on queue. 138 | 139 | @param block The code to be run on the queue of `FMDatabaseQueue` 140 | */ 141 | 142 | - (void)inDatabase:(void (^)(FMDatabase *db))block; 143 | 144 | /** Synchronously perform database operations on queue, using transactions. 145 | 146 | @param block The code to be run on the queue of `FMDatabaseQueue` 147 | */ 148 | 149 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block; 150 | 151 | /** Synchronously perform database operations on queue, using deferred transactions. 152 | 153 | @param block The code to be run on the queue of `FMDatabaseQueue` 154 | */ 155 | 156 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block; 157 | 158 | ///----------------------------------------------- 159 | /// @name Dispatching database operations to queue 160 | ///----------------------------------------------- 161 | 162 | /** Synchronously perform database operations using save point. 163 | 164 | @param block The code to be run on the queue of `FMDatabaseQueue` 165 | */ 166 | 167 | #if SQLITE_VERSION_NUMBER >= 3007000 168 | // NOTE: you can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock. 169 | // If you need to nest, use FMDatabase's startSavePointWithName:error: instead. 170 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block; 171 | #endif 172 | 173 | @end 174 | 175 | -------------------------------------------------------------------------------- /CoreModel/FrameWorks/CoreFMDB/Lib/fmdb/FMDatabaseQueue.m: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabaseQueue.m 3 | // fmdb 4 | // 5 | // Created by August Mueller on 6/22/11. 6 | // Copyright 2011 Flying Meat Inc. All rights reserved. 7 | // 8 | 9 | #import "FMDatabaseQueue.h" 10 | #import "FMDatabase.h" 11 | 12 | /* 13 | 14 | Note: we call [self retain]; before using dispatch_sync, just incase 15 | FMDatabaseQueue is released on another thread and we're in the middle of doing 16 | something in dispatch_sync 17 | 18 | */ 19 | 20 | /* 21 | * A key used to associate the FMDatabaseQueue object with the dispatch_queue_t it uses. 22 | * This in turn is used for deadlock detection by seeing if inDatabase: is called on 23 | * the queue's dispatch queue, which should not happen and causes a deadlock. 24 | */ 25 | static const void * const kDispatchQueueSpecificKey = &kDispatchQueueSpecificKey; 26 | 27 | @implementation FMDatabaseQueue 28 | 29 | @synthesize path = _path; 30 | @synthesize openFlags = _openFlags; 31 | 32 | + (instancetype)databaseQueueWithPath:(NSString*)aPath { 33 | 34 | FMDatabaseQueue *q = [[self alloc] initWithPath:aPath]; 35 | 36 | FMDBAutorelease(q); 37 | 38 | return q; 39 | } 40 | 41 | + (instancetype)databaseQueueWithPath:(NSString*)aPath flags:(int)openFlags { 42 | 43 | FMDatabaseQueue *q = [[self alloc] initWithPath:aPath flags:openFlags]; 44 | 45 | FMDBAutorelease(q); 46 | 47 | return q; 48 | } 49 | 50 | + (Class)databaseClass { 51 | return [FMDatabase class]; 52 | } 53 | 54 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags { 55 | 56 | self = [super init]; 57 | 58 | if (self != nil) { 59 | 60 | _db = [[[self class] databaseClass] databaseWithPath:aPath]; 61 | FMDBRetain(_db); 62 | 63 | #if SQLITE_VERSION_NUMBER >= 3005000 64 | BOOL success = [_db openWithFlags:openFlags]; 65 | #else 66 | BOOL success = [_db open]; 67 | #endif 68 | if (!success) { 69 | NSLog(@"Could not create database queue for path %@", aPath); 70 | FMDBRelease(self); 71 | return 0x00; 72 | } 73 | 74 | _path = FMDBReturnRetained(aPath); 75 | 76 | _queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL); 77 | dispatch_queue_set_specific(_queue, kDispatchQueueSpecificKey, (__bridge void *)self, NULL); 78 | _openFlags = openFlags; 79 | } 80 | 81 | return self; 82 | } 83 | 84 | - (instancetype)initWithPath:(NSString*)aPath { 85 | 86 | // default flags for sqlite3_open 87 | return [self initWithPath:aPath flags:SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE]; 88 | } 89 | 90 | - (instancetype)init { 91 | return [self initWithPath:nil]; 92 | } 93 | 94 | 95 | - (void)dealloc { 96 | 97 | FMDBRelease(_db); 98 | FMDBRelease(_path); 99 | 100 | if (_queue) { 101 | FMDBDispatchQueueRelease(_queue); 102 | _queue = 0x00; 103 | } 104 | #if ! __has_feature(objc_arc) 105 | [super dealloc]; 106 | #endif 107 | } 108 | 109 | - (void)close { 110 | FMDBRetain(self); 111 | dispatch_sync(_queue, ^() { 112 | [self->_db close]; 113 | FMDBRelease(_db); 114 | self->_db = 0x00; 115 | }); 116 | FMDBRelease(self); 117 | } 118 | 119 | - (FMDatabase*)database { 120 | if (!_db) { 121 | _db = FMDBReturnRetained([FMDatabase databaseWithPath:_path]); 122 | 123 | #if SQLITE_VERSION_NUMBER >= 3005000 124 | BOOL success = [_db openWithFlags:_openFlags]; 125 | #else 126 | BOOL success = [_db open]; 127 | #endif 128 | if (!success) { 129 | NSLog(@"FMDatabaseQueue could not reopen database for path %@", _path); 130 | FMDBRelease(_db); 131 | _db = 0x00; 132 | return 0x00; 133 | } 134 | } 135 | 136 | return _db; 137 | } 138 | 139 | - (void)inDatabase:(void (^)(FMDatabase *db))block { 140 | /* Get the currently executing queue (which should probably be nil, but in theory could be another DB queue 141 | * and then check it against self to make sure we're not about to deadlock. */ 142 | FMDatabaseQueue *currentSyncQueue = (__bridge id)dispatch_get_specific(kDispatchQueueSpecificKey); 143 | assert(currentSyncQueue != self && "inDatabase: was called reentrantly on the same queue, which would lead to a deadlock"); 144 | 145 | FMDBRetain(self); 146 | 147 | dispatch_sync(_queue, ^() { 148 | 149 | FMDatabase *db = [self database]; 150 | block(db); 151 | 152 | if ([db hasOpenResultSets]) { 153 | NSLog(@"Warning: there is at least one open result set around after performing [FMDatabaseQueue inDatabase:]"); 154 | 155 | #if defined(DEBUG) && DEBUG 156 | NSSet *openSetCopy = FMDBReturnAutoreleased([[db valueForKey:@"_openResultSets"] copy]); 157 | for (NSValue *rsInWrappedInATastyValueMeal in openSetCopy) { 158 | FMResultSet *rs = (FMResultSet *)[rsInWrappedInATastyValueMeal pointerValue]; 159 | NSLog(@"query: '%@'", [rs query]); 160 | } 161 | #endif 162 | } 163 | }); 164 | 165 | FMDBRelease(self); 166 | } 167 | 168 | 169 | - (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block { 170 | FMDBRetain(self); 171 | dispatch_sync(_queue, ^() { 172 | 173 | BOOL shouldRollback = NO; 174 | 175 | if (useDeferred) { 176 | [[self database] beginDeferredTransaction]; 177 | } 178 | else { 179 | [[self database] beginTransaction]; 180 | } 181 | 182 | block([self database], &shouldRollback); 183 | 184 | if (shouldRollback) { 185 | [[self database] rollback]; 186 | } 187 | else { 188 | [[self database] commit]; 189 | } 190 | }); 191 | 192 | FMDBRelease(self); 193 | } 194 | 195 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { 196 | [self beginTransaction:YES withBlock:block]; 197 | } 198 | 199 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { 200 | [self beginTransaction:NO withBlock:block]; 201 | } 202 | 203 | #if SQLITE_VERSION_NUMBER >= 3007000 204 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block { 205 | 206 | static unsigned long savePointIdx = 0; 207 | __block NSError *err = 0x00; 208 | FMDBRetain(self); 209 | dispatch_sync(_queue, ^() { 210 | 211 | NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++]; 212 | 213 | BOOL shouldRollback = NO; 214 | 215 | if ([[self database] startSavePointWithName:name error:&err]) { 216 | 217 | block([self database], &shouldRollback); 218 | 219 | if (shouldRollback) { 220 | // We need to rollback and release this savepoint to remove it 221 | [[self database] rollbackToSavePointWithName:name error:&err]; 222 | } 223 | [[self database] releaseSavePointWithName:name error:&err]; 224 | 225 | } 226 | }); 227 | FMDBRelease(self); 228 | return err; 229 | } 230 | #endif 231 | 232 | @end 233 | -------------------------------------------------------------------------------- /CoreModel/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /CoreModel/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 16/4/2. 6 | // Copyright © 2016年 冯成林. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /CoreModel/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 16/4/2. 6 | // Copyright © 2016年 冯成林. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view, typically from a nib. 20 | } 21 | 22 | - (void)didReceiveMemoryWarning { 23 | [super didReceiveMemoryWarning]; 24 | // Dispose of any resources that can be recreated. 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /CoreModel/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // CoreModel 4 | // 5 | // Created by 冯成林 on 16/4/2. 6 | // Copyright © 2016年 冯成林. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | --------------------------------------------------------------------------------