更新时间:2024-11-18 11:32:38下载pdf
涂鸦设备详情 UI 业务包包含了以下功能:
在工程的 Podfile
文件中添加业务包组件,并执行 pod update
命令。
source "https://github.com/tuya/tuya-pod-specs"
source 'https://cdn.cocoapods.org/'
platform :ios, '11.0'
target 'your_target_name' do
# 添加设备详情 UI 业务包
pod 'TuyaSmartDeviceDetailBizBundle'
end
设备详情 UI 业务包涉及到设备图标上传时,需要使用系统相册和相机权限。因此,会涉及到部分苹果隐私权限的声明。您需要在工程的 info.plist
中添加如下权限声明:
<!-- 相册 -->
<key>NSPhotoLibraryUsageDescription</key>
<string>App 需要您的同意,才能访问相册</string>
<!-- 相机 -->
<key>NSCameraUsageDescription</key>
<string>App 需要您的同意,才能访问相机</string>
在主工程中,新建 deviceDetailConfig.json
文件。如果已经存在该文件,则不用再新建。
在 deviceDetailConfig.json
中添加以下内容:
[
{
"name": "headerSection",
"items": [
{
"cellType": "header"
},{
"cellType": "device_info"
},{
"cellType": "net_setting"
},{
"cellType":"group_edit_devices"
}
]
},{
"name": "offLineWarnSection",
"header": {
"cellType":"section_off_line_warn"
},
"items": [
{
"cellType" : "off_line_warn"
}
]
},{
"name": "otherSection",
"header": {
"cellType":"section_other"
},
"items": [
{
"cellType":"bind_multi_control_link"
},
{
"cellType":"group_create"
},
{
"cellType":"help_and_feedback"
},
{
"cellType":"add_icon_to_home_screen"
},
{
"cellType":"show_infrared_gateway_sub_device"
},
{
"cellType":"check_device_network"
},
{
"cellType":"check_firmware_update"
}
]
},{
"name": "footerSection",
"items": [
{
"cellType":"footer"
}
],
"margin": {
"top": 16
}
}
]
自定义设备详情。
deviceDetail
数组 item
的顺序影响设备详情页 item
展示的顺序。如果移除 item
,则相应地移除设备详情页子功能。
deviceDetail 类型 |
设备详情页子功能 |
---|---|
header | 查看修改设备图标,名称,位置 |
device_info | 设备信息 |
net_setting | 设备备用网络 |
off_line_warn | 设备离线提醒 |
group_edit_devices | 编辑群组 |
group_create | 创建群组 |
help_and_feedback | 常见问题与反馈,您需要额外接入 常见问题与反馈 UI 业务包 |
check_firmware_update | 检查固件升级,您需要额外接入 设备 OTA 升级 UI 业务包 |
add_icon_to_home_screen | 添加到主屏幕 |
show_infrared_gateway_sub_device | 展示遥控器 |
footer | 移除设备 |
TYSmartHomeDataProtocol
(已废弃),推荐使用TYFamilyProtocol
/**
要使用该 API 获取当前家庭,请务必在更新当前家庭 id 的时候使用该协议的’updateCurrentHomeId:‘Api。
获取当前的家庭,当前没有家庭的时候,返回 nil。
@return TuyaSmartHome
*/
- (TuyaSmartHome *)getCurrentHome;
Objective-C 示例
#import <TuyaSmartBizCore/TuyaSmartBizCore.h>
#import <TYModuleServices/TYSmartHomeDataProtocol.h>
- (void)initCurrentHome {
// 注册要实现的协议
[[TuyaSmartBizCore sharedInstance] registerService:@protocol(TYSmartHomeDataProtocol) withInstance:self];
}
// 实现对应的协议方法
- (TuyaSmartHome *)getCurrentHome {
TuyaSmartHome *home = [TuyaSmartHome homeWithHomeId:@"当前家庭 id"];
return home;
}
Swift 示例
import TuyaSmartDeviceKit
class TYMessageCenterTest: NSObject,TYSmartHomeDataProtocol{
func test() {
TuyaSmartBizCore.sharedInstance().registerService(TYSmartHomeDataProtocol.self, withInstance: self)
}
func getCurrentHome() -> TuyaSmartHome! {
let home = TuyaSmartHome.init(homeId: 111)
return home
}
}
OTA 功能:需要接入 设备 OTA 升级 UI 业务包
常见问题与反馈功能:需要接入 常见问题与反馈 UI 业务包
群组创建/编辑:需要接入 设备群组 UI 业务包
方法 | 参数 |
---|---|
跳转到网络检测页 | 设备 ID |
跳转到设备详情页,以 push 方式 | TuyaSmartDeviceModel/TuyaSmartGroupModel |
查询红外子设备是否需要显示 | devId、spaceId |
获取红外子设备是否显示 | devId、spaceId |
设备显示红外子设备状态变化通知名称 | - |
接口说明
///跳转到网络检测页
/// @param devId 设备 ID
- (void)gotoDeviceDetailNetworkViewControllerWithDeviceId:(NSString *)devId;
///跳转到设备详情页,以 push 方式
/// @param device 设备
/// @param group 群组,若有就传
- (void)gotoDeviceDetailDetailViewControllerWithDevice:(TuyaSmartDeviceModel *)device group:(TuyaSmartGroupModel *)group;
@optional
/// 查询红外子设备是否需要显示
/// @param devId 设备 ID,传入非红外线网关或者子设备将返回 **YES**
/// @param spaceId 空间 ID
/// @return YES,展示;NO,不展示
- (BOOL)getInfraredDisplayStatusWithDevId:(nullable NSString *)devId spaceId:(long long)spaceId;
@optional
/// 判断设备是否开启了显示红外子设备
/// @param devId 设备 ID
/// @param spaceId 空间 ID
/// @return YES,展示;NO,不展示
- (BOOL)cacheOfInfraredDisplayStatusWithDevId:(nullable NSString *)devId spaceId:(long long)spaceId;
@optional
/// 设备显示红外子设备状态变化通知名称
- (nullable NSNotificationName)subDeviceDisplayStatusChangeNotificationName;
Objective-C 示例
#import <TuyaSmartBizCore/TuyaSmartBizCore.h>
#import <TYModuleServices/TYDeviceDetailProtocol.h>
id<TYDeviceDetailProtocol> impl = [[TuyaSmartBizCore sharedInstance] serviceOfProtocol:@protocol(TYDeviceDetailProtocol)];
// 跳转到设备网络检测页
[impl gotoDeviceDetailNetworkViewControllerWithDeviceId:@"设备 id"];
// 跳转到设备详情页,以 push 方式
// 如果是设备,new TuyaSmartDevice
TuyaSmartDevice * device = [TuyaSmartDevice deviceWithDeviceId:@"设备 id"]
[impl gotoDeviceDetailDetailViewControllerWithDevice: device.deviceModel group: nil];
// 如果是群组,new TuyaSmartGroup
TuyaSmartGroup * group = [TuyaSmartDevice groupWithGroupId:@"群组 id"]
[impl gotoDeviceDetailDetailViewControllerWithDevice: nil group: group.deviceModel];
Swift 示例
let impl = TuyaSmartBizCore.sharedInstance().service(of: TYDeviceDetailProtocol.self) as? TYDeviceDetailProtocol
//跳转到设备网络检测页
impl?.gotoDeviceDetailNetworkViewController(withDeviceId: "设备 id")
// 跳转到设备详情页,以 push 方式
//如果是设备,new TuyaSmartDevice
let device = TuyaSmartDevice.init(deviceId: "vdevo160888044089994")
impl?.gotoDeviceDetailDetailViewController(withDevice: device?.deviceModel, group: nil)
//如果是群组,new TuyaSmartGroup
let group = TuyaSmartGroup.init(groupId: "群组 id")
impl?.gotoDeviceDetailDetailViewController(withDevice: nil, group: group?.groupModel)
添加到主屏幕 会在屏幕上创建书签,用户点击书签后可以唤起 App 进入设备面板页面。您需要进行简单的配置,才能支持这个功能。
请在 deviceDetailConfig.json
中添加add_icon_to_home_screen
,否则该功能不会展示。
配置 ty_custom_config.json
文件中的 appScheme
,例如此处的值为 "您的 appScheme"
,您需要将它替换为一个自定义的值。
{
"config": {
...
"appScheme": "您的 appScheme"
},
...
}
在添加 App 的 URL Scheme
中添加上 ty_custom_config.json
文件中 appScheme
对应的值,例如上一步配置的 "您的appScheme"
,同样,您需要将它替换为一个自定义的值。
在 AppDelegate
中处理路由事件:
Objective-C 示例
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options {
if ([[url.scheme lowercaseString] isEqualToString:@"oralcaretest"]) {
NSDictionary *params = [self dictionaryFromQuery:url.query usingEncoding:NSUTF8StringEncoding];
NSString *host = url.host;
if ([host isEqualToString:@"panelEx"]) {
id <TYPanelProtocol> impl = [[TuyaSmartBizCore sharedInstance] serviceOfProtocol:@protocol(TYPanelProtocol)];
TuyaSmartDevice *device = [TuyaSmartDevice deviceWithDeviceId:params[@"devId"]?: @""];
[impl getPanelViewControllerWithDeviceModel:device.deviceModel initialProps:nil contextProps:nil completionHandler:^(__kindof UIViewController * _Nullable panelViewController, NSError * _Nullable error) {
if (error) {
NSLog(@"Load error: %@", error);
}
}];
}
return YES;
}
return NO;
}
- (NSDictionary *)dictionaryFromQuery:(NSString *)query usingEncoding:(NSStringEncoding)encoding {
if (!([query isKindOfClass:[NSString class]] && query.length > 0)) {
return nil;
}
NSCharacterSet *delimiterSet = [NSCharacterSet characterSetWithCharactersInString:@"&;"];
NSMutableDictionary* pairs = [NSMutableDictionary dictionary];
NSScanner* scanner = [[NSScanner alloc] initWithString:query];
while (![scanner isAtEnd]) {
NSString* pairString = nil;
[scanner scanUpToCharactersFromSet:delimiterSet intoString:&pairString];
[scanner scanCharactersFromSet:delimiterSet intoString:NULL];
NSArray* kvPair = [pairString componentsSeparatedByString:@"="];
if (kvPair.count == 2) {
NSString* key = [[kvPair objectAtIndex:0]
stringByReplacingPercentEscapesUsingEncoding:encoding];
NSString* value = [[kvPair objectAtIndex:1]
stringByReplacingPercentEscapesUsingEncoding:encoding];
[pairs setObject:value forKey:key];
}
}
return [NSDictionary dictionaryWithDictionary:pairs];
}
Swift 示例
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
if let scheme = url.scheme, scheme.lowercased() == "oralcaretest" {
let params = self.params(from: url.query, .utf8)
if let host = url.host, host == "panelEx", let devId = params?["devId"] as? String, let device = TuyaSmartDevice(deviceId: devId) {
let impl: TYPanelProtocol? = TuyaSmartBizCore.sharedInstance().service(of: TYPanelProtocol.self) as? TYPanelProtocol
impl?.getPanelViewController(with: device.deviceModel, initialProps: nil, contextProps: nil, completionHandler: { vc, error in
if error != nil {
print(error!.localizedDescription)
}else{
print("push the vc")
}
})
}
return true
}
return false
}
func params(from query: String?, _ encoding: String.Encoding) -> Dictionary<String, Any>? {
guard let queryString = query, queryString.count > 0 else {
return nil
}
let set = CharacterSet(charactersIn: "&;")
var pairs = Dictionary<String, Any>()
let scanner = Scanner(string: queryString)
while !scanner.isAtEnd {
var pairString: NSString? = ""
scanner.scanUpToCharacters(from: set, into: &pairString)
scanner.scanCharacters(from: set, into: nil)
if let kvPair = pairString?.components(separatedBy: "="), kvPair.count == 2 {
let key: String = kvPair.first!.removingPercentEncoding!
let value: String = kvPair.last!
pairs[key] = value
}
}
return pairs
}
实现设备信息支持相册选择照片或者照相机拍照进行设备图标修改,请在ty_custom_config.json
文件中:
配置 is_enable_device_icon_edit
为 true
后,可以开启普通设备 相册选择照片/照相机拍照 图标修改。
配置 is_enable_group_icon_edit
为 true
,可以开启群组设备 相册选择照片/照相机拍照 图标修改。
{
"config": {
...
"is_enable_device_icon_edit": true,
"is_enable_group_icon_edit": true
},
...
}
默认情况下,SDK 不会展示设备信息中的位置信息隐藏功能。如果需要展示,请在 ty_custom_config.json
文件中配置 is_support_home_manager
为 true
。
{
"config": {
...
"is_support_home_manager": true,
},
...
}
自定义子功能可以通过配置 deviceDetailConfig.json
来实现。在 deviceDetailConfig.json
文件的 deviceDetail
插入自定义 type
。
type
值必须以 c_
开头。例如,插入 c_test_insert
、c_test_async_insert
。
[
{
"name": "headerSection",
"items": [
{
"cellType": "header"
},{
"cellType": "device_info"
},{
"cellType": "net_setting"
},{
"cellType":"group_edit_devices"
}
]
},{
"name": "offLineWarnSection",
"header": {
"cellType":"section_off_line_warn"
},
"items": [
{
"cellType" : "off_line_warn"
}
]
},{
"name": "otherSection",
"header": {
"cellType":"section_other"
},
"items": [
{
"cellType":"bind_multi_control_link"
},
{
"cellType":"group_create"
},
{
"cellType":"help_and_feedback"
},
{
"cellType":"add_icon_to_home_screen"
},
{
"cellType":"show_infrared_gateway_sub_device"
},
{
"cellType":"check_device_network"
},
{
"cellType":"check_firmware_update"
},
{
"cellType":"c_test_insert"
},
{
"cellType":"c_test_async_insert"
}
]
},{
"name": "footerSection",
"items": [
{
"cellType":"footer"
}
],
"margin": {
"top": 16
}
}
]
接口说明
进行自定义 item
插入前,调用此方法可清空数据。
/// 清空设置的自定义 item
- (void)clearInsertItem;
/// 设置-》同步处理 item 插入的回调。insertDevMenuItemBlock 会在设备详情刷新时候回调,type 为配置文件中的 cellType
-(void)insertDevMenuItem:(InsertDevMenuItemBlock) insertDevMenuItemBlock customType:(NSString *)type;
//@param type configList.json 里自己添加的 type
//@param device 设备模型
//@param group 群组模型。 根据 group 是否为 nil,来判断设备还是群组
//@return 遵守 TYDeviceDetailCustomMenuModel 协议的对象。返回 nil,该 type 的 item 则不会显示
typedef id<TYDeviceDetailCustomMenuModel> _Nullable (^InsertDevMenuItemBlock)(NSString* _Nonnull type,
TuyaSmartDeviceModel* _Nullable device,
TuyaSmartGroupModel* _Nullable group);
/// 设置-》异步处理 item 插入的回调,insertDevMenuItemAsyncBlock 会在设备详情刷新时候回调,type 为配置文件中的 cellType
-(void)insertDevMenuItemAsync:(InsertDevMenuItemAsyncBlock) insertDevMenuItemAsyncBlock customType:(NSString *)type;
//异步处理 item 插入,当异步操作结束以后,调用 complete(id<TYDeviceDetailCustomMenuMode>),回调数据给设备详情,并进行刷新列表。
typedef void (^InsertDevMenuItemAsyncBlock)(NSString* _Nonnull type,
TuyaSmartDeviceModel* _Nullable device,
TuyaSmartGroupModel* _Nullable group,
InsertDevMenuItemComplete _Nonnull complete);
Objective-C 示例
//自定义一个类遵守 TYDeviceDetailCustomMenuModel 协议
@interface CustomMenuModel : NSObject<TYDeviceDetailCustomMenuModel>
///标题
@property (nonatomic,copy) NSString *title;
///子标题
@property (nonatomic,copy) NSString *detail;
@end
@implementation CustomMenuModel
@end
Swift 示例
class CustomMenuModel: NSObject, TYDeviceDetailCustomMenuModel{
var title : String?
var detail : String?
}
Objective-C 示例
id<TYDeviceDetailProtocol> impl = [[TuyaSmartBizCore sharedInstance] serviceOfProtocol:@protocol(TYDeviceDetailProtocol)];
[impl clearInsertItem];// 插入前清空数据
[impl insertDevMenuItem:^ id<TYDeviceDetailCustomMenuModel> (NSString * _Nonnull type, TuyaSmartDeviceModel * _Nonnull device, TuyaSmartGroupModel * _Nonnull group) {
if ([type isEqualToString:@"c_test_insert"]) {
CustomMenuModel *model = [CustomMenuModel new];
if (group) { //根据 group 是否为 nil,来判断设备还是群组
model.title = type;
model.detail = @"group";
}else{
model.title = type;
model.detail = @"device";
}
return model;
}
return nil;
} customType:@"c_test_insert"];
[impl insertDevMenuItemAsync:^(NSString * _Nonnull type, TuyaSmartDeviceModel * _Nonnull device, TuyaSmartGroupModel * _Nonnull group, InsertDevMenuItemComplete _Nonnull complete) {
if ([type isEqualToString:@"c_test_async_insert"]) {
//耗时操作
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
CustomMenuModel *model = [CustomMenuModel new];
if (group) { //根据 group 是否为 nil,来判断设备还是群组
model.title = type;
model.detail = @"group";
}else{
model.title = type;
model.detail = @"device";
}
complete(model);
});
}
} customType:@"c_test_insert"];
Swift 示例
let impl = TuyaSmartBizCore.sharedInstance().service(of: TYDeviceDetailProtocol.self) as? TYDeviceDetailProtocol
impl?.clearInsertItem // 插入前清空数据
impl?.insertDevMenuItem({ (type, deviceModel, groupModel) -> TYDeviceDetailCustomMenuModel? in
if type == "c_test_insert" {//根据 group 是否为 nil,来判断设备还是群组
let model = CustomMenuModel.init()
if groupModel != nil {
model.title = type
model.detail = "group"
}else{
model.title = type
model.detail = "device"
}
return model;
}
return nil;
} , customType: "c_test_insert")
impl?.insertDevMenuItemAsync({ (type, deviceModel, groupModel, complete) in
if type == "c_test_async_insert" {
//耗时操作
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
let model = CustomMenuModel.init()
if groupModel != nil {
model.title = type
model.detail = "group"
}else{
model.title = type
model.detail = "device"
}
complete(model);
}
}
} , customType: "c_test_async_insert");
Objective-C 示例
id<TYDeviceDetailProtocol> impl = [[TuyaSmartBizCore sharedInstance] serviceOfProtocol:@protocol(TYDeviceDetailProtocol)];
[impl clickMenuItem: ^(NSString * _Nonnull type, TuyaSmartDeviceModel * _Nonnull device, TuyaSmartGroupModel * _Nonnull group) {
NSLog(@"clickItem: type:%@",type);
}];
Swift 示例
let impl = TuyaSmartBizCore.sharedInstance().service(of: TYDeviceDetailProtocol.self) as? TYDeviceDetailProtocol
impl?.clickMenuItem({ (type, deviceModel, groupModel) in
print("clickItem: type:"+type);
})
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈