OC调用设备功能扩展(无UI界面,UI界面纯原生的,固定不变的)
非事件型功能--当业务需要某种信息或者需要终端执行某项指令,直接通过接口调用终端代码即可。
使用方法:创建类只需要继承自简单的NSObject类即可
XWPhotoModule.h
@interface XWPhotoModule : NSObject <HippyBridgeModule>
@end
XWPhotoModule.m
/// 将当前类注册,前端会对当前类进行实例对象指派。可以自定义,也可以不填
/// HIPPY_EXPORT_MODULE(PhotoModule)或者HIPPY_EXPORT_MODULE()(默认当前类名)
HIPPY_EXPORT_MODULE(PhotoModule)
// 无回调
HIPPY_EXPORT_METHOD(choosePhoto) {
NSLog(@"响应操作");
}
// 无回调带参
HIPPY_EXPORT_METHOD(choosePhoto:(NSString *)photoString) {
NSLog(@"%@", photoString);
NSLog(@"响应操作");
}
// 有回调
HIPPY_EXPORT_METHOD(updatePhotoString:(NSString *)photoString
resolver:(HippyPromiseResolveBlock)resolve
rejecter:(__unused HippyPromiseRejectBlock)reject) {
NSLog(@"%@", photoString);
resolve(@{@"result" : @"你谁啊?"});
}
事件型功能--业务需要终端监听某个事件。当事件触发时,终端通知前端。
使用方法:创建类继承HippyEventObserverModule类
XWPhotoModule.h
#import <UIKit/UIKit.h>
#import "HippyEventObserverModule.h"
@interface XWPhotoModule : HippyEventObserverModule <HippyBridgeModule>
@end
XWPhotoModule.m
HIPPY_EXPORT_MODULE(PhotoModule)
// 无回调
HIPPY_EXPORT_METHOD(choosePhoto) {
NSLog(@"响应操作");
}
// 在需要向前端发消息的方法中调用 [self sendEvent:@"photo" params:@{@"key": @"value"}]; 第一个参数为事件名,前端终端事件名必须一致。 第二个参数为事件信息,`NSDictionary`类型。
- (void)eventOccur {
// 事件发生,通知前端
[self sendEvent:@"photo" params:@{@"key": @"value"}];
}
JS调用终端能力
callNative/callNativeWithPromise
调用终端模块的方法,callNative 一般用于无返回的模块方法调用,callNativeWithPromise 一般用于有返回的模块方法调用,它会返回一个带着结果的 Promise。
methods: {
clickView() {
// 无回调(类名,方法)- (void)choosePhoto;
Vue.Native.callNative('PhotoModule', 'choosePhoto');
// 无回调带参(类名,方法,参数)- (void)choosePhoto:(NSString *)photo;
Vue.Native.callNative('PhotoModule', 'choosePhoto', '小李');
// 回调
Vue.Native.callNativeWithPromise('PhotoModule', 'updatePhotoString', '小李').then(resolve => {
console.log(resolve);
/// async 和await回调
this.updatePhotoString();
});
},
/// async 和await回调
async updatePhotoString() {
const resolve = await Vue.Native.callNativeWithPromise('PhotoModule', 'updatePhotoString', '小李');
console.log(resolve);
},
},
调用终端事件,终端通过[self sendEvent:@"photo" params:@{@"key": @"value"}];发送事件,前端需要监听事件发送来做出响应
methods: {
// 监听事件返回值,输出结果
listener(rsp) {
console.log(rsp);
console.log(rsp.key);
},
},
// 页面加载完成调用
mounted() {
// 将入口文件中 setApp() 时保存的 Vue 实例取出来。
const app = getApp();
// 通过 app 监听 rotate 事件,并通过 this.listener 在事件发生时触发回调。
app.$on('photo', this.listener);
},
当前组件不需要使用的时候,一定要销毁
// 销毁、释放
beforeDestroy() {
// 取消 mounted 里监听的自定义事件
app.$off('photo', this.listener);
},
以下是关于调用相机相册的完整例子
XWPhotoModule.h
#import <UIKit/UIKit.h>
#import "HippyEventObserverModule.h"
NS_ASSUME_NONNULL_BEGIN
@interface XWPhotoModule : HippyEventObserverModule <HippyBridgeModule, UINavigationControllerDelegate, UIImagePickerControllerDelegate>
@end
NS_ASSUME_NONNULL_END
XWPhotoModule.m
#import "XWPhotoModule.h"
#import "HippyUtils.h"
static NSString *xwPhotoEvent = @"photo";
@implementation XWPhotoModule
// hippy_export_module
HIPPY_EXPORT_MODULE(PhotoModule)
// hippy_export_method
HIPPY_EXPORT_METHOD(choosePhoto) {
UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
UIAlertAction *snapAction = [UIAlertAction actionWithTitle:@"拍照" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[self snapImage];
}];
UIAlertAction *albumAction = [UIAlertAction actionWithTitle:@"从手机相册选择" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[self localAlbum];
}];
[actionSheet addAction:cancelAction];
[actionSheet addAction:snapAction];
[actionSheet addAction:albumAction];
[HippyPresentedViewController() presentViewController:actionSheet animated:YES completion:nil];
}
/// 拍照
- (void)snapImage {
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
__block UIImagePickerController *ipc = [[UIImagePickerController alloc] init];
ipc.sourceType = UIImagePickerControllerSourceTypeCamera;
ipc.delegate = self;
ipc.navigationBar.barTintColor = [UIColor whiteColor];
ipc.navigationBar.tintColor = [UIColor whiteColor];
ipc.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName:[UIColor whiteColor]};
[HippyPresentedViewController() presentViewController:ipc animated:YES completion:^{
ipc = nil;
}];
} else {
NSLog(@"模拟器无法打开照相机");
}
}
/// 从手机相册选择
- (void)localAlbum {
__block UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.view.backgroundColor = [UIColor whiteColor];
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
picker.delegate = self;
picker.navigationBar.barTintColor = [UIColor whiteColor];
picker.navigationBar.tintColor = [UIColor blackColor];
picker.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName:[UIColor blackColor]};
[HippyPresentedViewController() presentViewController:picker animated:YES completion:^{
picker = nil;
}];
}
//当用户取消选择的时候,调用该方法
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:^{}];
}
/// 用户确认了选择了照片调取这个方法
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
[picker dismissViewControllerAnimated:YES completion:^{
UIImage *selectedImage = info[UIImagePickerControllerOriginalImage];
NSData *imgData = UIImageJPEGRepresentation(selectedImage, 0.4);
NSString *imageStr = @"";
if (imgData) {
imageStr = @"test";
}
// 事件发生,通知前端
[self sendEvent:xwPhotoEvent params:@{@"result": imageStr}];
}];
}
@end
JS的app.vue代码
<template>
<div class="button-demo">
<label>按钮和状态绑定:</label>
<button v-bind:class="{ 'is-active': isClicked, 'is-pressing': isPressing }"
class="button-demo-1"
@click="clickView"
<span v-if="isClicked" class="button-text">视图已经被点击了,再点一下恢复</span>
<span v-else class="button-text">视图尚未点击</span>
</button>
</div>
</template>
<script>
import Vue from 'vue';
import { getApp } from './util';
const XW_CAMERA = 'photo';
export default {
methods: {
clickView() {
Vue.Native.callNative('PhotoModule', 'choosePhoto');
},
// 监听
uploadImage(rsp) {
console.log(rsp);
console.log(rsp.result);
},
},
// 页面加载完成调用
mounted() {
// 将入口文件中 setApp() 时保存的 Vue 实例取出来。
const app = getApp();
// 通过 app 监听 rotate 事件,并通过 this.listener 在事件发生时触发回调。
/// 相册 相机
app.$on(XW_CAMERA, this.uploadImage);
},
data() {
return {
isClicked: false,
isPressing: false,
};
},
// 销毁、释放
beforeDestroy() {
// 取消 mounted 里监听的自定义事件
app.$off(XW_CAMERA, this.uploadImage);
},
};
</script>
<style scope>
.button-demo {
display: flex;
align-items: center;
flex-direction: column;
}
.button-demo-1 {
height: 64px;
width: 240px;
border-style: solid;
border-color: #40b883;
border-width: 2px;
border-radius: 10px;
align-items: center;
}
.button-demo-1 .button-text {
line-height: 56px;
text-align: center;
}
.button-demo-1-image {
width: 216px;
height: 58px;
}
.button-demo-1.is-active {
color: white;
background-color: red;
}
.button-demo-1.is-pressing {
color: white;
background-color: blue;
}
</style>
网友评论