ios封装UI组件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ios封装UI组件相关的知识,希望对你有一定的参考价值。

参考技术A 假定原生组件是一个View,在ios端封装该View

1.1 导入头文件 <React/RCTComponent.h>

1.2 导入原生组件头文件,本例子是 "TTAVPlayer.h"

1.3 引入js层传入的block 事件属性

RCTVideoPlayer.h

#import#import

#import "TTAVPlayer.h"

@interface RCTVideoPlayer : TTAVPlayerView

@property (nonatomic, copy) RCTBubblingEventBlock onBack;

@property (nonatomic, copy) RCTBubblingEventBlock onPlayError;

@property (nonatomic, copy) RCTBubblingEventBlock onPause;

@property (nonatomic, copy) RCTBubblingEventBlock onEnd;

@property (nonatomic, copy) RCTBubblingEventBlock onPlay;

@end

2.1 导入"RCTVideoPlayerManager.h"和<React/UIView+React.h>

2.2 init该View,并初始化js层设置的属性

2.3 如果该View有设置代理,实现代理方法并向js层发通知以执行额外操作

#import "RCTVideoPlayer.h"#import "RCTVideoPlayerManager.h"#import@implementation RCTVideoPlayer

- (id)init



self = [super initWithFrame:CGRectZero withViewMode:TTAVPlayerViewNormalMode];

[super setDelegate:self];

return self;



- (void)setSrc:(NSString *)src

NSLog(@"set src -> %@", src);

[super setVideoUrl:src];



- (void)backButtonGetTap:(BOOL)isFullScreen

if(self.onBack && !isFullScreen)

self.onBack(@@"isFullScreen": @(isFullScreen));





1.1 继承RCTViewManager

#import<React/RCTViewManager.h>

#import "TTAVPlayer.h"

@interface RCTVideoPlayerManager : RCTViewManager

@end

2.1 声明该class属性共享

RCT_EXPORT_MODULE();

RCT_EXPORT_VIEW_PROPERTY(placeholderImage, NSString)   值属性

RCT_EXPORT_VIEW_PROPERTY(onPlay, RCTBubblingEventBlock)  事件属性

事件属性与View中的事件属性相对应,实现原生向js层通信

2.2 初始化view(每个manager都有一个view)

- (UIView *)view

   return [[RCTVideoPlayer alloc] init];  

2.3 导出方法给js层调用

RCT_EXPORT_METHOD(play: (nonnull NSNumber *)reactTag) [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary*viewRegistry)

UIView *view = viewRegistry[reactTag];

if (![view isKindOfClass:[RCTVideoPlayer class]])

RCTLog(@"expecting UIView, got: %@", view);



else

RCTVideoPlayer *player = (RCTVideoPlayer *)view;

[player play];



];



在js主动要求更新原生UI层的事件中,需要注意两点,

1是使用[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary*viewRegistry) ]来更新UI,该方法需要导入<React/RCTUIManager.h>

2是该方法需要特定的线程执行,如下

- (dispatch_queue_t)methodQueue



return self.bridge.uiManager.methodQueue;



导出UI组件

import requireNativeComponent from'react-native';

class VideoPlayer extends Component

render()

return <RCTVideoref="native" ...this.props onPlayError=this.onPlayError/>;





constRCTVideo =requireNativeComponent('RCTVideoPlayer',VideoPlayer);

export defaultVideoPlayer;

需要注意

1.1 class类似一般的react class

1.2 constructor(...args)

1.3 staticpropTypes=

...View.propTypes,

src: PropTypes.string.isRequired,

onPlayError: PropTypes.func

;

1.4 js层调用原生方法

play= (url,isCache,title) =>

if(Platform.OS =='android')

UIManager.dispatchViewManagerCommand(

ReactNative.findNodeHandle(this),

UIManager.RCTVideoPlayer.Commands.play,

[url,isCache,title]

);

else

const VideoPlayerManager = NativeModules;

VideoPlayerManager.play(ReactNative.findNodeHandle(this));



;

react native 使用 iOS 原生 UI 组件

目前 react native 的组件还是不多,有些也并不怎么好用,这时候就需要封装原生 UI 组件了

之前写过RN 与 native 的通信 无非就是两种:

1>>>  react native 内部事件需要通知 native 调用 native 的方法(或者传递RN 中的数据到 native),这时候可以用新建一个 manager 之类的文件 RCT_EXPORT_MOUDLE() 暴露 native类  ,RCT_EXPORT_METHOD () 暴露 native 方法给 js 调用 ,在 js里通过 NativeMoudles.XXX 取得该 native 文件 然后调用方法(传递 js里的参数到 native )即可完成通信

2 >>>native 发生的事件需要通知到js的时候 一种发送通知 self.bridge sendXXX 这种方法好像不常用 有警告,当然也可以用上面的那种采用 js主动调用 native, 在 native 方法里添加一个 block 回调,在 block 回调里把数据回传给 js. 或者就是下面的方法,导出 native 组件的方法给 js

下面开始封装原生ios组件

这里我封装的是一个相册浏览视图,PhotoView 继承自 UIView ,就按普通的自定义 View 来就可以了.

然后有三点不同的

1>>> 声明一个RCTBubblingEventBlock 的属性,这是什么鬼 ? 就是你要导出的方法,命名以 on开头 比如 onTap,onClick自行发挥

2>>> 如果需要在 js里给你的 UI 组件传值 ,赋值属性的话 ,暴露出来一个需要传值得属性: 如@property(nonatomic,strong)NSString ***

3>>>如果需要导出方法的话, 声明一个 protocol ,代理方法 ,让你的代理去执行,为什么要用代理呢 , 后面再说,下面看图: 自定义 UI 组件

技术分享图片

注释已经很清楚了,没有什么需要解释的吧,需要的话,私聊哈

然后就是到处这个 UI 组件了

1>新建一个Manager,当然啦,你爱叫什么都行,一般以 manager 命名,继承自 RCTViewManger

2>遵守你刚才自定义视图的协议 作为他的代理 实现他的代理方法 

3>重写-(UIView *)view 的方法,在该方法里 不要赋值什么属性,什么都不要干, alloc init 设置代理为 self 就 OK

4>RCT_EXPORT_MOUDLE()导出模块  RCT_EXPORT_VIEW_PROPERTY(url,NSString)导出属性  RCT_EXPORT_VIEW_PROPERTY(onSingleTap,RCTBubblingEventBlock)导出方法  需要注意的是一定要写对属性名 和方法名 跟你自定义视图里的一致

5> 如果是单纯的导出属性的话不需要代理什么的已经可以了  导出方法的话就要实现代理方法 在代理方法里 通过持有的自定义视图 赋值自定义视图的 block,导出方法,可以带一个 obj类型的参数, 下面看图 

技术分享图片技术分享图片

tips: 有一个比较坑的地方,就是在 js调试你原生 UI 事件的时候不要用 console.warn(),一直不会打印警告,不过也可能跟我的视图有关系,我添加的有动画,可能产生冲突

 

以上是关于ios封装UI组件的主要内容,如果未能解决你的问题,请参考以下文章

Vue ui组件封装

react native 使用 iOS 原生 UI 组件

封装一个简单的UI组件

Vue + Element UI前端篇:功能组件封装

前端如何搭建UI组件库/封装插件(从零到有)

OpenHarmony——ets自定义弹窗UI组件封装