Demo/EZOpensdk_iOS_4.15.1_build20201104/Demo/EZOpenSDKDemo.xcodeproj/project.pbxproj
@@ -142,6 +142,7 @@ B91B6E5225EC9DFF00915F73 /* ResponseData.m in Sources */ = {isa = PBXBuildFile; fileRef = B91B6E5125EC9DFF00915F73 /* ResponseData.m */; }; B95004F125B927D0002D3C58 /* com.hri.hpc.mobile.ios.player.metallib in Resources */ = {isa = PBXBuildFile; fileRef = B95004F025B927D0002D3C58 /* com.hri.hpc.mobile.ios.player.metallib */; }; B95004F725B929EF002D3C58 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B95004F625B929EF002D3C58 /* Launch Screen.storyboard */; }; B95AB8792697F8F8007BC8D7 /* HDLAlarmInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = B95AB8782697F8F8007BC8D7 /* HDLAlarmInfo.m */; }; B96C125625E8C5EA00B69941 /* EZSDK.m in Sources */ = {isa = PBXBuildFile; fileRef = B96C125525E8C5EA00B69941 /* EZSDK.m */; }; B96C126725E8F64800B69941 /* EZHttpUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B96C126625E8F64800B69941 /* EZHttpUtil.m */; }; B9E6208D26969E170054E443 /* NSObject+YYModel.m in Sources */ = {isa = PBXBuildFile; fileRef = B9E6208A26969E170054E443 /* NSObject+YYModel.m */; }; @@ -571,6 +572,8 @@ B91B6E5125EC9DFF00915F73 /* ResponseData.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ResponseData.m; sourceTree = "<group>"; }; B95004F025B927D0002D3C58 /* com.hri.hpc.mobile.ios.player.metallib */ = {isa = PBXFileReference; lastKnownFileType = "archive.metal-library"; path = com.hri.hpc.mobile.ios.player.metallib; sourceTree = "<group>"; }; B95004F625B929EF002D3C58 /* Launch Screen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; }; B95AB8772697F8F8007BC8D7 /* HDLAlarmInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HDLAlarmInfo.h; sourceTree = "<group>"; }; B95AB8782697F8F8007BC8D7 /* HDLAlarmInfo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HDLAlarmInfo.m; sourceTree = "<group>"; }; B96C125425E8C5EA00B69941 /* EZSDK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZSDK.h; sourceTree = "<group>"; }; B96C125525E8C5EA00B69941 /* EZSDK.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZSDK.m; sourceTree = "<group>"; }; B96C126525E8F64800B69941 /* EZHttpUtil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EZHttpUtil.h; sourceTree = "<group>"; }; @@ -1041,6 +1044,8 @@ B96C126625E8F64800B69941 /* EZHttpUtil.m */, B91B6E5025EC9DFF00915F73 /* ResponseData.h */, B91B6E5125EC9DFF00915F73 /* ResponseData.m */, B95AB8772697F8F8007BC8D7 /* HDLAlarmInfo.h */, B95AB8782697F8F8007BC8D7 /* HDLAlarmInfo.m */, ); path = Global; sourceTree = "<group>"; @@ -1803,6 +1808,7 @@ B9EA4E4825C7E7AB000FFDA2 /* MJRefreshFooter.m in Sources */, B9EA4E3F25C7E7AB000FFDA2 /* MJRefreshBackGifFooter.m in Sources */, 0D5015181BF8B7FF00F13269 /* DACircularProgressView.m in Sources */, B95AB8792697F8F8007BC8D7 /* HDLAlarmInfo.m in Sources */, B9EA4E4025C7E7AB000FFDA2 /* MJRefreshBackStateFooter.m in Sources */, 0DCE0C0A1BE22761000EA68A /* UIView+DDKit.m in Sources */, B9EA4E4C25C7E7AB000FFDA2 /* MJRefreshComponent.m in Sources */, Demo/EZOpensdk_iOS_4.15.1_build20201104/Demo/EZOpenSDKDemo/Global/EZHttpUtil.h
@@ -48,6 +48,24 @@ */ - (void)deleteDeviceByHDL:(NSString *)deviceSerial completion:(void (^)(ResponseData *responseData))completion; /** * 根据设备序列号获取告警信息列表 */ - (void)getAlarmList:(NSString *)deviceSerial pageNo:(NSInteger)pageNo pageSize:(NSInteger)pageSize completion:(void (^)(ResponseData *responseData))completion; /** * 批量删除报警记录 */ - (void)deleteAlarmMessage:(NSArray *)alarmIds completion:(void (^)(ResponseData *responseData))completion; /** * 批量标记报警记录已读 */ - (void)readAlarmMessage:(NSArray *)alarmIds completion:(void (^)(ResponseData *responseData))completion; @end Demo/EZOpensdk_iOS_4.15.1_build20201104/Demo/EZOpenSDKDemo/Global/EZHttpUtil.m
@@ -10,6 +10,7 @@ #import <Foundation/Foundation.h> #import <CommonCrypto/CommonDigest.h> #import "AFNetworking.h" #import "YYModel.h" #define TestRequestHttpsHost @"https://test-gz.hdlcontrol.com" #pragma mark API @@ -18,6 +19,9 @@ #define API_POST_EZ_ChildDelDevice @"/home-wisdom/platform/yingshi/child/deleteDevice" #define API_POST_EZ_RefreshToken @"/smart-footstone/member/oauth/login" #define API_POST_EZ_GetAlarmList @"/home-wisdom/platform/yingshi/alarm/records"//获取报警消息 #define API_POST_EZ_DeleteAlarmMes @"/home-wisdom/platform/yingshi/alarm/delete"//删除报警消息 #define API_POST_EZ_ReadAlarmMes @"/home-wisdom/platform/yingshi/alarm/updateChecked"//标记报警消息已读 #pragma mark APP_KEY #define APP_KEY @"HDL-HOME-APP-TEST" @@ -126,6 +130,70 @@ } /** * 根据设备序列号获取告警信息列表 */ - (void)getAlarmList:(NSString *)deviceSerial pageNo:(NSInteger)pageNo pageSize:(NSInteger)pageSize completion:(void (^)(ResponseData *responseData))completion{ //1.设置请求参数 NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; [parameters setValue:deviceSerial forKey:@"deviceSerial"]; [parameters setValue:[GlobalKit shareKit].hdlHomeId forKey:@"homeId"]; [parameters setValue:[NSString stringWithFormat:@"%ld",(long)pageSize] forKey:@"pageSize"]; [parameters setValue:[NSString stringWithFormat:@"%ld",(long)pageNo] forKey:@"pageNo"]; parameters = [self GetSignRequestDictionary:parameters]; NSLog(@"HDLpageNo:%ld",(long)pageNo); [self requestHttpsPost:API_POST_EZ_GetAlarmList parameters:parameters completion:^(ResponseData *responseData) { if (completion) { completion (responseData); } }]; } /** * 批量删除报警记录 */ - (void)deleteAlarmMessage:(NSArray *)alarmIds completion:(void (^)(ResponseData *responseData))completion{ //1.设置请求参数 NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; [parameters setValue:[alarmIds yy_modelToJSONObject] forKey:@"alarmIds"]; parameters = [self GetSignRequestDictionary:parameters]; [self requestHttpsPost:API_POST_EZ_DeleteAlarmMes parameters:parameters completion:^(ResponseData *responseData) { if (completion) { completion (responseData); } }]; } /** * 批量标记报警记录已读 */ - (void)readAlarmMessage:(NSArray *)alarmIds completion:(void (^)(ResponseData *responseData))completion{ //1.设置请求参数 NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; [parameters setValue:@"1" forKey:@"isChecked"]; [parameters setValue:[alarmIds yy_modelToJSONObject] forKey:@"alarmIds"]; parameters = [self GetSignRequestDictionary:parameters]; [self requestHttpsPost:API_POST_EZ_ReadAlarmMes parameters:parameters completion:^(ResponseData *responseData) { if (completion) { completion (responseData); } }]; } /// 刷新token /// @param block 结果 @@ -143,7 +211,7 @@ if (block) { if (responseData) { if(responseData.success){ [EZSDK setHDlAccessToken: [[EZSDK sharedInstance] setHDlAccessToken: [NSString stringWithFormat:@"%@%@",responseData.data[@"headerPrefix"], responseData.data[@"accessToken"]] refreshToken:responseData.data[@"refreshToken"]]; Demo/EZOpensdk_iOS_4.15.1_build20201104/Demo/EZOpenSDKDemo/Global/EZSDK.h
@@ -9,46 +9,50 @@ #import "EZDeviceInfo.h" @interface EZSDK : NSObject ///sharedInstance + (instancetype)sharedInstance; /** 初始化SDK 传入国内版key 和海外版globalAppKey */ + (BOOL)initLibWithAppKey:(NSString *)appKey globalAppKey:(NSString *)globalAppKey; - (BOOL)initLibWithAppKey:(NSString *)appKey globalAppKey:(NSString *)globalAppKey; /** 设置SDK的accessToken */ +(void)setEZAccessToken:(NSString *) accessToken; - (void)setEZAccessToken:(NSString *) accessToken; /** 设置HDLSDK的accessToken */ +(void)setHDlAccessToken:(NSString *)accessToken refreshToken:(NSString *) refreshToken; - (void)setHDlAccessToken:(NSString *)accessToken refreshToken:(NSString *) refreshToken; /** 设置SDK的河东接口的requestHttpsHost和平台 标识,1.on+(默认) 2.evoyo */ +(void)setRequestHttpsHostAndPlatform:(NSString *) requestHttpsHost platform:(int)platform homeId:(NSString *)homeId; - (void)setRequestHttpsHostAndPlatform:(NSString *) requestHttpsHost platform:(int)platform homeId:(NSString *)homeId; /** 直接跳转到萤石摄像头列表 */ +(void)go2EZvizMonitor; - (void)go2EZvizMonitor; /** 跳转添加添加设备 */ +(void)addEzvizMonitor; - (void)addEzvizMonitor; /** 查看视频监控直播 */ +(void)Play:(EZDeviceInfo*)deviceInfo; - (void)Play:(EZDeviceInfo*)deviceInfo; /// 指定序列号 查看视频监控直播 /// @param deviceSerial 序列号 +(void)PlayWithDeviceSerial:(NSString *)deviceSerial; - (void)PlayWithDeviceSerial:(NSString *)deviceSerial; /** 打开摄像头设置页面 */ +(void)setting:(EZDeviceInfo*)deviceInfo; - (void)setting:(EZDeviceInfo*)deviceInfo; /** 回放播放历史 */ +(void)playBackVideo:(EZDeviceInfo*)deviceInfo; - (void)playBackVideo:(EZDeviceInfo*)deviceInfo; @end Demo/EZOpensdk_iOS_4.15.1_build20201104/Demo/EZOpenSDKDemo/Global/EZSDK.m
@@ -18,12 +18,24 @@ #import "EZPlaybackViewController.h" #import "EZDeviceTableViewController.h" #import "EZHCNetDeviceSDK.h" #import "EZMessagePhotoViewController.h" @implementation EZSDK /// + (instancetype)sharedInstance{ static EZSDK *instance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ if (!instance) { instance = [[EZSDK alloc] init]; } }); return instance; } static BOOL isHavelibInit=NO; @@ -31,7 +43,7 @@ 初始化SDK 传入国内版key 和海外版globalAppKey */ + (BOOL)initLibWithAppKey:(NSString *)appKey globalAppKey:(NSString *)globalAppKey - (BOOL)initLibWithAppKey:(NSString *)appKey globalAppKey:(NSString *)globalAppKey { if (!isHavelibInit) { @@ -57,7 +69,7 @@ /** 设置SDK的accessToken */ +(void)setEZAccessToken:(NSString *) accessToken -(void)setEZAccessToken:(NSString *) accessToken { [[GlobalKit shareKit] setAccessToken:accessToken]; [EZOPENSDK setAccessToken:accessToken]; @@ -66,7 +78,7 @@ /** 设置HDLSDK的accessToken */ +(void)setHDlAccessToken:(NSString *) accessToken refreshToken:(NSString *) refreshToken -(void)setHDlAccessToken:(NSString *) accessToken refreshToken:(NSString *) refreshToken { [[GlobalKit shareKit] setHdlAccessToken:accessToken]; [[GlobalKit shareKit] setHdlRefreshToken:refreshToken]; @@ -74,14 +86,14 @@ /** 设置SDK的河东接口的requestHttpsHost和平台 标识,1.on+(默认) 2.evoyo */ +(void)setRequestHttpsHostAndPlatform:(NSString *) requestHttpsHost platform:(int)platform homeId:(NSString *)homeId{ -(void)setRequestHttpsHostAndPlatform:(NSString *) requestHttpsHost platform:(int)platform homeId:(NSString *)homeId{ [[GlobalKit shareKit] setGlobalRequestHttpsHost:requestHttpsHost]; [[GlobalKit shareKit] setHdlPlatform:platform]; [[GlobalKit shareKit] setHdlHomeId:homeId]; } //获取当前屏幕显示的viewcontroller (这里面获取的相当于rootViewController) +(UINavigationController *)getCurrentVC -(UINavigationController *)getCurrentVC { UIWindow * window = [[UIApplication sharedApplication] keyWindow]; if (window.windowLevel != UIWindowLevelNormal) @@ -104,7 +116,7 @@ /** 直接跳转到萤石摄像头列表 */ +(void)go2EZvizMonitor -(void)go2EZvizMonitor { // NSLog(@"go2EZvizMonitor"); //获取EZMain的stroyboard文件 @@ -121,7 +133,7 @@ /** 跳转添加添加设备 */ +(void)addEzvizMonitor -(void)addEzvizMonitor { // NSLog(@"添加摄像头"); if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) { @@ -139,7 +151,7 @@ /** 查看视频监控直播 */ +(void)Play:(EZDeviceInfo*)deviceInfo -(void)Play:(EZDeviceInfo*)deviceInfo { UIStoryboard *addDeviceStoryBoard = [UIStoryboard storyboardWithName:@"EZMain" bundle:nil]; EZLivePlayViewController *rootViewController = [addDeviceStoryBoard instantiateViewControllerWithIdentifier:@"EZLivePlayViewController"]; @@ -155,7 +167,7 @@ /// 指定序列号播放 /// @param deviceSerial 序列号 +(void)PlayWithDeviceSerial:(NSString *)deviceSerial{ -(void)PlayWithDeviceSerial:(NSString *)deviceSerial{ //获取设备列表接口 [EZOpenSDK getDeviceInfo:deviceSerial completion:^(EZDeviceInfo *deviceInfo, NSError *error) { if(error) @@ -172,7 +184,7 @@ /** 打开摄像头设置页面 */ +(void)setting:(EZDeviceInfo*)deviceInfo -(void)setting:(EZDeviceInfo*)deviceInfo { UIStoryboard *settingStoryBoard=[UIStoryboard storyboardWithName:@"EZMain" bundle:nil]; EZSettingViewController *settingVC=[settingStoryBoard instantiateViewControllerWithIdentifier:@"EZSettingViewController"]; @@ -184,7 +196,7 @@ /** 回放播放历史 */ +(void)playBackVideo:(EZDeviceInfo*)deviceInfo -(void)playBackVideo:(EZDeviceInfo*)deviceInfo { UIStoryboard *playBackStoryBoard=[UIStoryboard storyboardWithName:@"EZMain" bundle:nil]; EZPlaybackViewController *playBackVC=[playBackStoryBoard instantiateViewControllerWithIdentifier:@"EZPlaybackViewController"]; @@ -193,6 +205,17 @@ [[self getCurrentVC] pushViewController:playBackVC animated:YES]; } //// //-(void)goToEZMessagePhotoVC:(EZAlarmInfo*)alarmInfo{ // UIStoryboard *addDeviceStoryBoard = [UIStoryboard storyboardWithName:@"EZMain" bundle:nil]; // EZMessagePhotoViewController *rootViewController = [addDeviceStoryBoard instantiateViewControllerWithIdentifier:@"EZMessagePhotoViewController"]; // // NSLog(@"play--iphone--rootViewController"); // rootViewController.info = alarmInfo; //// NSLog(@"play--iphone--deviceName -%@",rootViewController.deviceInfo.deviceName); //// rootViewController.cameraIndex=0; // [[self getCurrentVC] setNavigationBarHidden:NO]; // [[self getCurrentVC] pushViewController:rootViewController animated:YES]; //} //+(void)MonitorPushMessage:(NSString *)MonitorType ID:(NSString *)ID //{ Demo/EZOpensdk_iOS_4.15.1_build20201104/Demo/EZOpenSDKDemo/Global/GlobalKit.m
@@ -45,7 +45,6 @@ _accessToken = accessToken; [[NSUserDefaults standardUserDefaults] setObject:accessToken?:@"" forKey:EZOpenSDKAccessToken]; [[NSUserDefaults standardUserDefaults] synchronize]; [EZOPENSDK setAccessToken:[GlobalKit shareKit].accessToken]; } - (void)setHdlAccessToken:(NSString *)hdlAccessToken Demo/EZOpensdk_iOS_4.15.1_build20201104/Demo/EZOpenSDKDemo/Global/HDLAlarmInfo.h
New file @@ -0,0 +1,56 @@ // // HDLAlarmInfo.h // EZOpenSDKDemo // // Created by 陈嘉乐 on 2021/7/9. // Copyright © 2021 hikvision. All rights reserved. // #import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN @interface HDLAlarmInfo : NSObject /// 主键ID @property (nonatomic, copy) NSString *ysId; /// 告警ID @property (nonatomic, copy) NSString *alarmId; /// 通道号 @property (nonatomic, assign) NSInteger channelNo; /// 设备序列号 @property (nonatomic, copy) NSString *deviceSerial; /// 告警名称 @property (nonatomic, copy) NSString *alarmName; /// 告警图片 @property (nonatomic, copy) NSString *alarmPicUrl; /// 告警开始时间 @property (nonatomic, strong) NSDate *alarmTime; /// 住宅Id @property (nonatomic, copy) NSString *homeId; /// 告警类型 @property (nonatomic, copy) NSString *alarmType; /// 是否已读 @property (nonatomic, assign) NSInteger isChecked; /// 是否加密 @property (nonatomic, assign) NSInteger isEncrypt; //@property (nonatomic, assign) NSInteger deleted; //@property (nonatomic, copy) NSString *tenantID; @property (nonatomic, copy) NSString *createTime; //@property (nonatomic, copy) NSString *modifyTime; //@property (nonatomic, copy) NSString *region; //@property (nonatomic, copy) NSString *identifier; -(NSDate *)getAlarmStartTime; @end @interface HDLAlarmInfoData : NSObject @property (nonatomic, copy) NSArray<HDLAlarmInfo *> *list; @property (nonatomic, assign) NSInteger totalCount; @property (nonatomic, assign) NSInteger totalPage; @property (nonatomic, assign) NSInteger pageNo; @property (nonatomic, assign) NSInteger pageSize; @end NS_ASSUME_NONNULL_END Demo/EZOpensdk_iOS_4.15.1_build20201104/Demo/EZOpenSDKDemo/Global/HDLAlarmInfo.m
New file @@ -0,0 +1,25 @@ // // HDLAlarmInfo.m // EZOpenSDKDemo // // Created by 陈嘉乐 on 2021/7/9. // Copyright © 2021 hikvision. All rights reserved. // #import "HDLAlarmInfo.h" @implementation HDLAlarmInfo -(NSDate *)getAlarmStartTime{ NSTimeInterval time = [_createTime doubleValue]; // return [NSDate dateWithTimeIntervalSince1970:time];; return [NSDate dateWithTimeIntervalSince1970:time/1000]; } @end @implementation HDLAlarmInfoData + (NSDictionary *)modelContainerPropertyGenericClass { return @{@"list" : [HDLAlarmInfo class]}; } @end Demo/EZOpensdk_iOS_4.15.1_build20201104/Demo/EZOpenSDKDemo/TableViewCells/MessageListCell.h
@@ -7,7 +7,7 @@ // #import <UIKit/UIKit.h> #import "EZAlarmInfo.h" #import "HDLAlarmInfo.h" @interface MessageListCell : UITableViewCell @@ -18,6 +18,6 @@ @property (nonatomic, weak) IBOutlet UIImageView *readStatusIcon; @property (nonatomic, copy) NSString *deviceSerial; - (void)setAlarmInfo:(EZAlarmInfo *)info; - (void)setAlarmInfo:(HDLAlarmInfo *)info; @end Demo/EZOpensdk_iOS_4.15.1_build20201104/Demo/EZOpenSDKDemo/TableViewCells/MessageListCell.m
@@ -9,7 +9,7 @@ #import "MessageListCell.h" #import "UIImageView+EzvizOpenSDK.h" #import "UIImageView+AFNetworking.h" #import "HDLAlarmInfo.h" #import "DDKit.h" static dispatch_semaphore_t ezviz_sema; //全局信号量 @@ -55,13 +55,13 @@ dispatch_semaphore_signal(ezviz_sema); } - (void)setAlarmInfo:(EZAlarmInfo *)info - (void)setAlarmInfo:(HDLAlarmInfo *)info { NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.dateFormat = @"HH:mm:ss"; self.timeLabel.text = [formatter stringFromDate:info.alarmStartTime]; self.timeLabel.text = [formatter stringFromDate:[info getAlarmStartTime]]; self.readStatusIcon.hidden = NO; if(info.isRead) if(info.isChecked) { self.readStatusIcon.hidden = YES; } Demo/EZOpensdk_iOS_4.15.1_build20201104/Demo/EZOpenSDKDemo/UIViewControllers/EZMessageListViewController.m
@@ -15,6 +15,8 @@ #import "MBProgressHUD.h" #import "EZMessagePhotoViewController.h" #import "NSDate-Utilities.h" #import "HDLAlarmInfo.h" #import "YYModel.h" #define EZMessageListPageSize 10 @@ -31,7 +33,7 @@ @property (nonatomic) NSInteger currentIndex; @property (nonatomic, strong) NSMutableArray *messageList; @property (nonatomic, strong) NSDateFormatter *dateFormatter; @property (nonatomic, strong) NSMutableArray *sections; //@property (nonatomic, strong) NSMutableArray *sections; @property (nonatomic) NSInteger lastIndex; @property (nonatomic, weak) IBOutlet UIImageView *noMessage; @property (nonatomic, weak) IBOutlet UILabel *noMessageLabel; @@ -59,16 +61,16 @@ // self.navigationItem.rightBarButtonItem = self.editButtonItem; self.title = NSLocalizedString(@"dmessage_title", @"消息"); [EZOPENSDK getUnreadMessageCount:self.deviceInfo.deviceSerial messageType:EZMessageTypeAlarm completion:^(NSInteger count, NSError *error) { self.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"dmessage_title", @"消息"), (int)count]; }]; // [EZOPENSDK getUnreadMessageCount:self.deviceInfo.deviceSerial messageType:EZMessageTypeAlarm completion:^(NSInteger count, NSError *error) { // self.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"dmessage_title", @"消息"), (int)count]; // }]; if(!_messageList) _messageList = [NSMutableArray new]; if(!self.messageList) self.messageList = [NSMutableArray new]; if(!_sections) _sections = [NSMutableArray new]; // if(!_sections) // _sections = [NSMutableArray new]; // if(!_selectedMessageArray) _selectedMessageArray = [NSMutableArray new]; @@ -99,35 +101,20 @@ #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return _sections.count; return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (_sections.count == 1) { return _messageList.count; } else { if (section == 0) { return [_sections[1][@"index"] integerValue]; } else if (section == _sections.count - 1) { return _messageList.count - [_sections[section][@"index"] integerValue]; } else { return [_sections[section + 1][@"index"] integerValue] - [_sections[section][@"index"] integerValue]; } } return self.messageList.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // Configure the cell... MessageListCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MessageCell" forIndexPath:indexPath]; cell.deviceSerial = self.deviceInfo.deviceSerial; EZAlarmInfo *info = [_messageList dd_objectAtIndex:[[_sections dd_objectAtIndex:indexPath.section][@"index"] integerValue] + indexPath.row]; HDLAlarmInfo *info = self.messageList[indexPath.row]; [cell setAlarmInfo:info]; if (tableView.allowsMultipleSelectionDuringEditing == YES) { if([_selectedMessageArray containsObject:info]) @@ -150,7 +137,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { EZAlarmInfo *info = [_messageList dd_objectAtIndex:[[_sections dd_objectAtIndex:indexPath.section][@"index"] integerValue] + indexPath.row]; HDLAlarmInfo *info = self.messageList[indexPath.row]; if(tableView.allowsMultipleSelectionDuringEditing) { if ([self.selectedMessageArray containsObject:info]) @@ -165,14 +152,14 @@ { self.deleteSelected.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"delete", @"删除"),(int)[self.selectedMessageArray count]]; self.deleteSelected.enabled = YES; self.readAll.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"dmessage_read", @"标记已读"),(int)[self.selectedMessageArray count]]; self.readAll.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"message_read", @"标记已读"),(int)[self.selectedMessageArray count]]; self.readAll.enabled = YES; } else { self.deleteSelected.title = NSLocalizedString(@"delete", @"删除"); self.deleteSelected.enabled = NO; self.readAll.title = NSLocalizedString(@"dmessage_read", @"标记已读"); self.readAll.title = NSLocalizedString(@"message_read", @"标记已读"); self.readAll.enabled = NO; } return; @@ -180,16 +167,16 @@ MessageListCell *cell = [tableView cellForRowAtIndexPath:indexPath]; [self performSegueWithIdentifier:@"go2MessagePhoto" sender:@{@"image":cell.actionImageView.image?:[UIImage new], @"alarmInfo":info}]; [EZOPENSDK getUnreadMessageCount:self.deviceInfo.deviceSerial messageType:EZMessageTypeAlarm completion:^(NSInteger count, NSError *error) { self.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"dmessage_title", @"消息"), (int)count]; }]; // [EZOPENSDK getUnreadMessageCount:self.deviceInfo.deviceSerial messageType:EZMessageTypeAlarm completion:^(NSInteger count, NSError *error) { // self.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"dmessage_title", @"消息"), (int)count]; // }]; } - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { if(tableView.allowsMultipleSelectionDuringEditing) { EZAlarmInfo *info = [_messageList dd_objectAtIndex:[[_sections dd_objectAtIndex:indexPath.section][@"index"] integerValue] + indexPath.row]; HDLAlarmInfo *info = self.messageList[indexPath.row];; if ([self.selectedMessageArray containsObject:info]) { [self.selectedMessageArray removeObject:info]; @@ -202,14 +189,14 @@ { self.deleteSelected.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"delete", @"删除"),(int)[self.selectedMessageArray count]]; self.deleteSelected.enabled = YES; self.readAll.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"dmessage_read", @"标记已读"),(int)[self.selectedMessageArray count]]; self.readAll.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"message_read", @"标记已读"),(int)[self.selectedMessageArray count]]; self.readAll.enabled = YES; } else { self.deleteSelected.title = NSLocalizedString(@"delete", @"删除"); self.deleteSelected.enabled = NO; self.readAll.title = NSLocalizedString(@"dmessage_read", @"标记已读"); self.readAll.title = NSLocalizedString(@"message_read", @"标记已读"); self.readAll.enabled = NO; } } @@ -220,33 +207,48 @@ return 75.0f; } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 20.0f; } //- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section //{ // return 20.0f; //} - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 20)]; NSString *key = [self.sections dd_objectAtIndex:section][@"date"]; headerLabel.text = [NSString stringWithFormat:@" %@",[self dateStringWithUserDefine:key]]; headerLabel.font = [UIFont systemFontOfSize:14.0f]; headerLabel.backgroundColor = [UIColor dd_hexStringToColor:@"0xf0f0f3"]; return headerLabel; } //- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section //{ // UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 20)]; // NSString *key = [self.sections dd_objectAtIndex:section][@"date"]; // headerLabel.text = [NSString stringWithFormat:@" %@",[self dateStringWithUserDefine:key]]; // headerLabel.font = [UIFont systemFontOfSize:14.0f]; // headerLabel.backgroundColor = [UIColor dd_hexStringToColor:@"0xf0f0f3"]; // return headerLabel; //} // Override to support editing the table view. - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { // Delete the row from the data source EZAlarmInfo *info = [_messageList dd_objectAtIndex:[[_sections dd_objectAtIndex:indexPath.section][@"index"] integerValue] + indexPath.row]; HDLAlarmInfo *info = self.messageList[indexPath.row];; MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; hud.labelText = NSLocalizedString(@"message_deleting", @"正在删除,请稍候..."); [EZOPENSDK deleteAlarm:@[info.alarmId] completion:^(NSError *error) { // [EZOPENSDK deleteAlarm:@[info.alarmId] completion:^(NSError *error) { // [hud hide:YES]; // [self.messageList removeObject:info]; // [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; // }]; __weak __typeof(self)weakSelf = self; [[EZHttpUtil sharedManager] deleteAlarmMessage:@[info.ysId] completion:^(ResponseData * responseData) { if (responseData.success) { [hud hide:YES]; [_messageList removeObject:info]; [weakSelf.messageList removeObject:info]; [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; }else{ hud.labelText = NSLocalizedString(@"setting_opration_fail", @"操作失败"); hud.mode = MBProgressHUDModeText; [hud hide:YES afterDelay:1.2]; } }]; } } @@ -274,29 +276,51 @@ hud.labelText = NSLocalizedString(@"message_deleting", @"正在删除,请稍候..."); NSMutableArray *alarmIds = [NSMutableArray new]; for (int i = 0; i < self.selectedMessageArray.count; i++) { EZAlarmInfo *info = [self.selectedMessageArray dd_objectAtIndex:i]; [alarmIds addObject:info.alarmId]; HDLAlarmInfo *info = [self.selectedMessageArray dd_objectAtIndex:i]; [alarmIds addObject:info.ysId]; } [EZOPENSDK deleteAlarm:alarmIds completion:^(NSError *error) { if(error) { hud.labelText = error.localizedDescription; // [EZOPENSDK deleteAlarm:alarmIds completion:^(NSError *error) { // if(error) // { // hud.labelText = error.localizedDescription; // hud.mode = MBProgressHUDModeText; // [hud hide:YES afterDelay:1.2]; // } // else // { // [hud hide:YES]; // } // [self.messageList removeObjectsInArray:self.selectedMessageArray]; // [self editTableView:self.navigationItem.rightBarButtonItem]; // if(self.messageList.count > 0){ // [self.tableView reloadData]; // } // else // { // [self.tableView.mj_header beginRefreshing]; // } // }]; __weak __typeof(self)weakSelf = self; [[EZHttpUtil sharedManager] deleteAlarmMessage:alarmIds completion:^(ResponseData * responseData) { [hud hide:YES]; if (responseData.success) { [hud hide:YES]; }else{ hud.labelText = NSLocalizedString(@"setting_opration_fail", @"操作失败"); hud.mode = MBProgressHUDModeText; [hud hide:YES afterDelay:1.2]; } else { [hud hide:YES]; } [self.messageList removeObjectsInArray:self.selectedMessageArray]; [self editTableView:self.navigationItem.rightBarButtonItem]; if(self.messageList.count > 0){ [self.tableView reloadData]; [weakSelf.messageList removeObjectsInArray:self.selectedMessageArray]; [weakSelf editTableView:self.navigationItem.rightBarButtonItem]; if(weakSelf.messageList.count > 0){ [weakSelf.tableView reloadData]; } else { [self.tableView.header beginRefreshing]; [weakSelf.tableView.mj_header beginRefreshing]; } }]; } } @@ -308,15 +332,25 @@ // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. NSDictionary *dict = sender; EZAlarmInfo *info = dict[@"alarmInfo"]; if(!info.isRead){ [EZOPENSDK setAlarmStatus:@[info.alarmId] alarmStatus:EZMessageStatusRead completion:^(NSError *error) { if(!error) { info.isRead = YES; [self.tableView reloadData]; HDLAlarmInfo *info = dict[@"alarmInfo"]; if(!info.isChecked){ // [EZOPENSDK setAlarmStatus:@[info.alarmId] alarmStatus:EZMessageStatusRead completion:^(NSError *error) { // if(!error) // { // info.isChecked = YES; // [self.tableView reloadData]; // } // }]; //标记已读 __weak __typeof(self)weakSelf = self; [[EZHttpUtil sharedManager] readAlarmMessage:@[info.ysId] completion:^(ResponseData * responseData) { if(responseData.success){ info.isChecked = YES; [weakSelf.tableView reloadData]; } }]; } EZMessagePhotoViewController *nextVC = [segue destinationViewController]; nextVC.image = dict[@"image"]; @@ -329,18 +363,45 @@ - (void)addHeaderRefresh { __weak typeof(self) weakSelf = self; self.tableView.header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ weakSelf.currentIndex = 0; self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ weakSelf.currentIndex = 1; [weakSelf.noMessage removeFromSuperview]; [weakSelf.noMessageLabel removeFromSuperview]; [EZOPENSDK getAlarmList:weakSelf.deviceInfo.deviceSerial pageIndex:weakSelf.currentIndex++ pageSize:EZMessageListPageSize beginTime:weakSelf.beginTime endTime:weakSelf.endTime // beginTime:nil // endTime:nil completion:^(NSArray *alarmList, NSInteger alarmCount, NSError *error) { // [EZOPENSDK getAlarmList:weakSelf.deviceInfo.deviceSerial // pageIndex:weakSelf.currentIndex++ // pageSize:EZMessageListPageSize // beginTime:weakSelf.beginTime // endTime:weakSelf.endTime //// beginTime:nil //// endTime:nil // completion:^(NSArray *alarmList, NSInteger alarmCount, NSError *error) { // [weakSelf.messageList removeAllObjects]; // [weakSelf.messageList addObjectsFromArray:alarmList]; // weakSelf.totalCount = alarmCount; // if(weakSelf.messageList.count != weakSelf.totalCount) // { // [weakSelf addFooter]; // } // [weakSelf tableViewDidReload:alarmList]; // [weakSelf.tableView.mj_header endRefreshing]; // if(weakSelf.messageList.count > 0) // weakSelf.navigationItem.rightBarButtonItem = self.editButton; // }]; //2021-07-09 1.修改为HDL接口方案 [[EZHttpUtil sharedManager] getAlarmList:weakSelf.deviceInfo.deviceSerial pageNo:weakSelf.currentIndex++ pageSize:EZMessageListPageSize completion:^(ResponseData * responseData) { NSInteger alarmCount = 0; NSArray<HDLAlarmInfo *> *alarmList = [NSArray array]; if (responseData.success){ HDLAlarmInfoData *alarmInfoData = [HDLAlarmInfoData yy_modelWithDictionary:responseData.data]; if (alarmInfoData) { alarmCount = alarmInfoData.totalCount; if (alarmInfoData.list) { alarmList = alarmInfoData.list; } } } [weakSelf.messageList removeAllObjects]; [weakSelf.messageList addObjectsFromArray:alarmList]; weakSelf.totalCount = alarmCount; @@ -348,35 +409,62 @@ { [weakSelf addFooter]; } [weakSelf tableViewDidReload:alarmList]; [weakSelf.tableView.header endRefreshing]; [weakSelf tableViewDidReload]; [weakSelf.tableView.mj_header endRefreshing]; if(weakSelf.messageList.count > 0) weakSelf.navigationItem.rightBarButtonItem = self.editButton; }]; }]; self.tableView.header.automaticallyChangeAlpha = YES; [self.tableView.header beginRefreshing]; self.tableView.mj_header.automaticallyChangeAlpha = YES; [self.tableView.mj_header beginRefreshing]; } - (void)addFooter { __weak typeof(self) weakSelf = self; self.tableView.footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{ [EZOPENSDK getAlarmList:weakSelf.deviceInfo.deviceSerial pageIndex:weakSelf.currentIndex++ pageSize:EZMessageListPageSize beginTime:weakSelf.beginTime endTime:weakSelf.endTime completion:^(NSArray *alarmList, NSInteger alarmCount, NSError *error) { self.tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{ // [EZOPENSDK getAlarmList:weakSelf.deviceInfo.deviceSerial // pageIndex:weakSelf.currentIndex++ // pageSize:EZMessageListPageSize // beginTime:weakSelf.beginTime // endTime:weakSelf.endTime // completion:^(NSArray *alarmList, NSInteger alarmCount, NSError *error) { // [weakSelf.messageList addObjectsFromArray:alarmList]; // if(weakSelf.messageList.count >= weakSelf.totalCount) // { // weakSelf.tableView.mj_footer.hidden = YES; // return; // } // [weakSelf tableViewDidReload:alarmList]; // [weakSelf.tableView.mj_footer endRefreshing]; // }]; [[EZHttpUtil sharedManager] getAlarmList:weakSelf.deviceInfo.deviceSerial pageNo:weakSelf.currentIndex++ pageSize:EZMessageListPageSize completion:^(ResponseData * responseData) { NSArray<HDLAlarmInfo *> *alarmList = [NSArray array]; if (responseData.success){ HDLAlarmInfoData *alarmInfoData = [HDLAlarmInfoData yy_modelWithDictionary:responseData.data]; if (alarmInfoData) { if (alarmInfoData.list) { alarmList = alarmInfoData.list; } } } [weakSelf.messageList addObjectsFromArray:alarmList]; [weakSelf tableViewDidReload]; [weakSelf.tableView.mj_footer endRefreshing]; if(weakSelf.messageList.count >= weakSelf.totalCount) { weakSelf.tableView.footer.hidden = YES; weakSelf.tableView.mj_footer.hidden = YES; return; } [weakSelf tableViewDidReload:alarmList]; [weakSelf.tableView.footer endRefreshing]; }]; }]; @@ -384,9 +472,9 @@ #pragma mark - Action Methods - (void)tableViewDidReload:(NSArray *)messageList - (void)tableViewDidReload { if(messageList.count == 0) if(self.messageList.count == 0) { self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; [self.tableView reloadData]; @@ -397,28 +485,28 @@ self.noMessageLabel.frame = CGRectMake((self.tableView.frame.size.width - 100)/2.0, self.noMessage.frame.origin.y + self.noMessage.frame.size.height + 10, 100, 20.0); return; } if(self.currentIndex == 1) { [self.sections removeAllObjects]; [self.tableView.footer endRefreshing]; self.lastDate = [messageList[0] alarmStartTime]; self.dateFormatter.dateFormat = @"yyyy-MM-dd"; NSString *key = [self.dateFormatter stringFromDate:self.lastDate]; NSDictionary *dict = @{@"index":@0, @"date":key}; [self.sections addObject:dict]; } for (int i = 0; i < messageList.count; i++) { EZAlarmInfo *info = [messageList dd_objectAtIndex:i]; if(![info.alarmStartTime isSameToDate:self.lastDate]) { NSInteger index = [self.messageList indexOfObject:info]; self.dateFormatter.dateFormat = @"yyyy-MM-dd"; NSString *key = [self.dateFormatter stringFromDate:info.alarmStartTime]; NSDictionary *dict = @{@"index":@(index),@"date":key}; [self.sections addObject:dict]; } self.lastDate = info.alarmStartTime; } // if(self.currentIndex == 1) // { // [self.sections removeAllObjects]; // [self.tableView.mj_footer endRefreshing]; // self.lastDate = [messageList[0] getAlarmStartTime]; // self.dateFormatter.dateFormat = @"yyyy-MM-dd"; // NSString *key = [self.dateFormatter stringFromDate:self.lastDate]; // NSDictionary *dict = @{@"index":@0, @"date":key}; // [self.sections addObject:dict]; // } // for (int i = 0; i < messageList.count; i++) { // HDLAlarmInfo *info = [messageList dd_objectAtIndex:i]; // if(![[info getAlarmStartTime] isSameToDate:self.lastDate]) // { // NSInteger index = [self.messageList indexOfObject:info]; // self.dateFormatter.dateFormat = @"yyyy-MM-dd"; // NSString *key = [self.dateFormatter stringFromDate:[info getAlarmStartTime]]; // NSDictionary *dict = @{@"index":@(index),@"date":key}; // [self.sections addObject:dict]; // } // self.lastDate = [info getAlarmStartTime]; // } [self.tableView reloadData]; } @@ -431,19 +519,19 @@ [self.navigationController setToolbarHidden:YES animated:YES]; self.deleteSelected.title = NSLocalizedString(@"delete", @"删除"); self.deleteSelected.enabled = NO; self.readAll.title = NSLocalizedString(@"dmessage_read", @"标记已读"); self.readAll.title = NSLocalizedString(@"message_read", @"标记已读"); self.readAll.enabled = NO; [self.selectedMessageArray removeAllObjects]; self.tableView.header.hidden = NO; self.tableView.mj_header.hidden = NO; if(self.messageList.count < self.totalCount) self.tableView.footer.hidden = NO; self.tableView.mj_footer.hidden = NO; }else{ self.tableView.allowsMultipleSelectionDuringEditing = YES; [self.tableView setEditing:YES animated:YES]; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(editTableView:)]; [self.navigationController setToolbarHidden:NO animated:YES]; self.tableView.header.hidden = YES; self.tableView.footer.hidden = YES; self.tableView.mj_header.hidden = YES; self.tableView.mj_footer.hidden = YES; self.selectedAll.enabled = YES; self.deleteSelected.enabled = NO; self.readAll.enabled = NO; @@ -463,19 +551,19 @@ [self.selectedMessageArray addObjectsFromArray:self.messageList]; self.deleteSelected.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"delete", @"删除"),(int)[self.selectedMessageArray count]]; self.deleteSelected.enabled = YES; self.readAll.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"dmessage_read", @"标记已读"),(int)[self.selectedMessageArray count]]; self.readAll.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"message_read", @"标记已读"),(int)[self.selectedMessageArray count]]; self.readAll.enabled = YES; } else { self.deleteSelected.title = NSLocalizedString(@"delete", @"删除"); self.readAll.title = NSLocalizedString(@"dmessage_read", @"标记已读"); self.readAll.title = NSLocalizedString(@"message_read", @"标记已读"); [self.selectedMessageArray removeAllObjects]; self.deleteSelected.enabled = NO; self.readAll.enabled = NO; } [self.tableView reloadData]; self.tableView.footer.hidden = YES; self.tableView.mj_footer.hidden = YES; } - (IBAction)deleteMessage:(id)sender @@ -511,35 +599,57 @@ hud.labelText = NSLocalizedString(@"message_setting", @"正在设置已读,请稍候..."); NSMutableArray *alarmIds = [NSMutableArray new]; for (int i = 0; i < self.selectedMessageArray.count; i++) { EZAlarmInfo *info = [self.selectedMessageArray dd_objectAtIndex:i]; [alarmIds addObject:info.alarmId]; HDLAlarmInfo *info = [self.selectedMessageArray dd_objectAtIndex:i]; [alarmIds addObject:info.ysId]; } [EZOPENSDK setAlarmStatus:alarmIds alarmStatus:EZMessageStatusRead completion:^(NSError *error) { if(error) { hud.labelText = error.localizedDescription; // [EZOPENSDK setAlarmStatus:alarmIds // alarmStatus:EZMessageStatusRead // completion:^(NSError *error) { // if(error) // { // hud.labelText = error.localizedDescription; // hud.mode = MBProgressHUDModeText; // [hud hide:YES afterDelay:1.2]; // } // else // { // [hud hide:YES]; // } // if(!error) // { // for (int i = 0; i < self.selectedMessageArray.count; i++) { // HDLAlarmInfo *info = [self.selectedMessageArray dd_objectAtIndex:i]; // info.isChecked = YES; // } // [self editTableView:self.navigationItem.rightBarButtonItem]; // [self.tableView reloadData]; // [EZOPENSDK getUnreadMessageCount:self.deviceInfo.deviceSerial messageType:EZMessageTypeAlarm completion:^(NSInteger count, NSError *error) { // self.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"message_title", @"消息"), (int)count]; // }]; // } // }]; //标记已读 __weak __typeof(self)weakSelf = self; [[EZHttpUtil sharedManager] readAlarmMessage:alarmIds completion:^(ResponseData * responseData) { if(responseData.success){ [hud hide:YES]; for (int i = 0; i < self.selectedMessageArray.count; i++) { HDLAlarmInfo *info = [self.selectedMessageArray dd_objectAtIndex:i]; info.isChecked = YES; } [weakSelf editTableView:self.navigationItem.rightBarButtonItem]; [weakSelf.tableView reloadData]; }else{ hud.labelText = NSLocalizedString(@"setting_opration_fail", @"操作失败"); hud.mode = MBProgressHUDModeText; [hud hide:YES afterDelay:1.2]; } else { [hud hide:YES]; } if(!error) { for (int i = 0; i < self.selectedMessageArray.count; i++) { EZAlarmInfo *info = [self.selectedMessageArray dd_objectAtIndex:i]; info.isRead = YES; } [self editTableView:self.navigationItem.rightBarButtonItem]; [self.tableView reloadData]; [EZOPENSDK getUnreadMessageCount:self.deviceInfo.deviceSerial messageType:EZMessageTypeAlarm completion:^(NSInteger count, NSError *error) { self.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"message_title", @"消息"), (int)count]; }]; } }]; } - (NSString *)dateStringWithUserDefine:(NSString *)dateString Demo/EZOpensdk_iOS_4.15.1_build20201104/Demo/EZOpenSDKDemo/UIViewControllers/EZMessagePhotoViewController.h
@@ -7,13 +7,14 @@ // #import "MWPhotoBrowser.h" #import "EZAlarmInfo.h" //#import "EZAlarmInfo.h" #import "EZDeviceInfo.h" #import "HDLAlarmInfo.h" @interface EZMessagePhotoViewController : MWPhotoBrowser @property (nonatomic, strong) UIImage *image; @property (nonatomic, strong) EZAlarmInfo *info; @property (nonatomic, strong) HDLAlarmInfo *info; @property (nonatomic, strong) EZDeviceInfo *deviceInfo; @end Demo/EZOpensdk_iOS_4.15.1_build20201104/Demo/EZOpenSDKDemo/UIViewControllers/EZMessagePhotoViewController.m
@@ -34,8 +34,10 @@ NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.dateFormat = @"yyyy/MM/dd HH:mm:ss"; self.timeLabel.text = [formatter stringFromDate:self.info.alarmStartTime]; self.timeLabel.text = [formatter stringFromDate:[self.info getAlarmStartTime]]; self.contentLabel.text = [NSString stringWithFormat:@"%@:%@",NSLocalizedString(@"message_from", @"来自"),self.info.alarmName]; [self.recordButton setHidden:YES]; } - (void)didReceiveMemoryWarning { @@ -50,11 +52,11 @@ - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. EZAlarmInfo *info = sender; EZMessagePlaybackViewController *messagePlaybackVC = [segue destinationViewController]; messagePlaybackVC.info = info; messagePlaybackVC.deviceInfo = self.deviceInfo; // HDLAlarmInfo *info = sender; // // EZMessagePlaybackViewController *messagePlaybackVC = [segue destinationViewController]; // messagePlaybackVC.info = info; // messagePlaybackVC.deviceInfo = self.deviceInfo; } Demo/EZOpensdk_iOS_4.15.1_build20201104/Demo/EZOpenSDKDemo/ViewController.m
@@ -56,10 +56,10 @@ // */ // [self performSegueWithIdentifier:@"go2CameraList" sender:nil]; [EZSDK setHDlAccessToken:@"Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiIyYTAwZGRmOTNjMGY0YzlhYjljNjU2M2VhMDJjZjhmMyIsImNvbXBhbnlJZCI6IjAiLCJyb2xlIjoiIiwiaGVhZGVyUHJlZml4IjoiQmVhcmVyICIsInVzZXJBY2NvdW50Ijoid3hyIiwidGVuYW50SWQiOiIyMCIsInVzZXJUeXBlIjoiVVNFUl9DIiwidG9rZW5UeXBlIjoiYWNjZXNzX3Rva2VuIiwidXNlck5hbWUiOiJrYWVkZSIsIm9wZW5BcHBsaWNhdGlvbklkIjoiMCIsInVzZXJJZCI6IjEzOTIwMzU1NjgyMDQ0MjMxNjkiLCJleHAiOjE2MjU2NjA0NjQsIm5iZiI6MTYyNTY1MzI2NH0.I4YfZQqm1p1SwJQbNWyUEOWXCqpYCWQdmAMOR-xlOMJ0pYFh3_nyjPBiWypTTMgy5nTpj7IqUM1bHwHWGsDEInF4Bl6trxrgOE39Toj-aY1UJcViYhx7e3E3ChrlXptVfKtk3cVEtDlFkMdHdHiJi-6OZox4KOz_AallI8lFIlo" refreshToken:@"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI1ZjdmOGFkY2I3MGU0NzYwOWE0NTcxOTZmOTAyOTY1OSIsImNvbXBhbnlJZCI6IjAiLCJoZWFkZXJQcmVmaXgiOiJCZWFyZXIgIiwidGVuYW50SWQiOiIyMCIsInRva2VuVHlwZSI6InJlZnJlc2hfdG9rZW4iLCJvcGVuQXBwbGljYXRpb25JZCI6IjAiLCJ1c2VySWQiOiIxMzkyMDM1NTY4MjA0NDIzMTY5IiwiZXhwIjoxNjI2MjU4MDY0LCJuYmYiOjE2MjU2NTMyNjR9.DB1pGaM6xtpQiP_KvaAHbWDZtxjLXZwJCgFfrp_XA0bnV8wMC8SE7K_uoP79c97WGqcmpHJVY-x8NCVJneGpIKN2oSCvX0Sn0uAttqni4zbVjmErC2AmpONJwWY27GYjHk4LFri03p38D-5zlULFo3ITtN3Il2aJOjVOpyNCcuI"]; [[EZSDK sharedInstance] setHDlAccessToken:@"Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiIyYTAwZGRmOTNjMGY0YzlhYjljNjU2M2VhMDJjZjhmMyIsImNvbXBhbnlJZCI6IjAiLCJyb2xlIjoiIiwiaGVhZGVyUHJlZml4IjoiQmVhcmVyICIsInVzZXJBY2NvdW50Ijoid3hyIiwidGVuYW50SWQiOiIyMCIsInVzZXJUeXBlIjoiVVNFUl9DIiwidG9rZW5UeXBlIjoiYWNjZXNzX3Rva2VuIiwidXNlck5hbWUiOiJrYWVkZSIsIm9wZW5BcHBsaWNhdGlvbklkIjoiMCIsInVzZXJJZCI6IjEzOTIwMzU1NjgyMDQ0MjMxNjkiLCJleHAiOjE2MjU2NjA0NjQsIm5iZiI6MTYyNTY1MzI2NH0.I4YfZQqm1p1SwJQbNWyUEOWXCqpYCWQdmAMOR-xlOMJ0pYFh3_nyjPBiWypTTMgy5nTpj7IqUM1bHwHWGsDEInF4Bl6trxrgOE39Toj-aY1UJcViYhx7e3E3ChrlXptVfKtk3cVEtDlFkMdHdHiJi-6OZox4KOz_AallI8lFIlo" refreshToken:@"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI1ZjdmOGFkY2I3MGU0NzYwOWE0NTcxOTZmOTAyOTY1OSIsImNvbXBhbnlJZCI6IjAiLCJoZWFkZXJQcmVmaXgiOiJCZWFyZXIgIiwidGVuYW50SWQiOiIyMCIsInRva2VuVHlwZSI6InJlZnJlc2hfdG9rZW4iLCJvcGVuQXBwbGljYXRpb25JZCI6IjAiLCJ1c2VySWQiOiIxMzkyMDM1NTY4MjA0NDIzMTY5IiwiZXhwIjoxNjI2MjU4MDY0LCJuYmYiOjE2MjU2NTMyNjR9.DB1pGaM6xtpQiP_KvaAHbWDZtxjLXZwJCgFfrp_XA0bnV8wMC8SE7K_uoP79c97WGqcmpHJVY-x8NCVJneGpIKN2oSCvX0Sn0uAttqni4zbVjmErC2AmpONJwWY27GYjHk4LFri03p38D-5zlULFo3ITtN3Il2aJOjVOpyNCcuI"]; [EZSDK setRequestHttpsHostAndPlatform:@"https://test-gz.hdlcontrol.com" platform:1 homeId:@"1396717478877241345"]; [[EZSDK sharedInstance] setRequestHttpsHostAndPlatform:@"https://test-gz.hdlcontrol.com" platform:1 homeId:@"1396717478877241345"]; @@ -68,7 +68,7 @@ [EZHttpUtil.sharedManager getChildToken:^(NSString *accessToken) { [hud hide:YES]; if(accessToken != NULL && ![accessToken isEqual:@""]){ [[GlobalKit shareKit] setAccessToken:accessToken]; [[EZSDK sharedInstance] setEZAccessToken:accessToken]; /** * 下面代码功能与以上的注释方法相同 */ @@ -82,11 +82,13 @@ - (IBAction)logout:(id)sender { return; // [[GlobalKit shareKit] setAccessToken:@"ra.a5bfkhhx7ycscsj41if7l0cf9ytfhv5q-9keuxvphmn-1fvjt6p-jugtyy8sr"]; [EZSDK setHDlAccessToken:@"Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI2Zjk1ZTEwZWIwNjA0ZjNiYTdmNTc0ZGUyM2QxYmNmZiIsImNvbXBhbnlJZCI6IjAiLCJyb2xlIjoiIiwiaGVhZGVyUHJlZml4IjoiQmVhcmVyICIsInVzZXJBY2NvdW50Ijoid3hyIiwidGVuYW50SWQiOiIyMCIsInVzZXJUeXBlIjoiVVNFUl9DIiwidG9rZW5UeXBlIjoiYWNjZXNzX3Rva2VuIiwidXNlck5hbWUiOiJrYWVkZSIsIm9wZW5BcHBsaWNhdGlvbklkIjoiMCIsInVzZXJJZCI6IjEzOTIwMzU1NjgyMDQ0MjMxNjkiLCJleHAiOjE2MjU3MTY3NjAsIm5iZiI6MTYyNTcwOTU2MH0.C6w0mb0YiNhqQfLPscXiNVh_DOsbza_fubUbn_T-W04L3R7egi7-Gv_iifdfvh4XTU10rEdVl6FLXKxt3JJvo2x_sjBQLkWRQINMVl1qLOz9cMew79_aykXOwl8mdroYs9SKBd90qyM2lZaA91sD4H0HMVVyc_D2TEcG4XJzSBM" refreshToken:@"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI1M2FlMzg3NDhmNjU0MzE1OTM0MTQ0OWQyYmQ0NjE0NiIsImNvbXBhbnlJZCI6IjAiLCJoZWFkZXJQcmVmaXgiOiJCZWFyZXIgIiwidGVuYW50SWQiOiIyMCIsInRva2VuVHlwZSI6InJlZnJlc2hfdG9rZW4iLCJvcGVuQXBwbGljYXRpb25JZCI6IjAiLCJ1c2VySWQiOiIxMzkyMDM1NTY4MjA0NDIzMTY5IiwiZXhwIjoxNjI2MzE0MzYwLCJuYmYiOjE2MjU3MDk1NjB9.AZlG8jO8lFDcj5dfoY0rZsDfglGdeyLuSImzMw1enHWfAacjkIof0vXQ_qJG9Q-6qxyXXbPu_xrd0DhkGNFeHJ4WFL0iiYgDP51sJuUdKrQklUCSC6T7ZjIW0GSVmvOW4GCw0s6L51bVT_rkdrusVD4rDnOtJwWqXTUfyNanmlk"]; [[EZSDK sharedInstance] setHDlAccessToken:@"Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI2Zjk1ZTEwZWIwNjA0ZjNiYTdmNTc0ZGUyM2QxYmNmZiIsImNvbXBhbnlJZCI6IjAiLCJyb2xlIjoiIiwiaGVhZGVyUHJlZml4IjoiQmVhcmVyICIsInVzZXJBY2NvdW50Ijoid3hyIiwidGVuYW50SWQiOiIyMCIsInVzZXJUeXBlIjoiVVNFUl9DIiwidG9rZW5UeXBlIjoiYWNjZXNzX3Rva2VuIiwidXNlck5hbWUiOiJrYWVkZSIsIm9wZW5BcHBsaWNhdGlvbklkIjoiMCIsInVzZXJJZCI6IjEzOTIwMzU1NjgyMDQ0MjMxNjkiLCJleHAiOjE2MjU3MTY3NjAsIm5iZiI6MTYyNTcwOTU2MH0.C6w0mb0YiNhqQfLPscXiNVh_DOsbza_fubUbn_T-W04L3R7egi7-Gv_iifdfvh4XTU10rEdVl6FLXKxt3JJvo2x_sjBQLkWRQINMVl1qLOz9cMew79_aykXOwl8mdroYs9SKBd90qyM2lZaA91sD4H0HMVVyc_D2TEcG4XJzSBM" refreshToken:@"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI1M2FlMzg3NDhmNjU0MzE1OTM0MTQ0OWQyYmQ0NjE0NiIsImNvbXBhbnlJZCI6IjAiLCJoZWFkZXJQcmVmaXgiOiJCZWFyZXIgIiwidGVuYW50SWQiOiIyMCIsInRva2VuVHlwZSI6InJlZnJlc2hfdG9rZW4iLCJvcGVuQXBwbGljYXRpb25JZCI6IjAiLCJ1c2VySWQiOiIxMzkyMDM1NTY4MjA0NDIzMTY5IiwiZXhwIjoxNjI2MzE0MzYwLCJuYmYiOjE2MjU3MDk1NjB9.AZlG8jO8lFDcj5dfoY0rZsDfglGdeyLuSImzMw1enHWfAacjkIof0vXQ_qJG9Q-6qxyXXbPu_xrd0DhkGNFeHJ4WFL0iiYgDP51sJuUdKrQklUCSC6T7ZjIW0GSVmvOW4GCw0s6L51bVT_rkdrusVD4rDnOtJwWqXTUfyNanmlk"]; [EZSDK setRequestHttpsHostAndPlatform:@"https://test-gz.hdlcontrol.com" platform:1 homeId:@"1396717478877241345"]; [[EZSDK sharedInstance] setRequestHttpsHostAndPlatform:@"https://test-gz.hdlcontrol.com" platform:1 homeId:@"1396717478877241345"]; __weak MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; @@ -95,10 +97,14 @@ [hud hide:YES]; if(accessToken != NULL && ![accessToken isEqual:@""]){ NSLog(@"accessToken HDL:%@",accessToken); [[GlobalKit shareKit] setAccessToken:accessToken]; [[EZSDK sharedInstance] setEZAccessToken:accessToken]; [EZSDK PlayWithDeviceSerial:@"F44133728"]; // [[EZSDK sharedInstance] PlayWithDeviceSerial:@"F44133728"]; EZAlarmInfo *info = [[EZAlarmInfo alloc] init]; info.alarmName = @"人体检测"; info.alarmPicUrl = @"https://i.ys7.com/streamer/alarm/url/get?fileId=20210707204930-F41014762-1-00000-2-1&deviceSerialNo=F41014762&cn=1&isEncrypted=0&ct=1&lc=90&bn=1_hikalarm"; [[EZSDK sharedInstance] goToEZMessagePhotoVC:info]; } }]; @@ -118,7 +124,7 @@ return; } if (deviceInfo) { [EZSDK Play:deviceInfo]; [[EZSDK sharedInstance] Play:deviceInfo]; } }]; EZSDK.IOS/EZSDK.IOS/ApiDefinition.cs
@@ -56,7 +56,7 @@ // @property (nonatomic) NSInteger status; [Export("status")] int Status { get; set; } nint Status { get; set; } // @property (nonatomic) NSInteger isSupportTalk; [Export("isSupportTalk")] @@ -95,53 +95,48 @@ [BaseType(typeof(NSObject))] interface EZSDK { // +(BOOL)initLibWithAppKey:(NSString *)appKey globalAppKey:(NSString *)globalAppKey; // +(instancetype)sharedInstance; [Static] [Export("sharedInstance")] EZSDK SharedInstance(); // -(BOOL)initLibWithAppKey:(NSString *)appKey globalAppKey:(NSString *)globalAppKey; [Export("initLibWithAppKey:globalAppKey:")] bool InitLibWithAppKey(string appKey, string globalAppKey); // +(void)setEZAccessToken:(NSString *)accessToken; [Static] // -(void)setEZAccessToken:(NSString *)accessToken; [Export("setEZAccessToken:")] void SetEZAccessToken(string accessToken); // +(void)setHDlAccessToken:(NSString *)accessToken refreshToken:(NSString *)refreshToken; [Static] // -(void)setHDlAccessToken:(NSString *)accessToken refreshToken:(NSString *)refreshToken; [Export("setHDlAccessToken:refreshToken:")] void SetHDlAccessToken(string accessToken, string refreshToken); // +(void)setRequestHttpsHostAndPlatform:(NSString *)requestHttpsHost platform:(int)platform homeId:(NSString *)homeId; [Static] // -(void)setRequestHttpsHostAndPlatform:(NSString *)requestHttpsHost platform:(int)platform homeId:(NSString *)homeId; [Export("setRequestHttpsHostAndPlatform:platform:homeId:")] void SetRequestHttpsHostAndPlatform(string requestHttpsHost, int platform, string homeId); // +(void)go2EZvizMonitor; [Static] // -(void)go2EZvizMonitor; [Export("go2EZvizMonitor")] void Go2EZvizMonitor(); // +(void)addEzvizMonitor; [Static] // -(void)addEzvizMonitor; [Export("addEzvizMonitor")] void AddEzvizMonitor(); // +(void)Play:(EZDeviceInfo *)deviceInfo; [Static] // -(void)Play:(EZDeviceInfo *)deviceInfo; [Export("Play:")] void Play(EZDeviceInfo deviceInfo); // +(void)PlayWithDeviceSerial:(NSString *)deviceSerial; [Static] // -(void)PlayWithDeviceSerial:(NSString *)deviceSerial; [Export("PlayWithDeviceSerial:")] void PlayWithDeviceSerial(string deviceSerial); // +(void)setting:(EZDeviceInfo *)deviceInfo; [Static] // -(void)setting:(EZDeviceInfo *)deviceInfo; [Export("setting:")] void Setting(EZDeviceInfo deviceInfo); // +(void)playBackVideo:(EZDeviceInfo *)deviceInfo; [Static] // -(void)playBackVideo:(EZDeviceInfo *)deviceInfo; [Export("playBackVideo:")] void PlayBackVideo(EZDeviceInfo deviceInfo); } EZSDK.IOS/EZSDK.IOS/Library/libEZSDK.aBinary files differ
EZSDK.IOS/EZSDK.IOS/Properties/AssemblyInfo.cs
@@ -25,7 +25,7 @@ // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("1.4.2")] [assembly: AssemblyVersion("1.4.3")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. EZSDK/EZSDK.xcodeproj/project.pbxproj
@@ -7,6 +7,9 @@ objects = { /* Begin PBXBuildFile section */ B95AB87E26984D49007BC8D7 /* HDLAlarmInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = B95AB87D26984D49007BC8D7 /* HDLAlarmInfo.m */; }; B95AB88726984DD5007BC8D7 /* NSObject+YYModel.m in Sources */ = {isa = PBXBuildFile; fileRef = B95AB88426984DD5007BC8D7 /* NSObject+YYModel.m */; }; B95AB88826984DD5007BC8D7 /* YYClassInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = B95AB88526984DD5007BC8D7 /* YYClassInfo.m */; }; B965BE0325EE0B0D00E58AFB /* EZHttpUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B965BDFF25EE0B0D00E58AFB /* EZHttpUtil.m */; }; B965BE0425EE0B0D00E58AFB /* ResponseData.m in Sources */ = {isa = PBXBuildFile; fileRef = B965BE0025EE0B0D00E58AFB /* ResponseData.m */; }; B9BC92FF25C0FC3500C024FE /* EZSDK.m in Sources */ = {isa = PBXBuildFile; fileRef = B9BC92FE25C0FC3500C024FE /* EZSDK.m */; }; @@ -159,6 +162,13 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ B95AB87C26984D49007BC8D7 /* HDLAlarmInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDLAlarmInfo.h; sourceTree = "<group>"; }; B95AB87D26984D49007BC8D7 /* HDLAlarmInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDLAlarmInfo.m; sourceTree = "<group>"; }; B95AB88226984DD5007BC8D7 /* YYClassInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYClassInfo.h; sourceTree = "<group>"; }; B95AB88326984DD5007BC8D7 /* YYModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYModel.h; sourceTree = "<group>"; }; B95AB88426984DD5007BC8D7 /* NSObject+YYModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+YYModel.m"; sourceTree = "<group>"; }; B95AB88526984DD5007BC8D7 /* YYClassInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYClassInfo.m; sourceTree = "<group>"; }; B95AB88626984DD5007BC8D7 /* NSObject+YYModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+YYModel.h"; sourceTree = "<group>"; }; B965BDFF25EE0B0D00E58AFB /* EZHttpUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EZHttpUtil.m; sourceTree = "<group>"; }; B965BE0025EE0B0D00E58AFB /* ResponseData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ResponseData.m; sourceTree = "<group>"; }; B965BE0125EE0B0D00E58AFB /* EZHttpUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZHttpUtil.h; sourceTree = "<group>"; }; @@ -576,6 +586,18 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ B95AB88126984DD5007BC8D7 /* YYModel */ = { isa = PBXGroup; children = ( B95AB88226984DD5007BC8D7 /* YYClassInfo.h */, B95AB88326984DD5007BC8D7 /* YYModel.h */, B95AB88426984DD5007BC8D7 /* NSObject+YYModel.m */, B95AB88526984DD5007BC8D7 /* YYClassInfo.m */, B95AB88626984DD5007BC8D7 /* NSObject+YYModel.h */, ); path = YYModel; sourceTree = "<group>"; }; B99F57BA262D85CF0049A308 /* include */ = { isa = PBXGroup; children = ( @@ -675,6 +697,7 @@ B9BC97D425C0FFB600C024FE /* Venders */ = { isa = PBXGroup; children = ( B95AB88126984DD5007BC8D7 /* YYModel */, B9EA4E5325C7E805000FFDA2 /* MJRefresh */, B9BC97D525C0FFB600C024FE /* UITableView-FDTemplateLayoutCell */, B9BC97DE25C0FFB600C024FE /* DACircularProgress */, @@ -1147,6 +1170,8 @@ B9BC996F25C0FFBB00C024FE /* Global */ = { isa = PBXGroup; children = ( B95AB87C26984D49007BC8D7 /* HDLAlarmInfo.h */, B95AB87D26984D49007BC8D7 /* HDLAlarmInfo.m */, B9BC997125C0FFBB00C024FE /* GlobalKit.h */, B9BC997025C0FFBB00C024FE /* GlobalKit.m */, B965BE0125EE0B0D00E58AFB /* EZHttpUtil.h */, @@ -1340,6 +1365,7 @@ B9BC99B425C0FFBD00C024FE /* UIView+Toast.m in Sources */, B9BC99C925C0FFBD00C024FE /* UISegmentedControl+DDKit.m in Sources */, B9BC99DB25C0FFBD00C024FE /* AFHTTPSessionManager.m in Sources */, B95AB87E26984D49007BC8D7 /* HDLAlarmInfo.m in Sources */, B9BC99D325C0FFBD00C024FE /* UIAlertView+AFNetworking.m in Sources */, B9BC99EA25C0FFBD00C024FE /* UIImage+GIF.m in Sources */, B9BC99E825C0FFBD00C024FE /* UIImageView+HighlightedWebCache.m in Sources */, @@ -1459,6 +1485,8 @@ B9BC99A125C0FFBD00C024FE /* DDCollectionViewFlowLayout.m in Sources */, B9BC9A1E25C0FFBD00C024FE /* EZWifiInfoViewController.m in Sources */, B9BC9A1925C0FFBD00C024FE /* EZAPWiFiConfigViewController.m in Sources */, B95AB88826984DD5007BC8D7 /* YYClassInfo.m in Sources */, B95AB88726984DD5007BC8D7 /* NSObject+YYModel.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; EZSDK/EZSDK/EZ/Global/EZHttpUtil.h
@@ -48,6 +48,24 @@ */ - (void)deleteDeviceByHDL:(NSString *)deviceSerial completion:(void (^)(ResponseData *responseData))completion; /** * 根据设备序列号获取告警信息列表 */ - (void)getAlarmList:(NSString *)deviceSerial pageNo:(NSInteger)pageNo pageSize:(NSInteger)pageSize completion:(void (^)(ResponseData *responseData))completion; /** * 批量删除报警记录 */ - (void)deleteAlarmMessage:(NSArray *)alarmIds completion:(void (^)(ResponseData *responseData))completion; /** * 批量标记报警记录已读 */ - (void)readAlarmMessage:(NSArray *)alarmIds completion:(void (^)(ResponseData *responseData))completion; @end EZSDK/EZSDK/EZ/Global/EZHttpUtil.m
@@ -10,6 +10,7 @@ #import <Foundation/Foundation.h> #import <CommonCrypto/CommonDigest.h> #import "AFNetworking.h" #import "YYModel.h" #define TestRequestHttpsHost @"https://test-gz.hdlcontrol.com" #pragma mark API @@ -18,6 +19,9 @@ #define API_POST_EZ_ChildDelDevice @"/home-wisdom/platform/yingshi/child/deleteDevice" #define API_POST_EZ_RefreshToken @"/smart-footstone/member/oauth/login" #define API_POST_EZ_GetAlarmList @"/home-wisdom/platform/yingshi/alarm/records"//获取报警消息 #define API_POST_EZ_DeleteAlarmMes @"/home-wisdom/platform/yingshi/alarm/delete"//删除报警消息 #define API_POST_EZ_ReadAlarmMes @"/home-wisdom/platform/yingshi/alarm/updateChecked"//标记报警消息已读 #pragma mark APP_KEY #define APP_KEY @"HDL-HOME-APP-TEST" @@ -126,6 +130,70 @@ } /** * 根据设备序列号获取告警信息列表 */ - (void)getAlarmList:(NSString *)deviceSerial pageNo:(NSInteger)pageNo pageSize:(NSInteger)pageSize completion:(void (^)(ResponseData *responseData))completion{ //1.设置请求参数 NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; [parameters setValue:deviceSerial forKey:@"deviceSerial"]; [parameters setValue:[GlobalKit shareKit].hdlHomeId forKey:@"homeId"]; [parameters setValue:[NSString stringWithFormat:@"%ld",(long)pageSize] forKey:@"pageSize"]; [parameters setValue:[NSString stringWithFormat:@"%ld",(long)pageNo] forKey:@"pageNo"]; parameters = [self GetSignRequestDictionary:parameters]; NSLog(@"HDLpageNo:%ld",(long)pageNo); [self requestHttpsPost:API_POST_EZ_GetAlarmList parameters:parameters completion:^(ResponseData *responseData) { if (completion) { completion (responseData); } }]; } /** * 批量删除报警记录 */ - (void)deleteAlarmMessage:(NSArray *)alarmIds completion:(void (^)(ResponseData *responseData))completion{ //1.设置请求参数 NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; [parameters setValue:[alarmIds yy_modelToJSONObject] forKey:@"alarmIds"]; parameters = [self GetSignRequestDictionary:parameters]; [self requestHttpsPost:API_POST_EZ_DeleteAlarmMes parameters:parameters completion:^(ResponseData *responseData) { if (completion) { completion (responseData); } }]; } /** * 批量标记报警记录已读 */ - (void)readAlarmMessage:(NSArray *)alarmIds completion:(void (^)(ResponseData *responseData))completion{ //1.设置请求参数 NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; [parameters setValue:@"1" forKey:@"isChecked"]; [parameters setValue:[alarmIds yy_modelToJSONObject] forKey:@"alarmIds"]; parameters = [self GetSignRequestDictionary:parameters]; [self requestHttpsPost:API_POST_EZ_ReadAlarmMes parameters:parameters completion:^(ResponseData *responseData) { if (completion) { completion (responseData); } }]; } /// 刷新token /// @param block 结果 @@ -143,7 +211,7 @@ if (block) { if (responseData) { if(responseData.success){ [EZSDK setHDlAccessToken: [[EZSDK sharedInstance] setHDlAccessToken: [NSString stringWithFormat:@"%@%@",responseData.data[@"headerPrefix"], responseData.data[@"accessToken"]] refreshToken:responseData.data[@"refreshToken"]]; EZSDK/EZSDK/EZ/Global/HDLAlarmInfo.h
New file @@ -0,0 +1,56 @@ // // HDLAlarmInfo.h // EZOpenSDKDemo // // Created by 陈嘉乐 on 2021/7/9. // Copyright © 2021 hikvision. All rights reserved. // #import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN @interface HDLAlarmInfo : NSObject /// 主键ID @property (nonatomic, copy) NSString *ysId; /// 告警ID @property (nonatomic, copy) NSString *alarmId; /// 通道号 @property (nonatomic, assign) NSInteger channelNo; /// 设备序列号 @property (nonatomic, copy) NSString *deviceSerial; /// 告警名称 @property (nonatomic, copy) NSString *alarmName; /// 告警图片 @property (nonatomic, copy) NSString *alarmPicUrl; /// 告警开始时间 @property (nonatomic, strong) NSDate *alarmTime; /// 住宅Id @property (nonatomic, copy) NSString *homeId; /// 告警类型 @property (nonatomic, copy) NSString *alarmType; /// 是否已读 @property (nonatomic, assign) NSInteger isChecked; /// 是否加密 @property (nonatomic, assign) NSInteger isEncrypt; //@property (nonatomic, assign) NSInteger deleted; //@property (nonatomic, copy) NSString *tenantID; @property (nonatomic, copy) NSString *createTime; //@property (nonatomic, copy) NSString *modifyTime; //@property (nonatomic, copy) NSString *region; //@property (nonatomic, copy) NSString *identifier; -(NSDate *)getAlarmStartTime; @end @interface HDLAlarmInfoData : NSObject @property (nonatomic, copy) NSArray<HDLAlarmInfo *> *list; @property (nonatomic, assign) NSInteger totalCount; @property (nonatomic, assign) NSInteger totalPage; @property (nonatomic, assign) NSInteger pageNo; @property (nonatomic, assign) NSInteger pageSize; @end NS_ASSUME_NONNULL_END EZSDK/EZSDK/EZ/Global/HDLAlarmInfo.m
New file @@ -0,0 +1,25 @@ // // HDLAlarmInfo.m // EZOpenSDKDemo // // Created by 陈嘉乐 on 2021/7/9. // Copyright © 2021 hikvision. All rights reserved. // #import "HDLAlarmInfo.h" @implementation HDLAlarmInfo -(NSDate *)getAlarmStartTime{ NSTimeInterval time = [_createTime doubleValue]; // return [NSDate dateWithTimeIntervalSince1970:time];; return [NSDate dateWithTimeIntervalSince1970:time/1000]; } @end @implementation HDLAlarmInfoData + (NSDictionary *)modelContainerPropertyGenericClass { return @{@"list" : [HDLAlarmInfo class]}; } @end EZSDK/EZSDK/EZ/TableViewCells/MessageListCell.h
@@ -7,7 +7,7 @@ // #import <UIKit/UIKit.h> #import "EZAlarmInfo.h" #import "HDLAlarmInfo.h" @interface MessageListCell : UITableViewCell @@ -18,6 +18,6 @@ @property (nonatomic, weak) IBOutlet UIImageView *readStatusIcon; @property (nonatomic, copy) NSString *deviceSerial; - (void)setAlarmInfo:(EZAlarmInfo *)info; - (void)setAlarmInfo:(HDLAlarmInfo *)info; @end EZSDK/EZSDK/EZ/TableViewCells/MessageListCell.m
@@ -9,7 +9,7 @@ #import "MessageListCell.h" #import "UIImageView+EzvizOpenSDK.h" #import "UIImageView+AFNetworking.h" #import "HDLAlarmInfo.h" #import "DDKit.h" static dispatch_semaphore_t ezviz_sema; //全局信号量 @@ -55,13 +55,13 @@ dispatch_semaphore_signal(ezviz_sema); } - (void)setAlarmInfo:(EZAlarmInfo *)info - (void)setAlarmInfo:(HDLAlarmInfo *)info { NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.dateFormat = @"HH:mm:ss"; self.timeLabel.text = [formatter stringFromDate:info.alarmStartTime]; self.timeLabel.text = [formatter stringFromDate:[info getAlarmStartTime]]; self.readStatusIcon.hidden = NO; if(info.isRead) if(info.isChecked) { self.readStatusIcon.hidden = YES; } EZSDK/EZSDK/EZ/UIViewControllers/EZMessageListViewController.m
@@ -15,6 +15,8 @@ #import "MBProgressHUD.h" #import "EZMessagePhotoViewController.h" #import "NSDate-Utilities.h" #import "HDLAlarmInfo.h" #import "YYModel.h" #define EZMessageListPageSize 10 @@ -31,7 +33,7 @@ @property (nonatomic) NSInteger currentIndex; @property (nonatomic, strong) NSMutableArray *messageList; @property (nonatomic, strong) NSDateFormatter *dateFormatter; @property (nonatomic, strong) NSMutableArray *sections; //@property (nonatomic, strong) NSMutableArray *sections; @property (nonatomic) NSInteger lastIndex; @property (nonatomic, weak) IBOutlet UIImageView *noMessage; @property (nonatomic, weak) IBOutlet UILabel *noMessageLabel; @@ -59,16 +61,16 @@ // self.navigationItem.rightBarButtonItem = self.editButtonItem; self.title = NSLocalizedString(@"dmessage_title", @"消息"); [EZOPENSDK getUnreadMessageCount:self.deviceInfo.deviceSerial messageType:EZMessageTypeAlarm completion:^(NSInteger count, NSError *error) { self.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"dmessage_title", @"消息"), (int)count]; }]; // [EZOPENSDK getUnreadMessageCount:self.deviceInfo.deviceSerial messageType:EZMessageTypeAlarm completion:^(NSInteger count, NSError *error) { // self.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"dmessage_title", @"消息"), (int)count]; // }]; if(!_messageList) _messageList = [NSMutableArray new]; if(!self.messageList) self.messageList = [NSMutableArray new]; if(!_sections) _sections = [NSMutableArray new]; // if(!_sections) // _sections = [NSMutableArray new]; // if(!_selectedMessageArray) _selectedMessageArray = [NSMutableArray new]; @@ -99,35 +101,20 @@ #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return _sections.count; return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (_sections.count == 1) { return _messageList.count; } else { if (section == 0) { return [_sections[1][@"index"] integerValue]; } else if (section == _sections.count - 1) { return _messageList.count - [_sections[section][@"index"] integerValue]; } else { return [_sections[section + 1][@"index"] integerValue] - [_sections[section][@"index"] integerValue]; } } return self.messageList.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // Configure the cell... MessageListCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MessageCell" forIndexPath:indexPath]; cell.deviceSerial = self.deviceInfo.deviceSerial; EZAlarmInfo *info = [_messageList dd_objectAtIndex:[[_sections dd_objectAtIndex:indexPath.section][@"index"] integerValue] + indexPath.row]; HDLAlarmInfo *info = self.messageList[indexPath.row]; [cell setAlarmInfo:info]; if (tableView.allowsMultipleSelectionDuringEditing == YES) { if([_selectedMessageArray containsObject:info]) @@ -150,7 +137,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { EZAlarmInfo *info = [_messageList dd_objectAtIndex:[[_sections dd_objectAtIndex:indexPath.section][@"index"] integerValue] + indexPath.row]; HDLAlarmInfo *info = self.messageList[indexPath.row]; if(tableView.allowsMultipleSelectionDuringEditing) { if ([self.selectedMessageArray containsObject:info]) @@ -165,14 +152,14 @@ { self.deleteSelected.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"delete", @"删除"),(int)[self.selectedMessageArray count]]; self.deleteSelected.enabled = YES; self.readAll.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"dmessage_read", @"标记已读"),(int)[self.selectedMessageArray count]]; self.readAll.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"message_read", @"标记已读"),(int)[self.selectedMessageArray count]]; self.readAll.enabled = YES; } else { self.deleteSelected.title = NSLocalizedString(@"delete", @"删除"); self.deleteSelected.enabled = NO; self.readAll.title = NSLocalizedString(@"dmessage_read", @"标记已读"); self.readAll.title = NSLocalizedString(@"message_read", @"标记已读"); self.readAll.enabled = NO; } return; @@ -180,16 +167,16 @@ MessageListCell *cell = [tableView cellForRowAtIndexPath:indexPath]; [self performSegueWithIdentifier:@"go2MessagePhoto" sender:@{@"image":cell.actionImageView.image?:[UIImage new], @"alarmInfo":info}]; [EZOPENSDK getUnreadMessageCount:self.deviceInfo.deviceSerial messageType:EZMessageTypeAlarm completion:^(NSInteger count, NSError *error) { self.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"dmessage_title", @"消息"), (int)count]; }]; // [EZOPENSDK getUnreadMessageCount:self.deviceInfo.deviceSerial messageType:EZMessageTypeAlarm completion:^(NSInteger count, NSError *error) { // self.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"dmessage_title", @"消息"), (int)count]; // }]; } - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { if(tableView.allowsMultipleSelectionDuringEditing) { EZAlarmInfo *info = [_messageList dd_objectAtIndex:[[_sections dd_objectAtIndex:indexPath.section][@"index"] integerValue] + indexPath.row]; HDLAlarmInfo *info = self.messageList[indexPath.row];; if ([self.selectedMessageArray containsObject:info]) { [self.selectedMessageArray removeObject:info]; @@ -202,14 +189,14 @@ { self.deleteSelected.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"delete", @"删除"),(int)[self.selectedMessageArray count]]; self.deleteSelected.enabled = YES; self.readAll.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"dmessage_read", @"标记已读"),(int)[self.selectedMessageArray count]]; self.readAll.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"message_read", @"标记已读"),(int)[self.selectedMessageArray count]]; self.readAll.enabled = YES; } else { self.deleteSelected.title = NSLocalizedString(@"delete", @"删除"); self.deleteSelected.enabled = NO; self.readAll.title = NSLocalizedString(@"dmessage_read", @"标记已读"); self.readAll.title = NSLocalizedString(@"message_read", @"标记已读"); self.readAll.enabled = NO; } } @@ -220,33 +207,48 @@ return 75.0f; } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 20.0f; } //- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section //{ // return 20.0f; //} - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 20)]; NSString *key = [self.sections dd_objectAtIndex:section][@"date"]; headerLabel.text = [NSString stringWithFormat:@" %@",[self dateStringWithUserDefine:key]]; headerLabel.font = [UIFont systemFontOfSize:14.0f]; headerLabel.backgroundColor = [UIColor dd_hexStringToColor:@"0xf0f0f3"]; return headerLabel; } //- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section //{ // UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 20)]; // NSString *key = [self.sections dd_objectAtIndex:section][@"date"]; // headerLabel.text = [NSString stringWithFormat:@" %@",[self dateStringWithUserDefine:key]]; // headerLabel.font = [UIFont systemFontOfSize:14.0f]; // headerLabel.backgroundColor = [UIColor dd_hexStringToColor:@"0xf0f0f3"]; // return headerLabel; //} // Override to support editing the table view. - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { // Delete the row from the data source EZAlarmInfo *info = [_messageList dd_objectAtIndex:[[_sections dd_objectAtIndex:indexPath.section][@"index"] integerValue] + indexPath.row]; HDLAlarmInfo *info = self.messageList[indexPath.row];; MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; hud.labelText = NSLocalizedString(@"message_deleting", @"正在删除,请稍候..."); [EZOPENSDK deleteAlarm:@[info.alarmId] completion:^(NSError *error) { // [EZOPENSDK deleteAlarm:@[info.alarmId] completion:^(NSError *error) { // [hud hide:YES]; // [self.messageList removeObject:info]; // [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; // }]; __weak __typeof(self)weakSelf = self; [[EZHttpUtil sharedManager] deleteAlarmMessage:@[info.ysId] completion:^(ResponseData * responseData) { if (responseData.success) { [hud hide:YES]; [_messageList removeObject:info]; [weakSelf.messageList removeObject:info]; [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; }else{ hud.labelText = NSLocalizedString(@"setting_opration_fail", @"操作失败"); hud.mode = MBProgressHUDModeText; [hud hide:YES afterDelay:1.2]; } }]; } } @@ -274,29 +276,51 @@ hud.labelText = NSLocalizedString(@"message_deleting", @"正在删除,请稍候..."); NSMutableArray *alarmIds = [NSMutableArray new]; for (int i = 0; i < self.selectedMessageArray.count; i++) { EZAlarmInfo *info = [self.selectedMessageArray dd_objectAtIndex:i]; [alarmIds addObject:info.alarmId]; HDLAlarmInfo *info = [self.selectedMessageArray dd_objectAtIndex:i]; [alarmIds addObject:info.ysId]; } [EZOPENSDK deleteAlarm:alarmIds completion:^(NSError *error) { if(error) { hud.labelText = error.localizedDescription; // [EZOPENSDK deleteAlarm:alarmIds completion:^(NSError *error) { // if(error) // { // hud.labelText = error.localizedDescription; // hud.mode = MBProgressHUDModeText; // [hud hide:YES afterDelay:1.2]; // } // else // { // [hud hide:YES]; // } // [self.messageList removeObjectsInArray:self.selectedMessageArray]; // [self editTableView:self.navigationItem.rightBarButtonItem]; // if(self.messageList.count > 0){ // [self.tableView reloadData]; // } // else // { // [self.tableView.mj_header beginRefreshing]; // } // }]; __weak __typeof(self)weakSelf = self; [[EZHttpUtil sharedManager] deleteAlarmMessage:alarmIds completion:^(ResponseData * responseData) { [hud hide:YES]; if (responseData.success) { [hud hide:YES]; }else{ hud.labelText = NSLocalizedString(@"setting_opration_fail", @"操作失败"); hud.mode = MBProgressHUDModeText; [hud hide:YES afterDelay:1.2]; } else { [hud hide:YES]; } [self.messageList removeObjectsInArray:self.selectedMessageArray]; [self editTableView:self.navigationItem.rightBarButtonItem]; if(self.messageList.count > 0){ [self.tableView reloadData]; [weakSelf.messageList removeObjectsInArray:self.selectedMessageArray]; [weakSelf editTableView:self.navigationItem.rightBarButtonItem]; if(weakSelf.messageList.count > 0){ [weakSelf.tableView reloadData]; } else { [self.tableView.header beginRefreshing]; [weakSelf.tableView.mj_header beginRefreshing]; } }]; } } @@ -308,15 +332,25 @@ // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. NSDictionary *dict = sender; EZAlarmInfo *info = dict[@"alarmInfo"]; if(!info.isRead){ [EZOPENSDK setAlarmStatus:@[info.alarmId] alarmStatus:EZMessageStatusRead completion:^(NSError *error) { if(!error) { info.isRead = YES; [self.tableView reloadData]; HDLAlarmInfo *info = dict[@"alarmInfo"]; if(!info.isChecked){ // [EZOPENSDK setAlarmStatus:@[info.alarmId] alarmStatus:EZMessageStatusRead completion:^(NSError *error) { // if(!error) // { // info.isChecked = YES; // [self.tableView reloadData]; // } // }]; //标记已读 __weak __typeof(self)weakSelf = self; [[EZHttpUtil sharedManager] readAlarmMessage:@[info.ysId] completion:^(ResponseData * responseData) { if(responseData.success){ info.isChecked = YES; [weakSelf.tableView reloadData]; } }]; } EZMessagePhotoViewController *nextVC = [segue destinationViewController]; nextVC.image = dict[@"image"]; @@ -329,18 +363,45 @@ - (void)addHeaderRefresh { __weak typeof(self) weakSelf = self; self.tableView.header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ weakSelf.currentIndex = 0; self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ weakSelf.currentIndex = 1; [weakSelf.noMessage removeFromSuperview]; [weakSelf.noMessageLabel removeFromSuperview]; [EZOPENSDK getAlarmList:weakSelf.deviceInfo.deviceSerial pageIndex:weakSelf.currentIndex++ pageSize:EZMessageListPageSize beginTime:weakSelf.beginTime endTime:weakSelf.endTime // beginTime:nil // endTime:nil completion:^(NSArray *alarmList, NSInteger alarmCount, NSError *error) { // [EZOPENSDK getAlarmList:weakSelf.deviceInfo.deviceSerial // pageIndex:weakSelf.currentIndex++ // pageSize:EZMessageListPageSize // beginTime:weakSelf.beginTime // endTime:weakSelf.endTime //// beginTime:nil //// endTime:nil // completion:^(NSArray *alarmList, NSInteger alarmCount, NSError *error) { // [weakSelf.messageList removeAllObjects]; // [weakSelf.messageList addObjectsFromArray:alarmList]; // weakSelf.totalCount = alarmCount; // if(weakSelf.messageList.count != weakSelf.totalCount) // { // [weakSelf addFooter]; // } // [weakSelf tableViewDidReload:alarmList]; // [weakSelf.tableView.mj_header endRefreshing]; // if(weakSelf.messageList.count > 0) // weakSelf.navigationItem.rightBarButtonItem = self.editButton; // }]; //2021-07-09 1.修改为HDL接口方案 [[EZHttpUtil sharedManager] getAlarmList:weakSelf.deviceInfo.deviceSerial pageNo:weakSelf.currentIndex++ pageSize:EZMessageListPageSize completion:^(ResponseData * responseData) { NSInteger alarmCount = 0; NSArray<HDLAlarmInfo *> *alarmList = [NSArray array]; if (responseData.success){ HDLAlarmInfoData *alarmInfoData = [HDLAlarmInfoData yy_modelWithDictionary:responseData.data]; if (alarmInfoData) { alarmCount = alarmInfoData.totalCount; if (alarmInfoData.list) { alarmList = alarmInfoData.list; } } } [weakSelf.messageList removeAllObjects]; [weakSelf.messageList addObjectsFromArray:alarmList]; weakSelf.totalCount = alarmCount; @@ -348,35 +409,62 @@ { [weakSelf addFooter]; } [weakSelf tableViewDidReload:alarmList]; [weakSelf.tableView.header endRefreshing]; [weakSelf tableViewDidReload]; [weakSelf.tableView.mj_header endRefreshing]; if(weakSelf.messageList.count > 0) weakSelf.navigationItem.rightBarButtonItem = self.editButton; }]; }]; self.tableView.header.automaticallyChangeAlpha = YES; [self.tableView.header beginRefreshing]; self.tableView.mj_header.automaticallyChangeAlpha = YES; [self.tableView.mj_header beginRefreshing]; } - (void)addFooter { __weak typeof(self) weakSelf = self; self.tableView.footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{ [EZOPENSDK getAlarmList:weakSelf.deviceInfo.deviceSerial pageIndex:weakSelf.currentIndex++ pageSize:EZMessageListPageSize beginTime:weakSelf.beginTime endTime:weakSelf.endTime completion:^(NSArray *alarmList, NSInteger alarmCount, NSError *error) { self.tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{ // [EZOPENSDK getAlarmList:weakSelf.deviceInfo.deviceSerial // pageIndex:weakSelf.currentIndex++ // pageSize:EZMessageListPageSize // beginTime:weakSelf.beginTime // endTime:weakSelf.endTime // completion:^(NSArray *alarmList, NSInteger alarmCount, NSError *error) { // [weakSelf.messageList addObjectsFromArray:alarmList]; // if(weakSelf.messageList.count >= weakSelf.totalCount) // { // weakSelf.tableView.mj_footer.hidden = YES; // return; // } // [weakSelf tableViewDidReload:alarmList]; // [weakSelf.tableView.mj_footer endRefreshing]; // }]; [[EZHttpUtil sharedManager] getAlarmList:weakSelf.deviceInfo.deviceSerial pageNo:weakSelf.currentIndex++ pageSize:EZMessageListPageSize completion:^(ResponseData * responseData) { NSArray<HDLAlarmInfo *> *alarmList = [NSArray array]; if (responseData.success){ HDLAlarmInfoData *alarmInfoData = [HDLAlarmInfoData yy_modelWithDictionary:responseData.data]; if (alarmInfoData) { if (alarmInfoData.list) { alarmList = alarmInfoData.list; } } } [weakSelf.messageList addObjectsFromArray:alarmList]; [weakSelf tableViewDidReload]; [weakSelf.tableView.mj_footer endRefreshing]; if(weakSelf.messageList.count >= weakSelf.totalCount) { weakSelf.tableView.footer.hidden = YES; weakSelf.tableView.mj_footer.hidden = YES; return; } [weakSelf tableViewDidReload:alarmList]; [weakSelf.tableView.footer endRefreshing]; }]; }]; @@ -384,9 +472,9 @@ #pragma mark - Action Methods - (void)tableViewDidReload:(NSArray *)messageList - (void)tableViewDidReload { if(messageList.count == 0) if(self.messageList.count == 0) { self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; [self.tableView reloadData]; @@ -397,28 +485,28 @@ self.noMessageLabel.frame = CGRectMake((self.tableView.frame.size.width - 100)/2.0, self.noMessage.frame.origin.y + self.noMessage.frame.size.height + 10, 100, 20.0); return; } if(self.currentIndex == 1) { [self.sections removeAllObjects]; [self.tableView.footer endRefreshing]; self.lastDate = [messageList[0] alarmStartTime]; self.dateFormatter.dateFormat = @"yyyy-MM-dd"; NSString *key = [self.dateFormatter stringFromDate:self.lastDate]; NSDictionary *dict = @{@"index":@0, @"date":key}; [self.sections addObject:dict]; } for (int i = 0; i < messageList.count; i++) { EZAlarmInfo *info = [messageList dd_objectAtIndex:i]; if(![info.alarmStartTime isSameToDate:self.lastDate]) { NSInteger index = [self.messageList indexOfObject:info]; self.dateFormatter.dateFormat = @"yyyy-MM-dd"; NSString *key = [self.dateFormatter stringFromDate:info.alarmStartTime]; NSDictionary *dict = @{@"index":@(index),@"date":key}; [self.sections addObject:dict]; } self.lastDate = info.alarmStartTime; } // if(self.currentIndex == 1) // { // [self.sections removeAllObjects]; // [self.tableView.mj_footer endRefreshing]; // self.lastDate = [messageList[0] getAlarmStartTime]; // self.dateFormatter.dateFormat = @"yyyy-MM-dd"; // NSString *key = [self.dateFormatter stringFromDate:self.lastDate]; // NSDictionary *dict = @{@"index":@0, @"date":key}; // [self.sections addObject:dict]; // } // for (int i = 0; i < messageList.count; i++) { // HDLAlarmInfo *info = [messageList dd_objectAtIndex:i]; // if(![[info getAlarmStartTime] isSameToDate:self.lastDate]) // { // NSInteger index = [self.messageList indexOfObject:info]; // self.dateFormatter.dateFormat = @"yyyy-MM-dd"; // NSString *key = [self.dateFormatter stringFromDate:[info getAlarmStartTime]]; // NSDictionary *dict = @{@"index":@(index),@"date":key}; // [self.sections addObject:dict]; // } // self.lastDate = [info getAlarmStartTime]; // } [self.tableView reloadData]; } @@ -431,19 +519,19 @@ [self.navigationController setToolbarHidden:YES animated:YES]; self.deleteSelected.title = NSLocalizedString(@"delete", @"删除"); self.deleteSelected.enabled = NO; self.readAll.title = NSLocalizedString(@"dmessage_read", @"标记已读"); self.readAll.title = NSLocalizedString(@"message_read", @"标记已读"); self.readAll.enabled = NO; [self.selectedMessageArray removeAllObjects]; self.tableView.header.hidden = NO; self.tableView.mj_header.hidden = NO; if(self.messageList.count < self.totalCount) self.tableView.footer.hidden = NO; self.tableView.mj_footer.hidden = NO; }else{ self.tableView.allowsMultipleSelectionDuringEditing = YES; [self.tableView setEditing:YES animated:YES]; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(editTableView:)]; [self.navigationController setToolbarHidden:NO animated:YES]; self.tableView.header.hidden = YES; self.tableView.footer.hidden = YES; self.tableView.mj_header.hidden = YES; self.tableView.mj_footer.hidden = YES; self.selectedAll.enabled = YES; self.deleteSelected.enabled = NO; self.readAll.enabled = NO; @@ -463,19 +551,19 @@ [self.selectedMessageArray addObjectsFromArray:self.messageList]; self.deleteSelected.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"delete", @"删除"),(int)[self.selectedMessageArray count]]; self.deleteSelected.enabled = YES; self.readAll.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"dmessage_read", @"标记已读"),(int)[self.selectedMessageArray count]]; self.readAll.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"message_read", @"标记已读"),(int)[self.selectedMessageArray count]]; self.readAll.enabled = YES; } else { self.deleteSelected.title = NSLocalizedString(@"delete", @"删除"); self.readAll.title = NSLocalizedString(@"dmessage_read", @"标记已读"); self.readAll.title = NSLocalizedString(@"message_read", @"标记已读"); [self.selectedMessageArray removeAllObjects]; self.deleteSelected.enabled = NO; self.readAll.enabled = NO; } [self.tableView reloadData]; self.tableView.footer.hidden = YES; self.tableView.mj_footer.hidden = YES; } - (IBAction)deleteMessage:(id)sender @@ -511,35 +599,57 @@ hud.labelText = NSLocalizedString(@"message_setting", @"正在设置已读,请稍候..."); NSMutableArray *alarmIds = [NSMutableArray new]; for (int i = 0; i < self.selectedMessageArray.count; i++) { EZAlarmInfo *info = [self.selectedMessageArray dd_objectAtIndex:i]; [alarmIds addObject:info.alarmId]; HDLAlarmInfo *info = [self.selectedMessageArray dd_objectAtIndex:i]; [alarmIds addObject:info.ysId]; } [EZOPENSDK setAlarmStatus:alarmIds alarmStatus:EZMessageStatusRead completion:^(NSError *error) { if(error) { hud.labelText = error.localizedDescription; // [EZOPENSDK setAlarmStatus:alarmIds // alarmStatus:EZMessageStatusRead // completion:^(NSError *error) { // if(error) // { // hud.labelText = error.localizedDescription; // hud.mode = MBProgressHUDModeText; // [hud hide:YES afterDelay:1.2]; // } // else // { // [hud hide:YES]; // } // if(!error) // { // for (int i = 0; i < self.selectedMessageArray.count; i++) { // HDLAlarmInfo *info = [self.selectedMessageArray dd_objectAtIndex:i]; // info.isChecked = YES; // } // [self editTableView:self.navigationItem.rightBarButtonItem]; // [self.tableView reloadData]; // [EZOPENSDK getUnreadMessageCount:self.deviceInfo.deviceSerial messageType:EZMessageTypeAlarm completion:^(NSInteger count, NSError *error) { // self.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"message_title", @"消息"), (int)count]; // }]; // } // }]; //标记已读 __weak __typeof(self)weakSelf = self; [[EZHttpUtil sharedManager] readAlarmMessage:alarmIds completion:^(ResponseData * responseData) { if(responseData.success){ [hud hide:YES]; for (int i = 0; i < self.selectedMessageArray.count; i++) { HDLAlarmInfo *info = [self.selectedMessageArray dd_objectAtIndex:i]; info.isChecked = YES; } [weakSelf editTableView:self.navigationItem.rightBarButtonItem]; [weakSelf.tableView reloadData]; }else{ hud.labelText = NSLocalizedString(@"setting_opration_fail", @"操作失败"); hud.mode = MBProgressHUDModeText; [hud hide:YES afterDelay:1.2]; } else { [hud hide:YES]; } if(!error) { for (int i = 0; i < self.selectedMessageArray.count; i++) { EZAlarmInfo *info = [self.selectedMessageArray dd_objectAtIndex:i]; info.isRead = YES; } [self editTableView:self.navigationItem.rightBarButtonItem]; [self.tableView reloadData]; [EZOPENSDK getUnreadMessageCount:self.deviceInfo.deviceSerial messageType:EZMessageTypeAlarm completion:^(NSInteger count, NSError *error) { self.title = [NSString stringWithFormat:@"%@(%d)",NSLocalizedString(@"message_title", @"消息"), (int)count]; }]; } }]; } - (NSString *)dateStringWithUserDefine:(NSString *)dateString EZSDK/EZSDK/EZ/UIViewControllers/EZMessagePhotoViewController.h
@@ -7,13 +7,14 @@ // #import "MWPhotoBrowser.h" #import "EZAlarmInfo.h" //#import "EZAlarmInfo.h" #import "EZDeviceInfo.h" #import "HDLAlarmInfo.h" @interface EZMessagePhotoViewController : MWPhotoBrowser @property (nonatomic, strong) UIImage *image; @property (nonatomic, strong) EZAlarmInfo *info; @property (nonatomic, strong) HDLAlarmInfo *info; @property (nonatomic, strong) EZDeviceInfo *deviceInfo; @end EZSDK/EZSDK/EZ/UIViewControllers/EZMessagePhotoViewController.m
@@ -34,8 +34,10 @@ NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.dateFormat = @"yyyy/MM/dd HH:mm:ss"; self.timeLabel.text = [formatter stringFromDate:self.info.alarmStartTime]; self.timeLabel.text = [formatter stringFromDate:[self.info getAlarmStartTime]]; self.contentLabel.text = [NSString stringWithFormat:@"%@:%@",NSLocalizedString(@"message_from", @"来自"),self.info.alarmName]; [self.recordButton setHidden:YES]; } - (void)didReceiveMemoryWarning { @@ -50,11 +52,11 @@ - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. EZAlarmInfo *info = sender; EZMessagePlaybackViewController *messagePlaybackVC = [segue destinationViewController]; messagePlaybackVC.info = info; messagePlaybackVC.deviceInfo = self.deviceInfo; // HDLAlarmInfo *info = sender; // // EZMessagePlaybackViewController *messagePlaybackVC = [segue destinationViewController]; // messagePlaybackVC.info = info; // messagePlaybackVC.deviceInfo = self.deviceInfo; } EZSDK/EZSDK/EZ/Venders/YYModel/NSObject+YYModel.h
New file @@ -0,0 +1,440 @@ // // NSObject+YYModel.h // YYModel <https://github.com/ibireme/YYModel> // // Created by ibireme on 15/5/10. // Copyright (c) 2015 ibireme. // // This source code is licensed under the MIT-style license found in the // LICENSE file in the root directory of this source tree. // #import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN /** Provide some data-model method: * Convert json to any object, or convert any object to json. * Set object properties with a key-value dictionary (like KVC). * Implementations of `NSCoding`, `NSCopying`, `-hash` and `-isEqual:`. See `YYModel` protocol for custom methods. Sample Code: ********************** json convertor ********************* @code @interface YYAuthor : NSObject @property (nonatomic, strong) NSString *name; @property (nonatomic, assign) NSDate *birthday; @end @implementation YYAuthor @end @interface YYBook : NSObject @property (nonatomic, copy) NSString *name; @property (nonatomic, assign) NSUInteger pages; @property (nonatomic, strong) YYAuthor *author; @end @implementation YYBook @end int main() { // create model from json YYBook *book = [YYBook yy_modelWithJSON:@"{\"name\": \"Harry Potter\", \"pages\": 256, \"author\": {\"name\": \"J.K.Rowling\", \"birthday\": \"1965-07-31\" }}"]; // convert model to json NSString *json = [book yy_modelToJSONString]; // {"author":{"name":"J.K.Rowling","birthday":"1965-07-31T00:00:00+0000"},"name":"Harry Potter","pages":256} } @endcode ********************** Coding/Copying/hash/equal ********************* @code @interface YYShadow :NSObject <NSCoding, NSCopying> @property (nonatomic, copy) NSString *name; @property (nonatomic, assign) CGSize size; @end @implementation YYShadow - (void)encodeWithCoder:(NSCoder *)aCoder { [self yy_modelEncodeWithCoder:aCoder]; } - (id)initWithCoder:(NSCoder *)aDecoder { self = [super init]; return [self yy_modelInitWithCoder:aDecoder]; } - (id)copyWithZone:(NSZone *)zone { return [self yy_modelCopy]; } - (NSUInteger)hash { return [self yy_modelHash]; } - (BOOL)isEqual:(id)object { return [self yy_modelIsEqual:object]; } @end @endcode */ @interface NSObject (YYModel) /** Creates and returns a new instance of the receiver from a json. This method is thread-safe. @param json A json object in `NSDictionary`, `NSString` or `NSData`. @return A new instance created from the json, or nil if an error occurs. */ + (nullable instancetype)yy_modelWithJSON:(id)json; /** Creates and returns a new instance of the receiver from a key-value dictionary. This method is thread-safe. @param dictionary A key-value dictionary mapped to the instance's properties. Any invalid key-value pair in dictionary will be ignored. @return A new instance created from the dictionary, or nil if an error occurs. @discussion The key in `dictionary` will mapped to the reciever's property name, and the value will set to the property. If the value's type does not match the property, this method will try to convert the value based on these rules: `NSString` or `NSNumber` -> c number, such as BOOL, int, long, float, NSUInteger... `NSString` -> NSDate, parsed with format "yyyy-MM-dd'T'HH:mm:ssZ", "yyyy-MM-dd HH:mm:ss" or "yyyy-MM-dd". `NSString` -> NSURL. `NSValue` -> struct or union, such as CGRect, CGSize, ... `NSString` -> SEL, Class. */ + (nullable instancetype)yy_modelWithDictionary:(NSDictionary *)dictionary; /** Set the receiver's properties with a json object. @discussion Any invalid data in json will be ignored. @param json A json object of `NSDictionary`, `NSString` or `NSData`, mapped to the receiver's properties. @return Whether succeed. */ - (BOOL)yy_modelSetWithJSON:(id)json; /** Set the receiver's properties with a key-value dictionary. @param dic A key-value dictionary mapped to the receiver's properties. Any invalid key-value pair in dictionary will be ignored. @discussion The key in `dictionary` will mapped to the reciever's property name, and the value will set to the property. If the value's type doesn't match the property, this method will try to convert the value based on these rules: `NSString`, `NSNumber` -> c number, such as BOOL, int, long, float, NSUInteger... `NSString` -> NSDate, parsed with format "yyyy-MM-dd'T'HH:mm:ssZ", "yyyy-MM-dd HH:mm:ss" or "yyyy-MM-dd". `NSString` -> NSURL. `NSValue` -> struct or union, such as CGRect, CGSize, ... `NSString` -> SEL, Class. @return Whether succeed. */ - (BOOL)yy_modelSetWithDictionary:(NSDictionary *)dic; /** Generate a json object from the receiver's properties. @return A json object in `NSDictionary` or `NSArray`, or nil if an error occurs. See [NSJSONSerialization isValidJSONObject] for more information. @discussion Any of the invalid property is ignored. If the reciver is `NSArray`, `NSDictionary` or `NSSet`, it just convert the inner object to json object. */ - (nullable id)yy_modelToJSONObject; /** Generate a json string's data from the receiver's properties. @return A json string's data, or nil if an error occurs. @discussion Any of the invalid property is ignored. If the reciver is `NSArray`, `NSDictionary` or `NSSet`, it will also convert the inner object to json string. */ - (nullable NSData *)yy_modelToJSONData; /** Generate a json string from the receiver's properties. @return A json string, or nil if an error occurs. @discussion Any of the invalid property is ignored. If the reciver is `NSArray`, `NSDictionary` or `NSSet`, it will also convert the inner object to json string. */ - (nullable NSString *)yy_modelToJSONString; /** Copy a instance with the receiver's properties. @return A copied instance, or nil if an error occurs. */ - (nullable id)yy_modelCopy; /** Encode the receiver's properties to a coder. @param aCoder An archiver object. */ - (void)yy_modelEncodeWithCoder:(NSCoder *)aCoder; /** Decode the receiver's properties from a decoder. @param aDecoder An archiver object. @return self */ - (id)yy_modelInitWithCoder:(NSCoder *)aDecoder; /** Get a hash code with the receiver's properties. @return Hash code. */ - (NSUInteger)yy_modelHash; /** Compares the receiver with another object for equality, based on properties. @param model Another object. @return `YES` if the reciever is equal to the object, otherwise `NO`. */ - (BOOL)yy_modelIsEqual:(id)model; /** Description method for debugging purposes based on properties. @return A string that describes the contents of the receiver. */ - (NSString *)yy_modelDescription; @end /** Provide some data-model method for NSArray. */ @interface NSArray (YYModel) /** Creates and returns an array from a json-array. This method is thread-safe. @param cls The instance's class in array. @param json A json array of `NSArray`, `NSString` or `NSData`. Example: [{"name":"Mary"},{name:"Joe"}] @return A array, or nil if an error occurs. */ + (nullable NSArray *)yy_modelArrayWithClass:(Class)cls json:(id)json; @end /** Provide some data-model method for NSDictionary. */ @interface NSDictionary (YYModel) /** Creates and returns a dictionary from a json. This method is thread-safe. @param cls The value instance's class in dictionary. @param json A json dictionary of `NSDictionary`, `NSString` or `NSData`. Example: {"user1":{"name","Mary"}, "user2": {name:"Joe"}} @return A dictionary, or nil if an error occurs. */ + (nullable NSDictionary *)yy_modelDictionaryWithClass:(Class)cls json:(id)json; @end /** If the default model transform does not fit to your model class, implement one or more method in this protocol to change the default key-value transform process. There's no need to add '<YYModel>' to your class header. */ @protocol YYModel <NSObject> @optional /** Custom property mapper. @discussion If the key in JSON/Dictionary does not match to the model's property name, implements this method and returns the additional mapper. Example: json: { "n":"Harry Pottery", "p": 256, "ext" : { "desc" : "A book written by J.K.Rowling." }, "ID" : 100010 } model: @code @interface YYBook : NSObject @property NSString *name; @property NSInteger page; @property NSString *desc; @property NSString *bookID; @end @implementation YYBook + (NSDictionary *)modelCustomPropertyMapper { return @{@"name" : @"n", @"page" : @"p", @"desc" : @"ext.desc", @"bookID": @[@"id", @"ID", @"book_id"]}; } @end @endcode @return A custom mapper for properties. */ + (nullable NSDictionary<NSString *, id> *)modelCustomPropertyMapper; /** The generic class mapper for container properties. @discussion If the property is a container object, such as NSArray/NSSet/NSDictionary, implements this method and returns a property->class mapper, tells which kind of object will be add to the array/set/dictionary. Example: @code @class YYShadow, YYBorder, YYAttachment; @interface YYAttributes @property NSString *name; @property NSArray *shadows; @property NSSet *borders; @property NSDictionary *attachments; @end @implementation YYAttributes + (NSDictionary *)modelContainerPropertyGenericClass { return @{@"shadows" : [YYShadow class], @"borders" : YYBorder.class, @"attachments" : @"YYAttachment" }; } @end @endcode @return A class mapper. */ + (nullable NSDictionary<NSString *, id> *)modelContainerPropertyGenericClass; /** If you need to create instances of different classes during json->object transform, use the method to choose custom class based on dictionary data. @discussion If the model implements this method, it will be called to determine resulting class during `+modelWithJSON:`, `+modelWithDictionary:`, conveting object of properties of parent objects (both singular and containers via `+modelContainerPropertyGenericClass`). Example: @code @class YYCircle, YYRectangle, YYLine; @implementation YYShape + (Class)modelCustomClassForDictionary:(NSDictionary*)dictionary { if (dictionary[@"radius"] != nil) { return [YYCircle class]; } else if (dictionary[@"width"] != nil) { return [YYRectangle class]; } else if (dictionary[@"y2"] != nil) { return [YYLine class]; } else { return [self class]; } } @end @endcode @param dictionary The json/kv dictionary. @return Class to create from this dictionary, `nil` to use current class. */ + (nullable Class)modelCustomClassForDictionary:(NSDictionary *)dictionary; /** All the properties in blacklist will be ignored in model transform process. Returns nil to ignore this feature. @return An array of property's name. */ + (nullable NSArray<NSString *> *)modelPropertyBlacklist; /** If a property is not in the whitelist, it will be ignored in model transform process. Returns nil to ignore this feature. @return An array of property's name. */ + (nullable NSArray<NSString *> *)modelPropertyWhitelist; /** This method's behavior is similar to `- (BOOL)modelCustomTransformFromDictionary:(NSDictionary *)dic;`, but be called before the model transform. @discussion If the model implements this method, it will be called before `+modelWithJSON:`, `+modelWithDictionary:`, `-modelSetWithJSON:` and `-modelSetWithDictionary:`. If this method returns nil, the transform process will ignore this model. @param dic The json/kv dictionary. @return Returns the modified dictionary, or nil to ignore this model. */ - (NSDictionary *)modelCustomWillTransformFromDictionary:(NSDictionary *)dic; /** If the default json-to-model transform does not fit to your model object, implement this method to do additional process. You can also use this method to validate the model's properties. @discussion If the model implements this method, it will be called at the end of `+modelWithJSON:`, `+modelWithDictionary:`, `-modelSetWithJSON:` and `-modelSetWithDictionary:`. If this method returns NO, the transform process will ignore this model. @param dic The json/kv dictionary. @return Returns YES if the model is valid, or NO to ignore this model. */ - (BOOL)modelCustomTransformFromDictionary:(NSDictionary *)dic; /** If the default model-to-json transform does not fit to your model class, implement this method to do additional process. You can also use this method to validate the json dictionary. @discussion If the model implements this method, it will be called at the end of `-modelToJSONObject` and `-modelToJSONString`. If this method returns NO, the transform process will ignore this json dictionary. @param dic The json dictionary. @return Returns YES if the model is valid, or NO to ignore this model. */ - (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic; @end NS_ASSUME_NONNULL_END EZSDK/EZSDK/EZ/Venders/YYModel/NSObject+YYModel.m
New file @@ -0,0 +1,1839 @@ // // NSObject+YYModel.m // YYModel <https://github.com/ibireme/YYModel> // // Created by ibireme on 15/5/10. // Copyright (c) 2015 ibireme. // // This source code is licensed under the MIT-style license found in the // LICENSE file in the root directory of this source tree. // #import "NSObject+YYModel.h" #import "YYClassInfo.h" #import <objc/message.h> #define force_inline __inline__ __attribute__((always_inline)) /// Foundation Class Type typedef NS_ENUM (NSUInteger, YYEncodingNSType) { YYEncodingTypeNSUnknown = 0, YYEncodingTypeNSString, YYEncodingTypeNSMutableString, YYEncodingTypeNSValue, YYEncodingTypeNSNumber, YYEncodingTypeNSDecimalNumber, YYEncodingTypeNSData, YYEncodingTypeNSMutableData, YYEncodingTypeNSDate, YYEncodingTypeNSURL, YYEncodingTypeNSArray, YYEncodingTypeNSMutableArray, YYEncodingTypeNSDictionary, YYEncodingTypeNSMutableDictionary, YYEncodingTypeNSSet, YYEncodingTypeNSMutableSet, }; /// Get the Foundation class type from property info. static force_inline YYEncodingNSType YYClassGetNSType(Class cls) { if (!cls) return YYEncodingTypeNSUnknown; if ([cls isSubclassOfClass:[NSMutableString class]]) return YYEncodingTypeNSMutableString; if ([cls isSubclassOfClass:[NSString class]]) return YYEncodingTypeNSString; if ([cls isSubclassOfClass:[NSDecimalNumber class]]) return YYEncodingTypeNSDecimalNumber; if ([cls isSubclassOfClass:[NSNumber class]]) return YYEncodingTypeNSNumber; if ([cls isSubclassOfClass:[NSValue class]]) return YYEncodingTypeNSValue; if ([cls isSubclassOfClass:[NSMutableData class]]) return YYEncodingTypeNSMutableData; if ([cls isSubclassOfClass:[NSData class]]) return YYEncodingTypeNSData; if ([cls isSubclassOfClass:[NSDate class]]) return YYEncodingTypeNSDate; if ([cls isSubclassOfClass:[NSURL class]]) return YYEncodingTypeNSURL; if ([cls isSubclassOfClass:[NSMutableArray class]]) return YYEncodingTypeNSMutableArray; if ([cls isSubclassOfClass:[NSArray class]]) return YYEncodingTypeNSArray; if ([cls isSubclassOfClass:[NSMutableDictionary class]]) return YYEncodingTypeNSMutableDictionary; if ([cls isSubclassOfClass:[NSDictionary class]]) return YYEncodingTypeNSDictionary; if ([cls isSubclassOfClass:[NSMutableSet class]]) return YYEncodingTypeNSMutableSet; if ([cls isSubclassOfClass:[NSSet class]]) return YYEncodingTypeNSSet; return YYEncodingTypeNSUnknown; } /// Whether the type is c number. static force_inline BOOL YYEncodingTypeIsCNumber(YYEncodingType type) { switch (type & YYEncodingTypeMask) { case YYEncodingTypeBool: case YYEncodingTypeInt8: case YYEncodingTypeUInt8: case YYEncodingTypeInt16: case YYEncodingTypeUInt16: case YYEncodingTypeInt32: case YYEncodingTypeUInt32: case YYEncodingTypeInt64: case YYEncodingTypeUInt64: case YYEncodingTypeFloat: case YYEncodingTypeDouble: case YYEncodingTypeLongDouble: return YES; default: return NO; } } /// Parse a number value from 'id'. static force_inline NSNumber *YYNSNumberCreateFromID(__unsafe_unretained id value) { static NSCharacterSet *dot; static NSDictionary *dic; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ dot = [NSCharacterSet characterSetWithRange:NSMakeRange('.', 1)]; dic = @{@"TRUE" : @(YES), @"True" : @(YES), @"true" : @(YES), @"FALSE" : @(NO), @"False" : @(NO), @"false" : @(NO), @"YES" : @(YES), @"Yes" : @(YES), @"yes" : @(YES), @"NO" : @(NO), @"No" : @(NO), @"no" : @(NO), @"NIL" : (id)kCFNull, @"Nil" : (id)kCFNull, @"nil" : (id)kCFNull, @"NULL" : (id)kCFNull, @"Null" : (id)kCFNull, @"null" : (id)kCFNull, @"(NULL)" : (id)kCFNull, @"(Null)" : (id)kCFNull, @"(null)" : (id)kCFNull, @"<NULL>" : (id)kCFNull, @"<Null>" : (id)kCFNull, @"<null>" : (id)kCFNull}; }); if (!value || value == (id)kCFNull) return nil; if ([value isKindOfClass:[NSNumber class]]) return value; if ([value isKindOfClass:[NSString class]]) { NSNumber *num = dic[value]; if (num != nil) { if (num == (id)kCFNull) return nil; return num; } if ([(NSString *)value rangeOfCharacterFromSet:dot].location != NSNotFound) { const char *cstring = ((NSString *)value).UTF8String; if (!cstring) return nil; double num = atof(cstring); if (isnan(num) || isinf(num)) return nil; return @(num); } else { const char *cstring = ((NSString *)value).UTF8String; if (!cstring) return nil; return @(atoll(cstring)); } } return nil; } /// Parse string to date. static force_inline NSDate *YYNSDateFromString(__unsafe_unretained NSString *string) { typedef NSDate* (^YYNSDateParseBlock)(NSString *string); #define kParserNum 34 static YYNSDateParseBlock blocks[kParserNum + 1] = {0}; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ { /* 2014-01-20 // Google */ NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; formatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; formatter.dateFormat = @"yyyy-MM-dd"; blocks[10] = ^(NSString *string) { return [formatter dateFromString:string]; }; } { /* 2014-01-20 12:24:48 2014-01-20T12:24:48 // Google 2014-01-20 12:24:48.000 2014-01-20T12:24:48.000 */ NSDateFormatter *formatter1 = [[NSDateFormatter alloc] init]; formatter1.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; formatter1.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; formatter1.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss"; NSDateFormatter *formatter2 = [[NSDateFormatter alloc] init]; formatter2.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; formatter2.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; formatter2.dateFormat = @"yyyy-MM-dd HH:mm:ss"; NSDateFormatter *formatter3 = [[NSDateFormatter alloc] init]; formatter3.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; formatter3.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; formatter3.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss.SSS"; NSDateFormatter *formatter4 = [[NSDateFormatter alloc] init]; formatter4.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; formatter4.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; formatter4.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSS"; blocks[19] = ^(NSString *string) { if ([string characterAtIndex:10] == 'T') { return [formatter1 dateFromString:string]; } else { return [formatter2 dateFromString:string]; } }; blocks[23] = ^(NSString *string) { if ([string characterAtIndex:10] == 'T') { return [formatter3 dateFromString:string]; } else { return [formatter4 dateFromString:string]; } }; } { /* 2014-01-20T12:24:48Z // Github, Apple 2014-01-20T12:24:48+0800 // Facebook 2014-01-20T12:24:48+12:00 // Google 2014-01-20T12:24:48.000Z 2014-01-20T12:24:48.000+0800 2014-01-20T12:24:48.000+12:00 */ NSDateFormatter *formatter = [NSDateFormatter new]; formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ssZ"; NSDateFormatter *formatter2 = [NSDateFormatter new]; formatter2.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; formatter2.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss.SSSZ"; blocks[20] = ^(NSString *string) { return [formatter dateFromString:string]; }; blocks[24] = ^(NSString *string) { return [formatter dateFromString:string]?: [formatter2 dateFromString:string]; }; blocks[25] = ^(NSString *string) { return [formatter dateFromString:string]; }; blocks[28] = ^(NSString *string) { return [formatter2 dateFromString:string]; }; blocks[29] = ^(NSString *string) { return [formatter2 dateFromString:string]; }; } { /* Fri Sep 04 00:12:21 +0800 2015 // Weibo, Twitter Fri Sep 04 00:12:21.000 +0800 2015 */ NSDateFormatter *formatter = [NSDateFormatter new]; formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; formatter.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy"; NSDateFormatter *formatter2 = [NSDateFormatter new]; formatter2.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; formatter2.dateFormat = @"EEE MMM dd HH:mm:ss.SSS Z yyyy"; blocks[30] = ^(NSString *string) { return [formatter dateFromString:string]; }; blocks[34] = ^(NSString *string) { return [formatter2 dateFromString:string]; }; } }); if (!string) return nil; if (string.length > kParserNum) return nil; YYNSDateParseBlock parser = blocks[string.length]; if (!parser) return nil; return parser(string); #undef kParserNum } /// Get the 'NSBlock' class. static force_inline Class YYNSBlockClass() { static Class cls; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ void (^block)(void) = ^{}; cls = ((NSObject *)block).class; while (class_getSuperclass(cls) != [NSObject class]) { cls = class_getSuperclass(cls); } }); return cls; // current is "NSBlock" } /** Get the ISO date formatter. ISO8601 format example: 2010-07-09T16:13:30+12:00 2011-01-11T11:11:11+0000 2011-01-26T19:06:43Z length: 20/24/25 */ static force_inline NSDateFormatter *YYISODateFormatter() { static NSDateFormatter *formatter = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ formatter = [[NSDateFormatter alloc] init]; formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ssZ"; }); return formatter; } /// Get the value with key paths from dictionary /// The dic should be NSDictionary, and the keyPath should not be nil. static force_inline id YYValueForKeyPath(__unsafe_unretained NSDictionary *dic, __unsafe_unretained NSArray *keyPaths) { id value = nil; for (NSUInteger i = 0, max = keyPaths.count; i < max; i++) { value = dic[keyPaths[i]]; if (i + 1 < max) { if ([value isKindOfClass:[NSDictionary class]]) { dic = value; } else { return nil; } } } return value; } /// Get the value with multi key (or key path) from dictionary /// The dic should be NSDictionary static force_inline id YYValueForMultiKeys(__unsafe_unretained NSDictionary *dic, __unsafe_unretained NSArray *multiKeys) { id value = nil; for (NSString *key in multiKeys) { if ([key isKindOfClass:[NSString class]]) { value = dic[key]; if (value) break; } else { value = YYValueForKeyPath(dic, (NSArray *)key); if (value) break; } } return value; } /// A property info in object model. @interface _YYModelPropertyMeta : NSObject { @package NSString *_name; ///< property's name YYEncodingType _type; ///< property's type YYEncodingNSType _nsType; ///< property's Foundation type BOOL _isCNumber; ///< is c number type Class _cls; ///< property's class, or nil Class _genericCls; ///< container's generic class, or nil if threr's no generic class SEL _getter; ///< getter, or nil if the instances cannot respond SEL _setter; ///< setter, or nil if the instances cannot respond BOOL _isKVCCompatible; ///< YES if it can access with key-value coding BOOL _isStructAvailableForKeyedArchiver; ///< YES if the struct can encoded with keyed archiver/unarchiver BOOL _hasCustomClassFromDictionary; ///< class/generic class implements +modelCustomClassForDictionary: /* property->key: _mappedToKey:key _mappedToKeyPath:nil _mappedToKeyArray:nil property->keyPath: _mappedToKey:keyPath _mappedToKeyPath:keyPath(array) _mappedToKeyArray:nil property->keys: _mappedToKey:keys[0] _mappedToKeyPath:nil/keyPath _mappedToKeyArray:keys(array) */ NSString *_mappedToKey; ///< the key mapped to NSArray *_mappedToKeyPath; ///< the key path mapped to (nil if the name is not key path) NSArray *_mappedToKeyArray; ///< the key(NSString) or keyPath(NSArray) array (nil if not mapped to multiple keys) YYClassPropertyInfo *_info; ///< property's info _YYModelPropertyMeta *_next; ///< next meta if there are multiple properties mapped to the same key. } @end @implementation _YYModelPropertyMeta + (instancetype)metaWithClassInfo:(YYClassInfo *)classInfo propertyInfo:(YYClassPropertyInfo *)propertyInfo generic:(Class)generic { // support pseudo generic class with protocol name if (!generic && propertyInfo.protocols) { for (NSString *protocol in propertyInfo.protocols) { Class cls = objc_getClass(protocol.UTF8String); if (cls) { generic = cls; break; } } } _YYModelPropertyMeta *meta = [self new]; meta->_name = propertyInfo.name; meta->_type = propertyInfo.type; meta->_info = propertyInfo; meta->_genericCls = generic; if ((meta->_type & YYEncodingTypeMask) == YYEncodingTypeObject) { meta->_nsType = YYClassGetNSType(propertyInfo.cls); } else { meta->_isCNumber = YYEncodingTypeIsCNumber(meta->_type); } if ((meta->_type & YYEncodingTypeMask) == YYEncodingTypeStruct) { /* It seems that NSKeyedUnarchiver cannot decode NSValue except these structs: */ static NSSet *types = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSMutableSet *set = [NSMutableSet new]; // 32 bit [set addObject:@"{CGSize=ff}"]; [set addObject:@"{CGPoint=ff}"]; [set addObject:@"{CGRect={CGPoint=ff}{CGSize=ff}}"]; [set addObject:@"{CGAffineTransform=ffffff}"]; [set addObject:@"{UIEdgeInsets=ffff}"]; [set addObject:@"{UIOffset=ff}"]; // 64 bit [set addObject:@"{CGSize=dd}"]; [set addObject:@"{CGPoint=dd}"]; [set addObject:@"{CGRect={CGPoint=dd}{CGSize=dd}}"]; [set addObject:@"{CGAffineTransform=dddddd}"]; [set addObject:@"{UIEdgeInsets=dddd}"]; [set addObject:@"{UIOffset=dd}"]; types = set; }); if ([types containsObject:propertyInfo.typeEncoding]) { meta->_isStructAvailableForKeyedArchiver = YES; } } meta->_cls = propertyInfo.cls; if (generic) { meta->_hasCustomClassFromDictionary = [generic respondsToSelector:@selector(modelCustomClassForDictionary:)]; } else if (meta->_cls && meta->_nsType == YYEncodingTypeNSUnknown) { meta->_hasCustomClassFromDictionary = [meta->_cls respondsToSelector:@selector(modelCustomClassForDictionary:)]; } if (propertyInfo.getter) { if ([classInfo.cls instancesRespondToSelector:propertyInfo.getter]) { meta->_getter = propertyInfo.getter; } } if (propertyInfo.setter) { if ([classInfo.cls instancesRespondToSelector:propertyInfo.setter]) { meta->_setter = propertyInfo.setter; } } if (meta->_getter && meta->_setter) { /* KVC invalid type: long double pointer (such as SEL/CoreFoundation object) */ switch (meta->_type & YYEncodingTypeMask) { case YYEncodingTypeBool: case YYEncodingTypeInt8: case YYEncodingTypeUInt8: case YYEncodingTypeInt16: case YYEncodingTypeUInt16: case YYEncodingTypeInt32: case YYEncodingTypeUInt32: case YYEncodingTypeInt64: case YYEncodingTypeUInt64: case YYEncodingTypeFloat: case YYEncodingTypeDouble: case YYEncodingTypeObject: case YYEncodingTypeClass: case YYEncodingTypeBlock: case YYEncodingTypeStruct: case YYEncodingTypeUnion: { meta->_isKVCCompatible = YES; } break; default: break; } } return meta; } @end /// A class info in object model. @interface _YYModelMeta : NSObject { @package YYClassInfo *_classInfo; /// Key:mapped key and key path, Value:_YYModelPropertyMeta. NSDictionary *_mapper; /// Array<_YYModelPropertyMeta>, all property meta of this model. NSArray *_allPropertyMetas; /// Array<_YYModelPropertyMeta>, property meta which is mapped to a key path. NSArray *_keyPathPropertyMetas; /// Array<_YYModelPropertyMeta>, property meta which is mapped to multi keys. NSArray *_multiKeysPropertyMetas; /// The number of mapped key (and key path), same to _mapper.count. NSUInteger _keyMappedCount; /// Model class type. YYEncodingNSType _nsType; BOOL _hasCustomWillTransformFromDictionary; BOOL _hasCustomTransformFromDictionary; BOOL _hasCustomTransformToDictionary; BOOL _hasCustomClassFromDictionary; } @end @implementation _YYModelMeta - (instancetype)initWithClass:(Class)cls { YYClassInfo *classInfo = [YYClassInfo classInfoWithClass:cls]; if (!classInfo) return nil; self = [super init]; // Get black list NSSet *blacklist = nil; if ([cls respondsToSelector:@selector(modelPropertyBlacklist)]) { NSArray *properties = [(id<YYModel>)cls modelPropertyBlacklist]; if (properties) { blacklist = [NSSet setWithArray:properties]; } } // Get white list NSSet *whitelist = nil; if ([cls respondsToSelector:@selector(modelPropertyWhitelist)]) { NSArray *properties = [(id<YYModel>)cls modelPropertyWhitelist]; if (properties) { whitelist = [NSSet setWithArray:properties]; } } // Get container property's generic class NSDictionary *genericMapper = nil; if ([cls respondsToSelector:@selector(modelContainerPropertyGenericClass)]) { genericMapper = [(id<YYModel>)cls modelContainerPropertyGenericClass]; if (genericMapper) { NSMutableDictionary *tmp = [NSMutableDictionary new]; [genericMapper enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { if (![key isKindOfClass:[NSString class]]) return; Class meta = object_getClass(obj); if (!meta) return; if (class_isMetaClass(meta)) { tmp[key] = obj; } else if ([obj isKindOfClass:[NSString class]]) { Class cls = NSClassFromString(obj); if (cls) { tmp[key] = cls; } } }]; genericMapper = tmp; } } // Create all property metas. NSMutableDictionary *allPropertyMetas = [NSMutableDictionary new]; YYClassInfo *curClassInfo = classInfo; while (curClassInfo && curClassInfo.superCls != nil) { // recursive parse super class, but ignore root class (NSObject/NSProxy) for (YYClassPropertyInfo *propertyInfo in curClassInfo.propertyInfos.allValues) { if (!propertyInfo.name) continue; if (blacklist && [blacklist containsObject:propertyInfo.name]) continue; if (whitelist && ![whitelist containsObject:propertyInfo.name]) continue; _YYModelPropertyMeta *meta = [_YYModelPropertyMeta metaWithClassInfo:classInfo propertyInfo:propertyInfo generic:genericMapper[propertyInfo.name]]; if (!meta || !meta->_name) continue; if (!meta->_getter || !meta->_setter) continue; if (allPropertyMetas[meta->_name]) continue; allPropertyMetas[meta->_name] = meta; } curClassInfo = curClassInfo.superClassInfo; } if (allPropertyMetas.count) _allPropertyMetas = allPropertyMetas.allValues.copy; // create mapper NSMutableDictionary *mapper = [NSMutableDictionary new]; NSMutableArray *keyPathPropertyMetas = [NSMutableArray new]; NSMutableArray *multiKeysPropertyMetas = [NSMutableArray new]; if ([cls respondsToSelector:@selector(modelCustomPropertyMapper)]) { NSDictionary *customMapper = [(id <YYModel>)cls modelCustomPropertyMapper]; [customMapper enumerateKeysAndObjectsUsingBlock:^(NSString *propertyName, NSString *mappedToKey, BOOL *stop) { _YYModelPropertyMeta *propertyMeta = allPropertyMetas[propertyName]; if (!propertyMeta) return; [allPropertyMetas removeObjectForKey:propertyName]; if ([mappedToKey isKindOfClass:[NSString class]]) { if (mappedToKey.length == 0) return; propertyMeta->_mappedToKey = mappedToKey; NSArray *keyPath = [mappedToKey componentsSeparatedByString:@"."]; for (NSString *onePath in keyPath) { if (onePath.length == 0) { NSMutableArray *tmp = keyPath.mutableCopy; [tmp removeObject:@""]; keyPath = tmp; break; } } if (keyPath.count > 1) { propertyMeta->_mappedToKeyPath = keyPath; [keyPathPropertyMetas addObject:propertyMeta]; } propertyMeta->_next = mapper[mappedToKey] ?: nil; mapper[mappedToKey] = propertyMeta; } else if ([mappedToKey isKindOfClass:[NSArray class]]) { NSMutableArray *mappedToKeyArray = [NSMutableArray new]; for (NSString *oneKey in ((NSArray *)mappedToKey)) { if (![oneKey isKindOfClass:[NSString class]]) continue; if (oneKey.length == 0) continue; NSArray *keyPath = [oneKey componentsSeparatedByString:@"."]; if (keyPath.count > 1) { [mappedToKeyArray addObject:keyPath]; } else { [mappedToKeyArray addObject:oneKey]; } if (!propertyMeta->_mappedToKey) { propertyMeta->_mappedToKey = oneKey; propertyMeta->_mappedToKeyPath = keyPath.count > 1 ? keyPath : nil; } } if (!propertyMeta->_mappedToKey) return; propertyMeta->_mappedToKeyArray = mappedToKeyArray; [multiKeysPropertyMetas addObject:propertyMeta]; propertyMeta->_next = mapper[mappedToKey] ?: nil; mapper[mappedToKey] = propertyMeta; } }]; } [allPropertyMetas enumerateKeysAndObjectsUsingBlock:^(NSString *name, _YYModelPropertyMeta *propertyMeta, BOOL *stop) { propertyMeta->_mappedToKey = name; propertyMeta->_next = mapper[name] ?: nil; mapper[name] = propertyMeta; }]; if (mapper.count) _mapper = mapper; if (keyPathPropertyMetas) _keyPathPropertyMetas = keyPathPropertyMetas; if (multiKeysPropertyMetas) _multiKeysPropertyMetas = multiKeysPropertyMetas; _classInfo = classInfo; _keyMappedCount = _allPropertyMetas.count; _nsType = YYClassGetNSType(cls); _hasCustomWillTransformFromDictionary = ([cls instancesRespondToSelector:@selector(modelCustomWillTransformFromDictionary:)]); _hasCustomTransformFromDictionary = ([cls instancesRespondToSelector:@selector(modelCustomTransformFromDictionary:)]); _hasCustomTransformToDictionary = ([cls instancesRespondToSelector:@selector(modelCustomTransformToDictionary:)]); _hasCustomClassFromDictionary = ([cls respondsToSelector:@selector(modelCustomClassForDictionary:)]); return self; } /// Returns the cached model class meta + (instancetype)metaWithClass:(Class)cls { if (!cls) return nil; static CFMutableDictionaryRef cache; static dispatch_once_t onceToken; static dispatch_semaphore_t lock; dispatch_once(&onceToken, ^{ cache = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); lock = dispatch_semaphore_create(1); }); dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); _YYModelMeta *meta = CFDictionaryGetValue(cache, (__bridge const void *)(cls)); dispatch_semaphore_signal(lock); if (!meta || meta->_classInfo.needUpdate) { meta = [[_YYModelMeta alloc] initWithClass:cls]; if (meta) { dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); CFDictionarySetValue(cache, (__bridge const void *)(cls), (__bridge const void *)(meta)); dispatch_semaphore_signal(lock); } } return meta; } @end /** Get number from property. @discussion Caller should hold strong reference to the parameters before this function returns. @param model Should not be nil. @param meta Should not be nil, meta.isCNumber should be YES, meta.getter should not be nil. @return A number object, or nil if failed. */ static force_inline NSNumber *ModelCreateNumberFromProperty(__unsafe_unretained id model, __unsafe_unretained _YYModelPropertyMeta *meta) { switch (meta->_type & YYEncodingTypeMask) { case YYEncodingTypeBool: { return @(((bool (*)(id, SEL))(void *) objc_msgSend)((id)model, meta->_getter)); } case YYEncodingTypeInt8: { return @(((int8_t (*)(id, SEL))(void *) objc_msgSend)((id)model, meta->_getter)); } case YYEncodingTypeUInt8: { return @(((uint8_t (*)(id, SEL))(void *) objc_msgSend)((id)model, meta->_getter)); } case YYEncodingTypeInt16: { return @(((int16_t (*)(id, SEL))(void *) objc_msgSend)((id)model, meta->_getter)); } case YYEncodingTypeUInt16: { return @(((uint16_t (*)(id, SEL))(void *) objc_msgSend)((id)model, meta->_getter)); } case YYEncodingTypeInt32: { return @(((int32_t (*)(id, SEL))(void *) objc_msgSend)((id)model, meta->_getter)); } case YYEncodingTypeUInt32: { return @(((uint32_t (*)(id, SEL))(void *) objc_msgSend)((id)model, meta->_getter)); } case YYEncodingTypeInt64: { return @(((int64_t (*)(id, SEL))(void *) objc_msgSend)((id)model, meta->_getter)); } case YYEncodingTypeUInt64: { return @(((uint64_t (*)(id, SEL))(void *) objc_msgSend)((id)model, meta->_getter)); } case YYEncodingTypeFloat: { float num = ((float (*)(id, SEL))(void *) objc_msgSend)((id)model, meta->_getter); if (isnan(num) || isinf(num)) return nil; return @(num); } case YYEncodingTypeDouble: { double num = ((double (*)(id, SEL))(void *) objc_msgSend)((id)model, meta->_getter); if (isnan(num) || isinf(num)) return nil; return @(num); } case YYEncodingTypeLongDouble: { double num = ((long double (*)(id, SEL))(void *) objc_msgSend)((id)model, meta->_getter); if (isnan(num) || isinf(num)) return nil; return @(num); } default: return nil; } } /** Set number to property. @discussion Caller should hold strong reference to the parameters before this function returns. @param model Should not be nil. @param num Can be nil. @param meta Should not be nil, meta.isCNumber should be YES, meta.setter should not be nil. */ static force_inline void ModelSetNumberToProperty(__unsafe_unretained id model, __unsafe_unretained NSNumber *num, __unsafe_unretained _YYModelPropertyMeta *meta) { switch (meta->_type & YYEncodingTypeMask) { case YYEncodingTypeBool: { ((void (*)(id, SEL, bool))(void *) objc_msgSend)((id)model, meta->_setter, num.boolValue); } break; case YYEncodingTypeInt8: { ((void (*)(id, SEL, int8_t))(void *) objc_msgSend)((id)model, meta->_setter, (int8_t)num.charValue); } break; case YYEncodingTypeUInt8: { ((void (*)(id, SEL, uint8_t))(void *) objc_msgSend)((id)model, meta->_setter, (uint8_t)num.unsignedCharValue); } break; case YYEncodingTypeInt16: { ((void (*)(id, SEL, int16_t))(void *) objc_msgSend)((id)model, meta->_setter, (int16_t)num.shortValue); } break; case YYEncodingTypeUInt16: { ((void (*)(id, SEL, uint16_t))(void *) objc_msgSend)((id)model, meta->_setter, (uint16_t)num.unsignedShortValue); } break; case YYEncodingTypeInt32: { ((void (*)(id, SEL, int32_t))(void *) objc_msgSend)((id)model, meta->_setter, (int32_t)num.intValue); } case YYEncodingTypeUInt32: { ((void (*)(id, SEL, uint32_t))(void *) objc_msgSend)((id)model, meta->_setter, (uint32_t)num.unsignedIntValue); } break; case YYEncodingTypeInt64: { if ([num isKindOfClass:[NSDecimalNumber class]]) { ((void (*)(id, SEL, int64_t))(void *) objc_msgSend)((id)model, meta->_setter, (int64_t)num.stringValue.longLongValue); } else { ((void (*)(id, SEL, uint64_t))(void *) objc_msgSend)((id)model, meta->_setter, (uint64_t)num.longLongValue); } } break; case YYEncodingTypeUInt64: { if ([num isKindOfClass:[NSDecimalNumber class]]) { ((void (*)(id, SEL, int64_t))(void *) objc_msgSend)((id)model, meta->_setter, (int64_t)num.stringValue.longLongValue); } else { ((void (*)(id, SEL, uint64_t))(void *) objc_msgSend)((id)model, meta->_setter, (uint64_t)num.unsignedLongLongValue); } } break; case YYEncodingTypeFloat: { float f = num.floatValue; if (isnan(f) || isinf(f)) f = 0; ((void (*)(id, SEL, float))(void *) objc_msgSend)((id)model, meta->_setter, f); } break; case YYEncodingTypeDouble: { double d = num.doubleValue; if (isnan(d) || isinf(d)) d = 0; ((void (*)(id, SEL, double))(void *) objc_msgSend)((id)model, meta->_setter, d); } break; case YYEncodingTypeLongDouble: { long double d = num.doubleValue; if (isnan(d) || isinf(d)) d = 0; ((void (*)(id, SEL, long double))(void *) objc_msgSend)((id)model, meta->_setter, (long double)d); } // break; commented for code coverage in next line default: break; } } /** Set value to model with a property meta. @discussion Caller should hold strong reference to the parameters before this function returns. @param model Should not be nil. @param value Should not be nil, but can be NSNull. @param meta Should not be nil, and meta->_setter should not be nil. */ static void ModelSetValueForProperty(__unsafe_unretained id model, __unsafe_unretained id value, __unsafe_unretained _YYModelPropertyMeta *meta) { if (meta->_isCNumber) { NSNumber *num = YYNSNumberCreateFromID(value); ModelSetNumberToProperty(model, num, meta); if (num != nil) [num class]; // hold the number } else if (meta->_nsType) { if (value == (id)kCFNull) { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, (id)nil); } else { switch (meta->_nsType) { case YYEncodingTypeNSString: case YYEncodingTypeNSMutableString: { if ([value isKindOfClass:[NSString class]]) { if (meta->_nsType == YYEncodingTypeNSString) { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, value); } else { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, ((NSString *)value).mutableCopy); } } else if ([value isKindOfClass:[NSNumber class]]) { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, (meta->_nsType == YYEncodingTypeNSString) ? ((NSNumber *)value).stringValue : ((NSNumber *)value).stringValue.mutableCopy); } else if ([value isKindOfClass:[NSData class]]) { NSMutableString *string = [[NSMutableString alloc] initWithData:value encoding:NSUTF8StringEncoding]; ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, string); } else if ([value isKindOfClass:[NSURL class]]) { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, (meta->_nsType == YYEncodingTypeNSString) ? ((NSURL *)value).absoluteString : ((NSURL *)value).absoluteString.mutableCopy); } else if ([value isKindOfClass:[NSAttributedString class]]) { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, (meta->_nsType == YYEncodingTypeNSString) ? ((NSAttributedString *)value).string : ((NSAttributedString *)value).string.mutableCopy); } } break; case YYEncodingTypeNSValue: case YYEncodingTypeNSNumber: case YYEncodingTypeNSDecimalNumber: { if (meta->_nsType == YYEncodingTypeNSNumber) { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, YYNSNumberCreateFromID(value)); } else if (meta->_nsType == YYEncodingTypeNSDecimalNumber) { if ([value isKindOfClass:[NSDecimalNumber class]]) { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, value); } else if ([value isKindOfClass:[NSNumber class]]) { NSDecimalNumber *decNum = [NSDecimalNumber decimalNumberWithDecimal:[((NSNumber *)value) decimalValue]]; ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, decNum); } else if ([value isKindOfClass:[NSString class]]) { NSDecimalNumber *decNum = [NSDecimalNumber decimalNumberWithString:value]; NSDecimal dec = decNum.decimalValue; if (dec._length == 0 && dec._isNegative) { decNum = nil; // NaN } ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, decNum); } } else { // YYEncodingTypeNSValue if ([value isKindOfClass:[NSValue class]]) { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, value); } } } break; case YYEncodingTypeNSData: case YYEncodingTypeNSMutableData: { if ([value isKindOfClass:[NSData class]]) { if (meta->_nsType == YYEncodingTypeNSData) { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, value); } else { NSMutableData *data = ((NSData *)value).mutableCopy; ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, data); } } else if ([value isKindOfClass:[NSString class]]) { NSData *data = [(NSString *)value dataUsingEncoding:NSUTF8StringEncoding]; if (meta->_nsType == YYEncodingTypeNSMutableData) { data = ((NSData *)data).mutableCopy; } ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, data); } } break; case YYEncodingTypeNSDate: { if ([value isKindOfClass:[NSDate class]]) { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, value); } else if ([value isKindOfClass:[NSString class]]) { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, YYNSDateFromString(value)); } } break; case YYEncodingTypeNSURL: { if ([value isKindOfClass:[NSURL class]]) { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, value); } else if ([value isKindOfClass:[NSString class]]) { NSCharacterSet *set = [NSCharacterSet whitespaceAndNewlineCharacterSet]; NSString *str = [value stringByTrimmingCharactersInSet:set]; if (str.length == 0) { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, nil); } else { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, [[NSURL alloc] initWithString:str]); } } } break; case YYEncodingTypeNSArray: case YYEncodingTypeNSMutableArray: { if (meta->_genericCls) { NSArray *valueArr = nil; if ([value isKindOfClass:[NSArray class]]) valueArr = value; else if ([value isKindOfClass:[NSSet class]]) valueArr = ((NSSet *)value).allObjects; if (valueArr) { NSMutableArray *objectArr = [NSMutableArray new]; for (id one in valueArr) { if ([one isKindOfClass:meta->_genericCls]) { [objectArr addObject:one]; } else if ([one isKindOfClass:[NSDictionary class]]) { Class cls = meta->_genericCls; if (meta->_hasCustomClassFromDictionary) { cls = [cls modelCustomClassForDictionary:one]; if (!cls) cls = meta->_genericCls; // for xcode code coverage } NSObject *newOne = [cls new]; [newOne yy_modelSetWithDictionary:one]; if (newOne) [objectArr addObject:newOne]; } } ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, objectArr); } } else { if ([value isKindOfClass:[NSArray class]]) { if (meta->_nsType == YYEncodingTypeNSArray) { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, value); } else { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, ((NSArray *)value).mutableCopy); } } else if ([value isKindOfClass:[NSSet class]]) { if (meta->_nsType == YYEncodingTypeNSArray) { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, ((NSSet *)value).allObjects); } else { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, ((NSSet *)value).allObjects.mutableCopy); } } } } break; case YYEncodingTypeNSDictionary: case YYEncodingTypeNSMutableDictionary: { if ([value isKindOfClass:[NSDictionary class]]) { if (meta->_genericCls) { NSMutableDictionary *dic = [NSMutableDictionary new]; [((NSDictionary *)value) enumerateKeysAndObjectsUsingBlock:^(NSString *oneKey, id oneValue, BOOL *stop) { if ([oneValue isKindOfClass:[NSDictionary class]]) { Class cls = meta->_genericCls; if (meta->_hasCustomClassFromDictionary) { cls = [cls modelCustomClassForDictionary:oneValue]; if (!cls) cls = meta->_genericCls; // for xcode code coverage } NSObject *newOne = [cls new]; [newOne yy_modelSetWithDictionary:(id)oneValue]; if (newOne) dic[oneKey] = newOne; } }]; ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, dic); } else { if (meta->_nsType == YYEncodingTypeNSDictionary) { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, value); } else { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, ((NSDictionary *)value).mutableCopy); } } } } break; case YYEncodingTypeNSSet: case YYEncodingTypeNSMutableSet: { NSSet *valueSet = nil; if ([value isKindOfClass:[NSArray class]]) valueSet = [NSMutableSet setWithArray:value]; else if ([value isKindOfClass:[NSSet class]]) valueSet = ((NSSet *)value); if (meta->_genericCls) { NSMutableSet *set = [NSMutableSet new]; for (id one in valueSet) { if ([one isKindOfClass:meta->_genericCls]) { [set addObject:one]; } else if ([one isKindOfClass:[NSDictionary class]]) { Class cls = meta->_genericCls; if (meta->_hasCustomClassFromDictionary) { cls = [cls modelCustomClassForDictionary:one]; if (!cls) cls = meta->_genericCls; // for xcode code coverage } NSObject *newOne = [cls new]; [newOne yy_modelSetWithDictionary:one]; if (newOne) [set addObject:newOne]; } } ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, set); } else { if (meta->_nsType == YYEncodingTypeNSSet) { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, valueSet); } else { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, ((NSSet *)valueSet).mutableCopy); } } } // break; commented for code coverage in next line default: break; } } } else { BOOL isNull = (value == (id)kCFNull); switch (meta->_type & YYEncodingTypeMask) { case YYEncodingTypeObject: { Class cls = meta->_genericCls ?: meta->_cls; if (isNull) { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, (id)nil); } else if ([value isKindOfClass:cls] || !cls) { ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, (id)value); } else if ([value isKindOfClass:[NSDictionary class]]) { NSObject *one = nil; if (meta->_getter) { one = ((id (*)(id, SEL))(void *) objc_msgSend)((id)model, meta->_getter); } if (one) { [one yy_modelSetWithDictionary:value]; } else { if (meta->_hasCustomClassFromDictionary) { cls = [cls modelCustomClassForDictionary:value] ?: cls; } one = [cls new]; [one yy_modelSetWithDictionary:value]; ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, (id)one); } } } break; case YYEncodingTypeClass: { if (isNull) { ((void (*)(id, SEL, Class))(void *) objc_msgSend)((id)model, meta->_setter, (Class)NULL); } else { Class cls = nil; if ([value isKindOfClass:[NSString class]]) { cls = NSClassFromString(value); if (cls) { ((void (*)(id, SEL, Class))(void *) objc_msgSend)((id)model, meta->_setter, (Class)cls); } } else { cls = object_getClass(value); if (cls) { if (class_isMetaClass(cls)) { ((void (*)(id, SEL, Class))(void *) objc_msgSend)((id)model, meta->_setter, (Class)value); } } } } } break; case YYEncodingTypeSEL: { if (isNull) { ((void (*)(id, SEL, SEL))(void *) objc_msgSend)((id)model, meta->_setter, (SEL)NULL); } else if ([value isKindOfClass:[NSString class]]) { SEL sel = NSSelectorFromString(value); if (sel) ((void (*)(id, SEL, SEL))(void *) objc_msgSend)((id)model, meta->_setter, (SEL)sel); } } break; case YYEncodingTypeBlock: { if (isNull) { ((void (*)(id, SEL, void (^)()))(void *) objc_msgSend)((id)model, meta->_setter, (void (^)())NULL); } else if ([value isKindOfClass:YYNSBlockClass()]) { ((void (*)(id, SEL, void (^)()))(void *) objc_msgSend)((id)model, meta->_setter, (void (^)())value); } } break; case YYEncodingTypeStruct: case YYEncodingTypeUnion: case YYEncodingTypeCArray: { if ([value isKindOfClass:[NSValue class]]) { const char *valueType = ((NSValue *)value).objCType; const char *metaType = meta->_info.typeEncoding.UTF8String; if (valueType && metaType && strcmp(valueType, metaType) == 0) { [model setValue:value forKey:meta->_name]; } } } break; case YYEncodingTypePointer: case YYEncodingTypeCString: { if (isNull) { ((void (*)(id, SEL, void *))(void *) objc_msgSend)((id)model, meta->_setter, (void *)NULL); } else if ([value isKindOfClass:[NSValue class]]) { NSValue *nsValue = value; if (nsValue.objCType && strcmp(nsValue.objCType, "^v") == 0) { ((void (*)(id, SEL, void *))(void *) objc_msgSend)((id)model, meta->_setter, nsValue.pointerValue); } } } // break; commented for code coverage in next line default: break; } } } typedef struct { void *modelMeta; ///< _YYModelMeta void *model; ///< id (self) void *dictionary; ///< NSDictionary (json) } ModelSetContext; /** Apply function for dictionary, to set the key-value pair to model. @param _key should not be nil, NSString. @param _value should not be nil. @param _context _context.modelMeta and _context.model should not be nil. */ static void ModelSetWithDictionaryFunction(const void *_key, const void *_value, void *_context) { ModelSetContext *context = _context; __unsafe_unretained _YYModelMeta *meta = (__bridge _YYModelMeta *)(context->modelMeta); __unsafe_unretained _YYModelPropertyMeta *propertyMeta = [meta->_mapper objectForKey:(__bridge id)(_key)]; __unsafe_unretained id model = (__bridge id)(context->model); while (propertyMeta) { if (propertyMeta->_setter) { ModelSetValueForProperty(model, (__bridge __unsafe_unretained id)_value, propertyMeta); } propertyMeta = propertyMeta->_next; }; } /** Apply function for model property meta, to set dictionary to model. @param _propertyMeta should not be nil, _YYModelPropertyMeta. @param _context _context.model and _context.dictionary should not be nil. */ static void ModelSetWithPropertyMetaArrayFunction(const void *_propertyMeta, void *_context) { ModelSetContext *context = _context; __unsafe_unretained NSDictionary *dictionary = (__bridge NSDictionary *)(context->dictionary); __unsafe_unretained _YYModelPropertyMeta *propertyMeta = (__bridge _YYModelPropertyMeta *)(_propertyMeta); if (!propertyMeta->_setter) return; id value = nil; if (propertyMeta->_mappedToKeyArray) { value = YYValueForMultiKeys(dictionary, propertyMeta->_mappedToKeyArray); } else if (propertyMeta->_mappedToKeyPath) { value = YYValueForKeyPath(dictionary, propertyMeta->_mappedToKeyPath); } else { value = [dictionary objectForKey:propertyMeta->_mappedToKey]; } if (value) { __unsafe_unretained id model = (__bridge id)(context->model); ModelSetValueForProperty(model, value, propertyMeta); } } /** Returns a valid JSON object (NSArray/NSDictionary/NSString/NSNumber/NSNull), or nil if an error occurs. @param model Model, can be nil. @return JSON object, nil if an error occurs. */ static id ModelToJSONObjectRecursive(NSObject *model) { if (!model || model == (id)kCFNull) return model; if ([model isKindOfClass:[NSString class]]) return model; if ([model isKindOfClass:[NSNumber class]]) return model; if ([model isKindOfClass:[NSDictionary class]]) { if ([NSJSONSerialization isValidJSONObject:model]) return model; NSMutableDictionary *newDic = [NSMutableDictionary new]; [((NSDictionary *)model) enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) { NSString *stringKey = [key isKindOfClass:[NSString class]] ? key : key.description; if (!stringKey) return; id jsonObj = ModelToJSONObjectRecursive(obj); if (!jsonObj) jsonObj = (id)kCFNull; newDic[stringKey] = jsonObj; }]; return newDic; } if ([model isKindOfClass:[NSSet class]]) { NSArray *array = ((NSSet *)model).allObjects; if ([NSJSONSerialization isValidJSONObject:array]) return array; NSMutableArray *newArray = [NSMutableArray new]; for (id obj in array) { if ([obj isKindOfClass:[NSString class]] || [obj isKindOfClass:[NSNumber class]]) { [newArray addObject:obj]; } else { id jsonObj = ModelToJSONObjectRecursive(obj); if (jsonObj && jsonObj != (id)kCFNull) [newArray addObject:jsonObj]; } } return newArray; } if ([model isKindOfClass:[NSArray class]]) { if ([NSJSONSerialization isValidJSONObject:model]) return model; NSMutableArray *newArray = [NSMutableArray new]; for (id obj in (NSArray *)model) { if ([obj isKindOfClass:[NSString class]] || [obj isKindOfClass:[NSNumber class]]) { [newArray addObject:obj]; } else { id jsonObj = ModelToJSONObjectRecursive(obj); if (jsonObj && jsonObj != (id)kCFNull) [newArray addObject:jsonObj]; } } return newArray; } if ([model isKindOfClass:[NSURL class]]) return ((NSURL *)model).absoluteString; if ([model isKindOfClass:[NSAttributedString class]]) return ((NSAttributedString *)model).string; if ([model isKindOfClass:[NSDate class]]) return [YYISODateFormatter() stringFromDate:(id)model]; if ([model isKindOfClass:[NSData class]]) return nil; _YYModelMeta *modelMeta = [_YYModelMeta metaWithClass:[model class]]; if (!modelMeta || modelMeta->_keyMappedCount == 0) return nil; NSMutableDictionary *result = [[NSMutableDictionary alloc] initWithCapacity:64]; __unsafe_unretained NSMutableDictionary *dic = result; // avoid retain and release in block [modelMeta->_mapper enumerateKeysAndObjectsUsingBlock:^(NSString *propertyMappedKey, _YYModelPropertyMeta *propertyMeta, BOOL *stop) { if (!propertyMeta->_getter) return; id value = nil; if (propertyMeta->_isCNumber) { value = ModelCreateNumberFromProperty(model, propertyMeta); } else if (propertyMeta->_nsType) { id v = ((id (*)(id, SEL))(void *) objc_msgSend)((id)model, propertyMeta->_getter); value = ModelToJSONObjectRecursive(v); } else { switch (propertyMeta->_type & YYEncodingTypeMask) { case YYEncodingTypeObject: { id v = ((id (*)(id, SEL))(void *) objc_msgSend)((id)model, propertyMeta->_getter); value = ModelToJSONObjectRecursive(v); if (value == (id)kCFNull) value = nil; } break; case YYEncodingTypeClass: { Class v = ((Class (*)(id, SEL))(void *) objc_msgSend)((id)model, propertyMeta->_getter); value = v ? NSStringFromClass(v) : nil; } break; case YYEncodingTypeSEL: { SEL v = ((SEL (*)(id, SEL))(void *) objc_msgSend)((id)model, propertyMeta->_getter); value = v ? NSStringFromSelector(v) : nil; } break; default: break; } } if (!value) return; if (propertyMeta->_mappedToKeyPath) { NSMutableDictionary *superDic = dic; NSMutableDictionary *subDic = nil; for (NSUInteger i = 0, max = propertyMeta->_mappedToKeyPath.count; i < max; i++) { NSString *key = propertyMeta->_mappedToKeyPath[i]; if (i + 1 == max) { // end if (!superDic[key]) superDic[key] = value; break; } subDic = superDic[key]; if (subDic) { if ([subDic isKindOfClass:[NSDictionary class]]) { subDic = subDic.mutableCopy; superDic[key] = subDic; } else { break; } } else { subDic = [NSMutableDictionary new]; superDic[key] = subDic; } superDic = subDic; subDic = nil; } } else { if (!dic[propertyMeta->_mappedToKey]) { dic[propertyMeta->_mappedToKey] = value; } } }]; if (modelMeta->_hasCustomTransformToDictionary) { BOOL suc = [((id<YYModel>)model) modelCustomTransformToDictionary:dic]; if (!suc) return nil; } return result; } /// Add indent to string (exclude first line) static NSMutableString *ModelDescriptionAddIndent(NSMutableString *desc, NSUInteger indent) { for (NSUInteger i = 0, max = desc.length; i < max; i++) { unichar c = [desc characterAtIndex:i]; if (c == '\n') { for (NSUInteger j = 0; j < indent; j++) { [desc insertString:@" " atIndex:i + 1]; } i += indent * 4; max += indent * 4; } } return desc; } /// Generate a description string static NSString *ModelDescription(NSObject *model) { static const int kDescMaxLength = 100; if (!model) return @"<nil>"; if (model == (id)kCFNull) return @"<null>"; if (![model isKindOfClass:[NSObject class]]) return [NSString stringWithFormat:@"%@",model]; _YYModelMeta *modelMeta = [_YYModelMeta metaWithClass:model.class]; switch (modelMeta->_nsType) { case YYEncodingTypeNSString: case YYEncodingTypeNSMutableString: { return [NSString stringWithFormat:@"\"%@\"",model]; } case YYEncodingTypeNSValue: case YYEncodingTypeNSData: case YYEncodingTypeNSMutableData: { NSString *tmp = model.description; if (tmp.length > kDescMaxLength) { tmp = [tmp substringToIndex:kDescMaxLength]; tmp = [tmp stringByAppendingString:@"..."]; } return tmp; } case YYEncodingTypeNSNumber: case YYEncodingTypeNSDecimalNumber: case YYEncodingTypeNSDate: case YYEncodingTypeNSURL: { return [NSString stringWithFormat:@"%@",model]; } case YYEncodingTypeNSSet: case YYEncodingTypeNSMutableSet: { model = ((NSSet *)model).allObjects; } // no break case YYEncodingTypeNSArray: case YYEncodingTypeNSMutableArray: { NSArray *array = (id)model; NSMutableString *desc = [NSMutableString new]; if (array.count == 0) { return [desc stringByAppendingString:@"[]"]; } else { [desc appendFormat:@"[\n"]; for (NSUInteger i = 0, max = array.count; i < max; i++) { NSObject *obj = array[i]; [desc appendString:@" "]; [desc appendString:ModelDescriptionAddIndent(ModelDescription(obj).mutableCopy, 1)]; [desc appendString:(i + 1 == max) ? @"\n" : @";\n"]; } [desc appendString:@"]"]; return desc; } } case YYEncodingTypeNSDictionary: case YYEncodingTypeNSMutableDictionary: { NSDictionary *dic = (id)model; NSMutableString *desc = [NSMutableString new]; if (dic.count == 0) { return [desc stringByAppendingString:@"{}"]; } else { NSArray *keys = dic.allKeys; [desc appendFormat:@"{\n"]; for (NSUInteger i = 0, max = keys.count; i < max; i++) { NSString *key = keys[i]; NSObject *value = dic[key]; [desc appendString:@" "]; [desc appendFormat:@"%@ = %@",key, ModelDescriptionAddIndent(ModelDescription(value).mutableCopy, 1)]; [desc appendString:(i + 1 == max) ? @"\n" : @";\n"]; } [desc appendString:@"}"]; } return desc; } default: { NSMutableString *desc = [NSMutableString new]; [desc appendFormat:@"<%@: %p>", model.class, model]; if (modelMeta->_allPropertyMetas.count == 0) return desc; // sort property names NSArray *properties = [modelMeta->_allPropertyMetas sortedArrayUsingComparator:^NSComparisonResult(_YYModelPropertyMeta *p1, _YYModelPropertyMeta *p2) { return [p1->_name compare:p2->_name]; }]; [desc appendFormat:@" {\n"]; for (NSUInteger i = 0, max = properties.count; i < max; i++) { _YYModelPropertyMeta *property = properties[i]; NSString *propertyDesc; if (property->_isCNumber) { NSNumber *num = ModelCreateNumberFromProperty(model, property); propertyDesc = num.stringValue; } else { switch (property->_type & YYEncodingTypeMask) { case YYEncodingTypeObject: { id v = ((id (*)(id, SEL))(void *) objc_msgSend)((id)model, property->_getter); propertyDesc = ModelDescription(v); if (!propertyDesc) propertyDesc = @"<nil>"; } break; case YYEncodingTypeClass: { id v = ((id (*)(id, SEL))(void *) objc_msgSend)((id)model, property->_getter); propertyDesc = ((NSObject *)v).description; if (!propertyDesc) propertyDesc = @"<nil>"; } break; case YYEncodingTypeSEL: { SEL sel = ((SEL (*)(id, SEL))(void *) objc_msgSend)((id)model, property->_getter); if (sel) propertyDesc = NSStringFromSelector(sel); else propertyDesc = @"<NULL>"; } break; case YYEncodingTypeBlock: { id block = ((id (*)(id, SEL))(void *) objc_msgSend)((id)model, property->_getter); propertyDesc = block ? ((NSObject *)block).description : @"<nil>"; } break; case YYEncodingTypeCArray: case YYEncodingTypeCString: case YYEncodingTypePointer: { void *pointer = ((void* (*)(id, SEL))(void *) objc_msgSend)((id)model, property->_getter); propertyDesc = [NSString stringWithFormat:@"%p",pointer]; } break; case YYEncodingTypeStruct: case YYEncodingTypeUnion: { NSValue *value = [model valueForKey:property->_name]; propertyDesc = value ? value.description : @"{unknown}"; } break; default: propertyDesc = @"<unknown>"; } } propertyDesc = ModelDescriptionAddIndent(propertyDesc.mutableCopy, 1); [desc appendFormat:@" %@ = %@",property->_name, propertyDesc]; [desc appendString:(i + 1 == max) ? @"\n" : @";\n"]; } [desc appendFormat:@"}"]; return desc; } } } @implementation NSObject (YYModel) + (NSDictionary *)_yy_dictionaryWithJSON:(id)json { if (!json || json == (id)kCFNull) return nil; NSDictionary *dic = nil; NSData *jsonData = nil; if ([json isKindOfClass:[NSDictionary class]]) { dic = json; } else if ([json isKindOfClass:[NSString class]]) { jsonData = [(NSString *)json dataUsingEncoding : NSUTF8StringEncoding]; } else if ([json isKindOfClass:[NSData class]]) { jsonData = json; } if (jsonData) { dic = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:NULL]; if (![dic isKindOfClass:[NSDictionary class]]) dic = nil; } return dic; } + (instancetype)yy_modelWithJSON:(id)json { NSDictionary *dic = [self _yy_dictionaryWithJSON:json]; return [self yy_modelWithDictionary:dic]; } + (instancetype)yy_modelWithDictionary:(NSDictionary *)dictionary { if (!dictionary || dictionary == (id)kCFNull) return nil; if (![dictionary isKindOfClass:[NSDictionary class]]) return nil; Class cls = [self class]; _YYModelMeta *modelMeta = [_YYModelMeta metaWithClass:cls]; if (modelMeta->_hasCustomClassFromDictionary) { cls = [cls modelCustomClassForDictionary:dictionary] ?: cls; } NSObject *one = [cls new]; if ([one yy_modelSetWithDictionary:dictionary]) return one; return nil; } - (BOOL)yy_modelSetWithJSON:(id)json { NSDictionary *dic = [NSObject _yy_dictionaryWithJSON:json]; return [self yy_modelSetWithDictionary:dic]; } - (BOOL)yy_modelSetWithDictionary:(NSDictionary *)dic { if (!dic || dic == (id)kCFNull) return NO; if (![dic isKindOfClass:[NSDictionary class]]) return NO; _YYModelMeta *modelMeta = [_YYModelMeta metaWithClass:object_getClass(self)]; if (modelMeta->_keyMappedCount == 0) return NO; if (modelMeta->_hasCustomWillTransformFromDictionary) { dic = [((id<YYModel>)self) modelCustomWillTransformFromDictionary:dic]; if (![dic isKindOfClass:[NSDictionary class]]) return NO; } ModelSetContext context = {0}; context.modelMeta = (__bridge void *)(modelMeta); context.model = (__bridge void *)(self); context.dictionary = (__bridge void *)(dic); if (modelMeta->_keyMappedCount >= CFDictionaryGetCount((CFDictionaryRef)dic)) { CFDictionaryApplyFunction((CFDictionaryRef)dic, ModelSetWithDictionaryFunction, &context); if (modelMeta->_keyPathPropertyMetas) { CFArrayApplyFunction((CFArrayRef)modelMeta->_keyPathPropertyMetas, CFRangeMake(0, CFArrayGetCount((CFArrayRef)modelMeta->_keyPathPropertyMetas)), ModelSetWithPropertyMetaArrayFunction, &context); } if (modelMeta->_multiKeysPropertyMetas) { CFArrayApplyFunction((CFArrayRef)modelMeta->_multiKeysPropertyMetas, CFRangeMake(0, CFArrayGetCount((CFArrayRef)modelMeta->_multiKeysPropertyMetas)), ModelSetWithPropertyMetaArrayFunction, &context); } } else { CFArrayApplyFunction((CFArrayRef)modelMeta->_allPropertyMetas, CFRangeMake(0, modelMeta->_keyMappedCount), ModelSetWithPropertyMetaArrayFunction, &context); } if (modelMeta->_hasCustomTransformFromDictionary) { return [((id<YYModel>)self) modelCustomTransformFromDictionary:dic]; } return YES; } - (id)yy_modelToJSONObject { /* Apple said: The top level object is an NSArray or NSDictionary. All objects are instances of NSString, NSNumber, NSArray, NSDictionary, or NSNull. All dictionary keys are instances of NSString. Numbers are not NaN or infinity. */ id jsonObject = ModelToJSONObjectRecursive(self); if ([jsonObject isKindOfClass:[NSArray class]]) return jsonObject; if ([jsonObject isKindOfClass:[NSDictionary class]]) return jsonObject; return nil; } - (NSData *)yy_modelToJSONData { id jsonObject = [self yy_modelToJSONObject]; if (!jsonObject) return nil; return [NSJSONSerialization dataWithJSONObject:jsonObject options:0 error:NULL]; } - (NSString *)yy_modelToJSONString { NSData *jsonData = [self yy_modelToJSONData]; if (jsonData.length == 0) return nil; return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; } - (id)yy_modelCopy{ if (self == (id)kCFNull) return self; _YYModelMeta *modelMeta = [_YYModelMeta metaWithClass:self.class]; if (modelMeta->_nsType) return [self copy]; NSObject *one = [self.class new]; for (_YYModelPropertyMeta *propertyMeta in modelMeta->_allPropertyMetas) { if (!propertyMeta->_getter || !propertyMeta->_setter) continue; if (propertyMeta->_isCNumber) { switch (propertyMeta->_type & YYEncodingTypeMask) { case YYEncodingTypeBool: { bool num = ((bool (*)(id, SEL))(void *) objc_msgSend)((id)self, propertyMeta->_getter); ((void (*)(id, SEL, bool))(void *) objc_msgSend)((id)one, propertyMeta->_setter, num); } break; case YYEncodingTypeInt8: case YYEncodingTypeUInt8: { uint8_t num = ((bool (*)(id, SEL))(void *) objc_msgSend)((id)self, propertyMeta->_getter); ((void (*)(id, SEL, uint8_t))(void *) objc_msgSend)((id)one, propertyMeta->_setter, num); } break; case YYEncodingTypeInt16: case YYEncodingTypeUInt16: { uint16_t num = ((uint16_t (*)(id, SEL))(void *) objc_msgSend)((id)self, propertyMeta->_getter); ((void (*)(id, SEL, uint16_t))(void *) objc_msgSend)((id)one, propertyMeta->_setter, num); } break; case YYEncodingTypeInt32: case YYEncodingTypeUInt32: { uint32_t num = ((uint32_t (*)(id, SEL))(void *) objc_msgSend)((id)self, propertyMeta->_getter); ((void (*)(id, SEL, uint32_t))(void *) objc_msgSend)((id)one, propertyMeta->_setter, num); } break; case YYEncodingTypeInt64: case YYEncodingTypeUInt64: { uint64_t num = ((uint64_t (*)(id, SEL))(void *) objc_msgSend)((id)self, propertyMeta->_getter); ((void (*)(id, SEL, uint64_t))(void *) objc_msgSend)((id)one, propertyMeta->_setter, num); } break; case YYEncodingTypeFloat: { float num = ((float (*)(id, SEL))(void *) objc_msgSend)((id)self, propertyMeta->_getter); ((void (*)(id, SEL, float))(void *) objc_msgSend)((id)one, propertyMeta->_setter, num); } break; case YYEncodingTypeDouble: { double num = ((double (*)(id, SEL))(void *) objc_msgSend)((id)self, propertyMeta->_getter); ((void (*)(id, SEL, double))(void *) objc_msgSend)((id)one, propertyMeta->_setter, num); } break; case YYEncodingTypeLongDouble: { long double num = ((long double (*)(id, SEL))(void *) objc_msgSend)((id)self, propertyMeta->_getter); ((void (*)(id, SEL, long double))(void *) objc_msgSend)((id)one, propertyMeta->_setter, num); } // break; commented for code coverage in next line default: break; } } else { switch (propertyMeta->_type & YYEncodingTypeMask) { case YYEncodingTypeObject: case YYEncodingTypeClass: case YYEncodingTypeBlock: { id value = ((id (*)(id, SEL))(void *) objc_msgSend)((id)self, propertyMeta->_getter); ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)one, propertyMeta->_setter, value); } break; case YYEncodingTypeSEL: case YYEncodingTypePointer: case YYEncodingTypeCString: { size_t value = ((size_t (*)(id, SEL))(void *) objc_msgSend)((id)self, propertyMeta->_getter); ((void (*)(id, SEL, size_t))(void *) objc_msgSend)((id)one, propertyMeta->_setter, value); } break; case YYEncodingTypeStruct: case YYEncodingTypeUnion: { @try { NSValue *value = [self valueForKey:NSStringFromSelector(propertyMeta->_getter)]; if (value) { [one setValue:value forKey:propertyMeta->_name]; } } @catch (NSException *exception) {} } // break; commented for code coverage in next line default: break; } } } return one; } - (void)yy_modelEncodeWithCoder:(NSCoder *)aCoder { if (!aCoder) return; if (self == (id)kCFNull) { [((id<NSCoding>)self)encodeWithCoder:aCoder]; return; } _YYModelMeta *modelMeta = [_YYModelMeta metaWithClass:self.class]; if (modelMeta->_nsType) { [((id<NSCoding>)self)encodeWithCoder:aCoder]; return; } for (_YYModelPropertyMeta *propertyMeta in modelMeta->_allPropertyMetas) { if (!propertyMeta->_getter) return; if (propertyMeta->_isCNumber) { NSNumber *value = ModelCreateNumberFromProperty(self, propertyMeta); if (value != nil) [aCoder encodeObject:value forKey:propertyMeta->_name]; } else { switch (propertyMeta->_type & YYEncodingTypeMask) { case YYEncodingTypeObject: { id value = ((id (*)(id, SEL))(void *)objc_msgSend)((id)self, propertyMeta->_getter); if (value && (propertyMeta->_nsType || [value respondsToSelector:@selector(encodeWithCoder:)])) { if ([value isKindOfClass:[NSValue class]]) { if ([value isKindOfClass:[NSNumber class]]) { [aCoder encodeObject:value forKey:propertyMeta->_name]; } } else { [aCoder encodeObject:value forKey:propertyMeta->_name]; } } } break; case YYEncodingTypeSEL: { SEL value = ((SEL (*)(id, SEL))(void *)objc_msgSend)((id)self, propertyMeta->_getter); if (value) { NSString *str = NSStringFromSelector(value); [aCoder encodeObject:str forKey:propertyMeta->_name]; } } break; case YYEncodingTypeStruct: case YYEncodingTypeUnion: { if (propertyMeta->_isKVCCompatible && propertyMeta->_isStructAvailableForKeyedArchiver) { @try { NSValue *value = [self valueForKey:NSStringFromSelector(propertyMeta->_getter)]; [aCoder encodeObject:value forKey:propertyMeta->_name]; } @catch (NSException *exception) {} } } break; default: break; } } } } - (id)yy_modelInitWithCoder:(NSCoder *)aDecoder { if (!aDecoder) return self; if (self == (id)kCFNull) return self; _YYModelMeta *modelMeta = [_YYModelMeta metaWithClass:self.class]; if (modelMeta->_nsType) return self; for (_YYModelPropertyMeta *propertyMeta in modelMeta->_allPropertyMetas) { if (!propertyMeta->_setter) continue; if (propertyMeta->_isCNumber) { NSNumber *value = [aDecoder decodeObjectForKey:propertyMeta->_name]; if ([value isKindOfClass:[NSNumber class]]) { ModelSetNumberToProperty(self, value, propertyMeta); [value class]; } } else { YYEncodingType type = propertyMeta->_type & YYEncodingTypeMask; switch (type) { case YYEncodingTypeObject: { id value = [aDecoder decodeObjectForKey:propertyMeta->_name]; ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)self, propertyMeta->_setter, value); } break; case YYEncodingTypeSEL: { NSString *str = [aDecoder decodeObjectForKey:propertyMeta->_name]; if ([str isKindOfClass:[NSString class]]) { SEL sel = NSSelectorFromString(str); ((void (*)(id, SEL, SEL))(void *) objc_msgSend)((id)self, propertyMeta->_setter, sel); } } break; case YYEncodingTypeStruct: case YYEncodingTypeUnion: { if (propertyMeta->_isKVCCompatible) { @try { NSValue *value = [aDecoder decodeObjectForKey:propertyMeta->_name]; if (value) [self setValue:value forKey:propertyMeta->_name]; } @catch (NSException *exception) {} } } break; default: break; } } } return self; } - (NSUInteger)yy_modelHash { if (self == (id)kCFNull) return [self hash]; _YYModelMeta *modelMeta = [_YYModelMeta metaWithClass:self.class]; if (modelMeta->_nsType) return [self hash]; NSUInteger value = 0; NSUInteger count = 0; for (_YYModelPropertyMeta *propertyMeta in modelMeta->_allPropertyMetas) { if (!propertyMeta->_isKVCCompatible) continue; value ^= [[self valueForKey:NSStringFromSelector(propertyMeta->_getter)] hash]; count++; } if (count == 0) value = (long)((__bridge void *)self); return value; } - (BOOL)yy_modelIsEqual:(id)model { if (self == model) return YES; if (![model isMemberOfClass:self.class]) return NO; _YYModelMeta *modelMeta = [_YYModelMeta metaWithClass:self.class]; if (modelMeta->_nsType) return [self isEqual:model]; if ([self hash] != [model hash]) return NO; for (_YYModelPropertyMeta *propertyMeta in modelMeta->_allPropertyMetas) { if (!propertyMeta->_isKVCCompatible) continue; id this = [self valueForKey:NSStringFromSelector(propertyMeta->_getter)]; id that = [model valueForKey:NSStringFromSelector(propertyMeta->_getter)]; if (this == that) continue; if (this == nil || that == nil) return NO; if (![this isEqual:that]) return NO; } return YES; } - (NSString *)yy_modelDescription { return ModelDescription(self); } @end @implementation NSArray (YYModel) + (NSArray *)yy_modelArrayWithClass:(Class)cls json:(id)json { if (!json) return nil; NSArray *arr = nil; NSData *jsonData = nil; if ([json isKindOfClass:[NSArray class]]) { arr = json; } else if ([json isKindOfClass:[NSString class]]) { jsonData = [(NSString *)json dataUsingEncoding : NSUTF8StringEncoding]; } else if ([json isKindOfClass:[NSData class]]) { jsonData = json; } if (jsonData) { arr = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:NULL]; if (![arr isKindOfClass:[NSArray class]]) arr = nil; } return [self yy_modelArrayWithClass:cls array:arr]; } + (NSArray *)yy_modelArrayWithClass:(Class)cls array:(NSArray *)arr { if (!cls || !arr) return nil; NSMutableArray *result = [NSMutableArray new]; for (NSDictionary *dic in arr) { if (![dic isKindOfClass:[NSDictionary class]]) continue; NSObject *obj = [cls yy_modelWithDictionary:dic]; if (obj) [result addObject:obj]; } return result; } @end @implementation NSDictionary (YYModel) + (NSDictionary *)yy_modelDictionaryWithClass:(Class)cls json:(id)json { if (!json) return nil; NSDictionary *dic = nil; NSData *jsonData = nil; if ([json isKindOfClass:[NSDictionary class]]) { dic = json; } else if ([json isKindOfClass:[NSString class]]) { jsonData = [(NSString *)json dataUsingEncoding : NSUTF8StringEncoding]; } else if ([json isKindOfClass:[NSData class]]) { jsonData = json; } if (jsonData) { dic = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:NULL]; if (![dic isKindOfClass:[NSDictionary class]]) dic = nil; } return [self yy_modelDictionaryWithClass:cls dictionary:dic]; } + (NSDictionary *)yy_modelDictionaryWithClass:(Class)cls dictionary:(NSDictionary *)dic { if (!cls || !dic) return nil; NSMutableDictionary *result = [NSMutableDictionary new]; for (NSString *key in dic.allKeys) { if (![key isKindOfClass:[NSString class]]) continue; NSObject *obj = [cls yy_modelWithDictionary:dic[key]]; if (obj) result[key] = obj; } return result; } @end EZSDK/EZSDK/EZ/Venders/YYModel/YYClassInfo.h
New file @@ -0,0 +1,200 @@ // // YYClassInfo.h // YYModel <https://github.com/ibireme/YYModel> // // Created by ibireme on 15/5/9. // Copyright (c) 2015 ibireme. // // This source code is licensed under the MIT-style license found in the // LICENSE file in the root directory of this source tree. // #import <Foundation/Foundation.h> #import <objc/runtime.h> NS_ASSUME_NONNULL_BEGIN /** Type encoding's type. */ typedef NS_OPTIONS(NSUInteger, YYEncodingType) { YYEncodingTypeMask = 0xFF, ///< mask of type value YYEncodingTypeUnknown = 0, ///< unknown YYEncodingTypeVoid = 1, ///< void YYEncodingTypeBool = 2, ///< bool YYEncodingTypeInt8 = 3, ///< char / BOOL YYEncodingTypeUInt8 = 4, ///< unsigned char YYEncodingTypeInt16 = 5, ///< short YYEncodingTypeUInt16 = 6, ///< unsigned short YYEncodingTypeInt32 = 7, ///< int YYEncodingTypeUInt32 = 8, ///< unsigned int YYEncodingTypeInt64 = 9, ///< long long YYEncodingTypeUInt64 = 10, ///< unsigned long long YYEncodingTypeFloat = 11, ///< float YYEncodingTypeDouble = 12, ///< double YYEncodingTypeLongDouble = 13, ///< long double YYEncodingTypeObject = 14, ///< id YYEncodingTypeClass = 15, ///< Class YYEncodingTypeSEL = 16, ///< SEL YYEncodingTypeBlock = 17, ///< block YYEncodingTypePointer = 18, ///< void* YYEncodingTypeStruct = 19, ///< struct YYEncodingTypeUnion = 20, ///< union YYEncodingTypeCString = 21, ///< char* YYEncodingTypeCArray = 22, ///< char[10] (for example) YYEncodingTypeQualifierMask = 0xFF00, ///< mask of qualifier YYEncodingTypeQualifierConst = 1 << 8, ///< const YYEncodingTypeQualifierIn = 1 << 9, ///< in YYEncodingTypeQualifierInout = 1 << 10, ///< inout YYEncodingTypeQualifierOut = 1 << 11, ///< out YYEncodingTypeQualifierBycopy = 1 << 12, ///< bycopy YYEncodingTypeQualifierByref = 1 << 13, ///< byref YYEncodingTypeQualifierOneway = 1 << 14, ///< oneway YYEncodingTypePropertyMask = 0xFF0000, ///< mask of property YYEncodingTypePropertyReadonly = 1 << 16, ///< readonly YYEncodingTypePropertyCopy = 1 << 17, ///< copy YYEncodingTypePropertyRetain = 1 << 18, ///< retain YYEncodingTypePropertyNonatomic = 1 << 19, ///< nonatomic YYEncodingTypePropertyWeak = 1 << 20, ///< weak YYEncodingTypePropertyCustomGetter = 1 << 21, ///< getter= YYEncodingTypePropertyCustomSetter = 1 << 22, ///< setter= YYEncodingTypePropertyDynamic = 1 << 23, ///< @dynamic }; /** Get the type from a Type-Encoding string. @discussion See also: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html @param typeEncoding A Type-Encoding string. @return The encoding type. */ YYEncodingType YYEncodingGetType(const char *typeEncoding); /** Instance variable information. */ @interface YYClassIvarInfo : NSObject @property (nonatomic, assign, readonly) Ivar ivar; ///< ivar opaque struct @property (nonatomic, strong, readonly) NSString *name; ///< Ivar's name @property (nonatomic, assign, readonly) ptrdiff_t offset; ///< Ivar's offset @property (nonatomic, strong, readonly) NSString *typeEncoding; ///< Ivar's type encoding @property (nonatomic, assign, readonly) YYEncodingType type; ///< Ivar's type /** Creates and returns an ivar info object. @param ivar ivar opaque struct @return A new object, or nil if an error occurs. */ - (instancetype)initWithIvar:(Ivar)ivar; @end /** Method information. */ @interface YYClassMethodInfo : NSObject @property (nonatomic, assign, readonly) Method method; ///< method opaque struct @property (nonatomic, strong, readonly) NSString *name; ///< method name @property (nonatomic, assign, readonly) SEL sel; ///< method's selector @property (nonatomic, assign, readonly) IMP imp; ///< method's implementation @property (nonatomic, strong, readonly) NSString *typeEncoding; ///< method's parameter and return types @property (nonatomic, strong, readonly) NSString *returnTypeEncoding; ///< return value's type @property (nullable, nonatomic, strong, readonly) NSArray<NSString *> *argumentTypeEncodings; ///< array of arguments' type /** Creates and returns a method info object. @param method method opaque struct @return A new object, or nil if an error occurs. */ - (instancetype)initWithMethod:(Method)method; @end /** Property information. */ @interface YYClassPropertyInfo : NSObject @property (nonatomic, assign, readonly) objc_property_t property; ///< property's opaque struct @property (nonatomic, strong, readonly) NSString *name; ///< property's name @property (nonatomic, assign, readonly) YYEncodingType type; ///< property's type @property (nonatomic, strong, readonly) NSString *typeEncoding; ///< property's encoding value @property (nonatomic, strong, readonly) NSString *ivarName; ///< property's ivar name @property (nullable, nonatomic, assign, readonly) Class cls; ///< may be nil @property (nullable, nonatomic, strong, readonly) NSArray<NSString *> *protocols; ///< may nil @property (nonatomic, assign, readonly) SEL getter; ///< getter (nonnull) @property (nonatomic, assign, readonly) SEL setter; ///< setter (nonnull) /** Creates and returns a property info object. @param property property opaque struct @return A new object, or nil if an error occurs. */ - (instancetype)initWithProperty:(objc_property_t)property; @end /** Class information for a class. */ @interface YYClassInfo : NSObject @property (nonatomic, assign, readonly) Class cls; ///< class object @property (nullable, nonatomic, assign, readonly) Class superCls; ///< super class object @property (nullable, nonatomic, assign, readonly) Class metaCls; ///< class's meta class object @property (nonatomic, readonly) BOOL isMeta; ///< whether this class is meta class @property (nonatomic, strong, readonly) NSString *name; ///< class name @property (nullable, nonatomic, strong, readonly) YYClassInfo *superClassInfo; ///< super class's class info @property (nullable, nonatomic, strong, readonly) NSDictionary<NSString *, YYClassIvarInfo *> *ivarInfos; ///< ivars @property (nullable, nonatomic, strong, readonly) NSDictionary<NSString *, YYClassMethodInfo *> *methodInfos; ///< methods @property (nullable, nonatomic, strong, readonly) NSDictionary<NSString *, YYClassPropertyInfo *> *propertyInfos; ///< properties /** If the class is changed (for example: you add a method to this class with 'class_addMethod()'), you should call this method to refresh the class info cache. After called this method, `needUpdate` will returns `YES`, and you should call 'classInfoWithClass' or 'classInfoWithClassName' to get the updated class info. */ - (void)setNeedUpdate; /** If this method returns `YES`, you should stop using this instance and call `classInfoWithClass` or `classInfoWithClassName` to get the updated class info. @return Whether this class info need update. */ - (BOOL)needUpdate; /** Get the class info of a specified Class. @discussion This method will cache the class info and super-class info at the first access to the Class. This method is thread-safe. @param cls A class. @return A class info, or nil if an error occurs. */ + (nullable instancetype)classInfoWithClass:(Class)cls; /** Get the class info of a specified Class. @discussion This method will cache the class info and super-class info at the first access to the Class. This method is thread-safe. @param className A class name. @return A class info, or nil if an error occurs. */ + (nullable instancetype)classInfoWithClassName:(NSString *)className; @end NS_ASSUME_NONNULL_END EZSDK/EZSDK/EZ/Venders/YYModel/YYClassInfo.m
New file @@ -0,0 +1,362 @@ // // YYClassInfo.m // YYModel <https://github.com/ibireme/YYModel> // // Created by ibireme on 15/5/9. // Copyright (c) 2015 ibireme. // // This source code is licensed under the MIT-style license found in the // LICENSE file in the root directory of this source tree. // #import "YYClassInfo.h" #import <objc/runtime.h> YYEncodingType YYEncodingGetType(const char *typeEncoding) { char *type = (char *)typeEncoding; if (!type) return YYEncodingTypeUnknown; size_t len = strlen(type); if (len == 0) return YYEncodingTypeUnknown; YYEncodingType qualifier = 0; bool prefix = true; while (prefix) { switch (*type) { case 'r': { qualifier |= YYEncodingTypeQualifierConst; type++; } break; case 'n': { qualifier |= YYEncodingTypeQualifierIn; type++; } break; case 'N': { qualifier |= YYEncodingTypeQualifierInout; type++; } break; case 'o': { qualifier |= YYEncodingTypeQualifierOut; type++; } break; case 'O': { qualifier |= YYEncodingTypeQualifierBycopy; type++; } break; case 'R': { qualifier |= YYEncodingTypeQualifierByref; type++; } break; case 'V': { qualifier |= YYEncodingTypeQualifierOneway; type++; } break; default: { prefix = false; } break; } } len = strlen(type); if (len == 0) return YYEncodingTypeUnknown | qualifier; switch (*type) { case 'v': return YYEncodingTypeVoid | qualifier; case 'B': return YYEncodingTypeBool | qualifier; case 'c': return YYEncodingTypeInt8 | qualifier; case 'C': return YYEncodingTypeUInt8 | qualifier; case 's': return YYEncodingTypeInt16 | qualifier; case 'S': return YYEncodingTypeUInt16 | qualifier; case 'i': return YYEncodingTypeInt32 | qualifier; case 'I': return YYEncodingTypeUInt32 | qualifier; case 'l': return YYEncodingTypeInt32 | qualifier; case 'L': return YYEncodingTypeUInt32 | qualifier; case 'q': return YYEncodingTypeInt64 | qualifier; case 'Q': return YYEncodingTypeUInt64 | qualifier; case 'f': return YYEncodingTypeFloat | qualifier; case 'd': return YYEncodingTypeDouble | qualifier; case 'D': return YYEncodingTypeLongDouble | qualifier; case '#': return YYEncodingTypeClass | qualifier; case ':': return YYEncodingTypeSEL | qualifier; case '*': return YYEncodingTypeCString | qualifier; case '^': return YYEncodingTypePointer | qualifier; case '[': return YYEncodingTypeCArray | qualifier; case '(': return YYEncodingTypeUnion | qualifier; case '{': return YYEncodingTypeStruct | qualifier; case '@': { if (len == 2 && *(type + 1) == '?') return YYEncodingTypeBlock | qualifier; else return YYEncodingTypeObject | qualifier; } default: return YYEncodingTypeUnknown | qualifier; } } @implementation YYClassIvarInfo - (instancetype)initWithIvar:(Ivar)ivar { if (!ivar) return nil; self = [super init]; _ivar = ivar; const char *name = ivar_getName(ivar); if (name) { _name = [NSString stringWithUTF8String:name]; } _offset = ivar_getOffset(ivar); const char *typeEncoding = ivar_getTypeEncoding(ivar); if (typeEncoding) { _typeEncoding = [NSString stringWithUTF8String:typeEncoding]; _type = YYEncodingGetType(typeEncoding); } return self; } @end @implementation YYClassMethodInfo - (instancetype)initWithMethod:(Method)method { if (!method) return nil; self = [super init]; _method = method; _sel = method_getName(method); _imp = method_getImplementation(method); const char *name = sel_getName(_sel); if (name) { _name = [NSString stringWithUTF8String:name]; } const char *typeEncoding = method_getTypeEncoding(method); if (typeEncoding) { _typeEncoding = [NSString stringWithUTF8String:typeEncoding]; } char *returnType = method_copyReturnType(method); if (returnType) { _returnTypeEncoding = [NSString stringWithUTF8String:returnType]; free(returnType); } unsigned int argumentCount = method_getNumberOfArguments(method); if (argumentCount > 0) { NSMutableArray *argumentTypes = [NSMutableArray new]; for (unsigned int i = 0; i < argumentCount; i++) { char *argumentType = method_copyArgumentType(method, i); NSString *type = argumentType ? [NSString stringWithUTF8String:argumentType] : nil; [argumentTypes addObject:type ? type : @""]; if (argumentType) free(argumentType); } _argumentTypeEncodings = argumentTypes; } return self; } @end @implementation YYClassPropertyInfo - (instancetype)initWithProperty:(objc_property_t)property { if (!property) return nil; self = [super init]; _property = property; const char *name = property_getName(property); if (name) { _name = [NSString stringWithUTF8String:name]; } YYEncodingType type = 0; unsigned int attrCount; objc_property_attribute_t *attrs = property_copyAttributeList(property, &attrCount); for (unsigned int i = 0; i < attrCount; i++) { switch (attrs[i].name[0]) { case 'T': { // Type encoding if (attrs[i].value) { _typeEncoding = [NSString stringWithUTF8String:attrs[i].value]; type = YYEncodingGetType(attrs[i].value); if ((type & YYEncodingTypeMask) == YYEncodingTypeObject && _typeEncoding.length) { NSScanner *scanner = [NSScanner scannerWithString:_typeEncoding]; if (![scanner scanString:@"@\"" intoString:NULL]) continue; NSString *clsName = nil; if ([scanner scanUpToCharactersFromSet: [NSCharacterSet characterSetWithCharactersInString:@"\"<"] intoString:&clsName]) { if (clsName.length) _cls = objc_getClass(clsName.UTF8String); } NSMutableArray *protocols = nil; while ([scanner scanString:@"<" intoString:NULL]) { NSString* protocol = nil; if ([scanner scanUpToString:@">" intoString: &protocol]) { if (protocol.length) { if (!protocols) protocols = [NSMutableArray new]; [protocols addObject:protocol]; } } [scanner scanString:@">" intoString:NULL]; } _protocols = protocols; } } } break; case 'V': { // Instance variable if (attrs[i].value) { _ivarName = [NSString stringWithUTF8String:attrs[i].value]; } } break; case 'R': { type |= YYEncodingTypePropertyReadonly; } break; case 'C': { type |= YYEncodingTypePropertyCopy; } break; case '&': { type |= YYEncodingTypePropertyRetain; } break; case 'N': { type |= YYEncodingTypePropertyNonatomic; } break; case 'D': { type |= YYEncodingTypePropertyDynamic; } break; case 'W': { type |= YYEncodingTypePropertyWeak; } break; case 'G': { type |= YYEncodingTypePropertyCustomGetter; if (attrs[i].value) { _getter = NSSelectorFromString([NSString stringWithUTF8String:attrs[i].value]); } } break; case 'S': { type |= YYEncodingTypePropertyCustomSetter; if (attrs[i].value) { _setter = NSSelectorFromString([NSString stringWithUTF8String:attrs[i].value]); } } // break; commented for code coverage in next line default: break; } } if (attrs) { free(attrs); attrs = NULL; } _type = type; if (_name.length) { if (!_getter) { _getter = NSSelectorFromString(_name); } if (!_setter) { _setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:", [_name substringToIndex:1].uppercaseString, [_name substringFromIndex:1]]); } } return self; } @end @implementation YYClassInfo { BOOL _needUpdate; } - (instancetype)initWithClass:(Class)cls { if (!cls) return nil; self = [super init]; _cls = cls; _superCls = class_getSuperclass(cls); _isMeta = class_isMetaClass(cls); if (!_isMeta) { _metaCls = objc_getMetaClass(class_getName(cls)); } _name = NSStringFromClass(cls); [self _update]; _superClassInfo = [self.class classInfoWithClass:_superCls]; return self; } - (void)_update { _ivarInfos = nil; _methodInfos = nil; _propertyInfos = nil; Class cls = self.cls; unsigned int methodCount = 0; Method *methods = class_copyMethodList(cls, &methodCount); if (methods) { NSMutableDictionary *methodInfos = [NSMutableDictionary new]; _methodInfos = methodInfos; for (unsigned int i = 0; i < methodCount; i++) { YYClassMethodInfo *info = [[YYClassMethodInfo alloc] initWithMethod:methods[i]]; if (info.name) methodInfos[info.name] = info; } free(methods); } unsigned int propertyCount = 0; objc_property_t *properties = class_copyPropertyList(cls, &propertyCount); if (properties) { NSMutableDictionary *propertyInfos = [NSMutableDictionary new]; _propertyInfos = propertyInfos; for (unsigned int i = 0; i < propertyCount; i++) { YYClassPropertyInfo *info = [[YYClassPropertyInfo alloc] initWithProperty:properties[i]]; if (info.name) propertyInfos[info.name] = info; } free(properties); } unsigned int ivarCount = 0; Ivar *ivars = class_copyIvarList(cls, &ivarCount); if (ivars) { NSMutableDictionary *ivarInfos = [NSMutableDictionary new]; _ivarInfos = ivarInfos; for (unsigned int i = 0; i < ivarCount; i++) { YYClassIvarInfo *info = [[YYClassIvarInfo alloc] initWithIvar:ivars[i]]; if (info.name) ivarInfos[info.name] = info; } free(ivars); } if (!_ivarInfos) _ivarInfos = @{}; if (!_methodInfos) _methodInfos = @{}; if (!_propertyInfos) _propertyInfos = @{}; _needUpdate = NO; } - (void)setNeedUpdate { _needUpdate = YES; } - (BOOL)needUpdate { return _needUpdate; } + (instancetype)classInfoWithClass:(Class)cls { if (!cls) return nil; static CFMutableDictionaryRef classCache; static CFMutableDictionaryRef metaCache; static dispatch_once_t onceToken; static dispatch_semaphore_t lock; dispatch_once(&onceToken, ^{ classCache = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); metaCache = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); lock = dispatch_semaphore_create(1); }); dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); YYClassInfo *info = CFDictionaryGetValue(class_isMetaClass(cls) ? metaCache : classCache, (__bridge const void *)(cls)); if (info && info->_needUpdate) { [info _update]; } dispatch_semaphore_signal(lock); if (!info) { info = [[YYClassInfo alloc] initWithClass:cls]; if (info) { dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); CFDictionarySetValue(info.isMeta ? metaCache : classCache, (__bridge const void *)(cls), (__bridge const void *)(info)); dispatch_semaphore_signal(lock); } } return info; } + (instancetype)classInfoWithClassName:(NSString *)className { Class cls = NSClassFromString(className); return [self classInfoWithClass:cls]; } @end EZSDK/EZSDK/EZ/Venders/YYModel/YYModel.h
New file @@ -0,0 +1,22 @@ // // YYModel.h // YYModel <https://github.com/ibireme/YYModel> // // Created by ibireme on 15/5/10. // Copyright (c) 2015 ibireme. // // This source code is licensed under the MIT-style license found in the // LICENSE file in the root directory of this source tree. // #import <Foundation/Foundation.h> #if __has_include(<YYModel/YYModel.h>) FOUNDATION_EXPORT double YYModelVersionNumber; FOUNDATION_EXPORT const unsigned char YYModelVersionString[]; #import <YYModel/NSObject+YYModel.h> #import <YYModel/YYClassInfo.h> #else #import "NSObject+YYModel.h" #import "YYClassInfo.h" #endif EZSDK/EZSDK/EZDeviceInfo.h
New file @@ -0,0 +1,55 @@ // // EZDeviceInfo.h // EzvizOpenSDK // // Created by DeJohn Dong on 15/9/16. // Copyright (c) 2015年 Ezviz. All rights reserved. // #import <Foundation/Foundation.h> /// 此类为设备信息对象 @interface EZDeviceInfo : NSObject /// 设备关联的通道信息 @property (nonatomic, strong) NSArray *cameraInfo; /// 设备关联的通道数量 @property (nonatomic) NSInteger cameraNum; /// 具有防护能力的设备布撤防状态:0-睡眠,8-在家,16-外出,普通IPC布撤防状态:0-撤防,1-布防 @property (nonatomic) NSInteger defence; /// 设备关联的探测器数量 @property (nonatomic) NSInteger detectorNum; /// 设备关联的探测器信息 @property (nonatomic, strong) NSArray *detectorInfo; /// 设备图片 @property (nonatomic, copy) NSString *deviceCover; /// 设备名称 @property (nonatomic, copy) NSString *deviceName; /// 设备序列号 @property (nonatomic, copy) NSString *deviceSerial; /// 设备类型 @property (nonatomic, copy) NSString *deviceType; /// 设备版本号 @property (nonatomic, copy) NSString *deviceVersion; /// 设备是否开启加密 @property (nonatomic) BOOL isEncrypt; /// 设备状态,1-在线,2-不在线 @property (nonatomic) NSInteger status; /// 是否支持对讲 0-不支持对讲,1-支持全双工对讲,3-支持半双工对讲 @property (nonatomic) NSInteger isSupportTalk; /// 是否支持云台控制 @property (nonatomic) BOOL isSupportPTZ; /// 是否支持放大 @property (nonatomic) BOOL isSupportZoom; ///是否支持提示音开关 @property (nonatomic) BOOL isSupportAudioOnOff; /// 是否支持中心镜像翻转 @property (nonatomic) BOOL isSupportMirrorCenter; /// 是否支持声波配网 @property (nonatomic) BOOL isSupportSoundWave; /// 设备大类 @property (nonatomic,copy) NSString *category; /// 添加时间 @property (nonatomic,strong) NSDate *addTime; @end EZSDK/EZSDK/EZSDK.h
@@ -9,46 +9,53 @@ #import "EZDeviceInfo.h" @interface EZSDK : NSObject ///sharedInstance + (instancetype)sharedInstance; /** 初始化SDK 传入国内版key 和海外版globalAppKey */ + (BOOL)initLibWithAppKey:(NSString *)appKey globalAppKey:(NSString *)globalAppKey; - (BOOL)initLibWithAppKey:(NSString *)appKey globalAppKey:(NSString *)globalAppKey; /** 设置SDK的accessToken */ +(void)setEZAccessToken:(NSString *) accessToken; - (void)setEZAccessToken:(NSString *) accessToken; /** 设置HDLSDK的accessToken */ +(void)setHDlAccessToken:(NSString *)accessToken refreshToken:(NSString *) refreshToken; - (void)setHDlAccessToken:(NSString *)accessToken refreshToken:(NSString *) refreshToken; /** 设置SDK的河东接口的requestHttpsHost和平台 标识,1.on+(默认) 2.evoyo */ +(void)setRequestHttpsHostAndPlatform:(NSString *) requestHttpsHost platform:(int)platform homeId:(NSString *)homeId; - (void)setRequestHttpsHostAndPlatform:(NSString *) requestHttpsHost platform:(int)platform homeId:(NSString *)homeId; /** 直接跳转到萤石摄像头列表 */ +(void)go2EZvizMonitor; - (void)go2EZvizMonitor; /** 跳转添加添加设备 */ +(void)addEzvizMonitor; - (void)addEzvizMonitor; /** 查看视频监控直播 */ +(void)Play:(EZDeviceInfo*)deviceInfo; - (void)Play:(EZDeviceInfo*)deviceInfo; /// 指定序列号 查看视频监控直播 /// @param deviceSerial 序列号 +(void)PlayWithDeviceSerial:(NSString *)deviceSerial; - (void)PlayWithDeviceSerial:(NSString *)deviceSerial; /** 打开摄像头设置页面 */ +(void)setting:(EZDeviceInfo*)deviceInfo; - (void)setting:(EZDeviceInfo*)deviceInfo; /** 回放播放历史 */ +(void)playBackVideo:(EZDeviceInfo*)deviceInfo; - (void)playBackVideo:(EZDeviceInfo*)deviceInfo; ////查看告警信息 //- (void)goToEZMessagePhotoVC:(EZAlarmInfo*)alarmInfo; @end EZSDK/EZSDK/EZSDK.m
@@ -18,12 +18,24 @@ #import "EZPlaybackViewController.h" #import "EZDeviceTableViewController.h" #import "EZHCNetDeviceSDK.h" #import "EZMessagePhotoViewController.h" @implementation EZSDK /// + (instancetype)sharedInstance{ static EZSDK *instance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ if (!instance) { instance = [[EZSDK alloc] init]; } }); return instance; } static BOOL isHavelibInit=NO; @@ -31,7 +43,7 @@ 初始化SDK 传入国内版key 和海外版globalAppKey */ + (BOOL)initLibWithAppKey:(NSString *)appKey globalAppKey:(NSString *)globalAppKey - (BOOL)initLibWithAppKey:(NSString *)appKey globalAppKey:(NSString *)globalAppKey { if (!isHavelibInit) { @@ -57,7 +69,7 @@ /** 设置SDK的accessToken */ +(void)setEZAccessToken:(NSString *) accessToken -(void)setEZAccessToken:(NSString *) accessToken { [[GlobalKit shareKit] setAccessToken:accessToken]; [EZOPENSDK setAccessToken:accessToken]; @@ -66,7 +78,7 @@ /** 设置HDLSDK的accessToken */ +(void)setHDlAccessToken:(NSString *) accessToken refreshToken:(NSString *) refreshToken -(void)setHDlAccessToken:(NSString *) accessToken refreshToken:(NSString *) refreshToken { [[GlobalKit shareKit] setHdlAccessToken:accessToken]; [[GlobalKit shareKit] setHdlRefreshToken:refreshToken]; @@ -74,14 +86,14 @@ /** 设置SDK的河东接口的requestHttpsHost和平台 标识,1.on+(默认) 2.evoyo */ +(void)setRequestHttpsHostAndPlatform:(NSString *) requestHttpsHost platform:(int)platform homeId:(NSString *)homeId{ -(void)setRequestHttpsHostAndPlatform:(NSString *) requestHttpsHost platform:(int)platform homeId:(NSString *)homeId{ [[GlobalKit shareKit] setGlobalRequestHttpsHost:requestHttpsHost]; [[GlobalKit shareKit] setHdlPlatform:platform]; [[GlobalKit shareKit] setHdlHomeId:homeId]; } //获取当前屏幕显示的viewcontroller (这里面获取的相当于rootViewController) +(UINavigationController *)getCurrentVC -(UINavigationController *)getCurrentVC { UIWindow * window = [[UIApplication sharedApplication] keyWindow]; if (window.windowLevel != UIWindowLevelNormal) @@ -104,7 +116,7 @@ /** 直接跳转到萤石摄像头列表 */ +(void)go2EZvizMonitor -(void)go2EZvizMonitor { // NSLog(@"go2EZvizMonitor"); //获取EZMain的stroyboard文件 @@ -121,7 +133,7 @@ /** 跳转添加添加设备 */ +(void)addEzvizMonitor -(void)addEzvizMonitor { // NSLog(@"添加摄像头"); if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) { @@ -139,7 +151,7 @@ /** 查看视频监控直播 */ +(void)Play:(EZDeviceInfo*)deviceInfo -(void)Play:(EZDeviceInfo*)deviceInfo { UIStoryboard *addDeviceStoryBoard = [UIStoryboard storyboardWithName:@"EZMain" bundle:nil]; EZLivePlayViewController *rootViewController = [addDeviceStoryBoard instantiateViewControllerWithIdentifier:@"EZLivePlayViewController"]; @@ -155,7 +167,7 @@ /// 指定序列号播放 /// @param deviceSerial 序列号 +(void)PlayWithDeviceSerial:(NSString *)deviceSerial{ -(void)PlayWithDeviceSerial:(NSString *)deviceSerial{ //获取设备列表接口 [EZOpenSDK getDeviceInfo:deviceSerial completion:^(EZDeviceInfo *deviceInfo, NSError *error) { if(error) @@ -172,7 +184,7 @@ /** 打开摄像头设置页面 */ +(void)setting:(EZDeviceInfo*)deviceInfo -(void)setting:(EZDeviceInfo*)deviceInfo { UIStoryboard *settingStoryBoard=[UIStoryboard storyboardWithName:@"EZMain" bundle:nil]; EZSettingViewController *settingVC=[settingStoryBoard instantiateViewControllerWithIdentifier:@"EZSettingViewController"]; @@ -184,7 +196,7 @@ /** 回放播放历史 */ +(void)playBackVideo:(EZDeviceInfo*)deviceInfo -(void)playBackVideo:(EZDeviceInfo*)deviceInfo { UIStoryboard *playBackStoryBoard=[UIStoryboard storyboardWithName:@"EZMain" bundle:nil]; EZPlaybackViewController *playBackVC=[playBackStoryBoard instantiateViewControllerWithIdentifier:@"EZPlaybackViewController"]; @@ -193,7 +205,17 @@ [[self getCurrentVC] pushViewController:playBackVC animated:YES]; } //// //-(void)goToEZMessagePhotoVC:(EZAlarmInfo*)alarmInfo{ // UIStoryboard *addDeviceStoryBoard = [UIStoryboard storyboardWithName:@"EZMain" bundle:nil]; // EZMessagePhotoViewController *rootViewController = [addDeviceStoryBoard instantiateViewControllerWithIdentifier:@"EZMessagePhotoViewController"]; // // NSLog(@"play--iphone--rootViewController"); // rootViewController.info = alarmInfo; //// NSLog(@"play--iphone--deviceName -%@",rootViewController.deviceInfo.deviceName); //// rootViewController.cameraIndex=0; // [[self getCurrentVC] setNavigationBarHidden:NO]; // [[self getCurrentVC] pushViewController:rootViewController animated:YES]; //} //+(void)MonitorPushMessage:(NSString *)MonitorType ID:(NSString *)ID //{ // [CommonList login];