iOS 8 WkWebView 网页的配置和前进,后退,js 交互和进度条的加载
2015-12-22 16:22
956 查看
本文也将讲解到WebKit中更新的WKWebView控件的新特性与使用方法,它很好的解决了UIWebView存在的内存、加载速度等诸多问题。
一、WKWebView新特性
在性能、稳定性、功能方面有很大提升(最直观的体现就是加载网页是占用的内存,模拟器加载百度与开源中国网站时,WKWebView占用23M,而UIWebView占用85M);
允许JavaScript的Nitro库加载并使用(UIWebView中限制);
支持了更多的HTML5特性;
高达60fps的滚动刷新率以及内置手势;
将UIWebViewDelegate与UIWebView重构成了14类与3个协议;
二、代码实现。
// Created by 周双建 on 15/12/21.
// Copyright © 2015年
周双建. All rights reserved.
//
#import "ViewController.h"
//要导入其框架
#import <WebKit/WKWebView.h>
#import <WebKit/WebKit.h>
typedef enum {
URL_load = 0,
HTML_load ,
Data_load ,
Fiel_load,
}WkwebLoadType;
@interface
ViewController ()<WKNavigationDelegate,WKUIDelegate>
//创建一个实体变量
@property(nonatomic,strong)
WKWebView * ZSJ_WkwebView;
// 加载type
@property(nonatomic,assign)
NSInteger IntegerType;
// 设置加载进度条
@property(nonatomic,strong)
UIProgressView * ProgressView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super
viewDidLoad];
[self makeNav];
//
创建进度条
if (!self.ProgressView) {
self.ProgressView = [[UIProgressView
alloc]initWithProgressViewStyle:UIProgressViewStyleDefault];
self.ProgressView.frame =
CGRectMake(0,
64, self.view.bounds.size.width,
1);
//
设置进度条的色彩
[self.ProgressView
setTrackTintColor:[UIColor
clearColor]];
self.ProgressView.progressTintColor = [UIColor
magentaColor];
[self.view
addSubview:self.ProgressView];
}
//初始化webview
if (!self.ZSJ_WkwebView) {
//设置网页的配置文件
WKWebViewConfiguration * Configuration = [[WKWebViewConfiguration
alloc]init];
//允许视频播放
Configuration.allowsAirPlayForMediaPlayback =
YES;
//
允许在线播放
Configuration.allowsInlineMediaPlayback =
YES;
// 允许可以与网页交互,选择视图
Configuration.selectionGranularity =
YES;
//创建更改数据源
NSString * JS = [NSString
stringWithFormat:@"loadDetail(\"%d\")",70];
WKUserScript * script = [[WKUserScript
alloc] initWithSource:JS
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
forMainFrameOnly:YES];
WKUserContentController * UserContentController = [[WKUserContentController
alloc]init];
[UserContentController addUserScript:script];
//
是否支持记忆读取
Configuration.suppressesIncrementalRendering =
YES;
//
允许用户更改网页的设置
Configuration.userContentController = UserContentController;
self.ZSJ_WkwebView = [[WKWebView
alloc]initWithFrame:CGRectMake(0,
66, self.view.bounds.size.width,
self.view.bounds.size.height -111)
configuration:Configuration];
// 设置代理
self.ZSJ_WkwebView.navigationDelegate =
self;
self.ZSJ_WkwebView.UIDelegate =
self;
//
添加进度监控
/*
NSKeyValueObservingOptionNew
把更改之前的值提供给处理方法
NSKeyValueObservingOptionOld
把更改之后的值提供给处理方法
NSKeyValueObservingOptionInitial
把初始化的值提供给处理方法,一旦注册,立马就会调用一次。通常它会带有新值,而不会带有旧值。
NSKeyValueObservingOptionPrior
分2次调用。在值改变之前和值改变之后。
*/
[self.ZSJ_WkwebView
addObserver:self
forKeyPath:@"estimatedProgress"
options:NSKeyValueObservingOptionNew
context:nil];
//开启手势触摸
self.ZSJ_WkwebView.allowsBackForwardNavigationGestures
= YES;
//
设置 可以前进
和
后退
//适应你设定的尺寸
[self.ZSJ_WkwebView
sizeToFit];
//选择加载方式
[self
loadinteger:HTML_load];
//添加到主控制器上
[self.view
addSubview:self.ZSJ_WkwebView];
[self makefourbtn];
}
// Do any additional setup after loading the view, typically from a nib.
}
-(void)makeNav{
UILabel * Nav_Label = [[UILabel
alloc]initWithFrame:CGRectMake(self.view.center.x-100,
20, 200,
44)];
Nav_Label.text =
@"成功QQ吧提供";
Nav_Label.textAlignment =
NSTextAlignmentCenter;
Nav_Label.font = [UIFont
italicSystemFontOfSize:22];
[self.view
addSubview:Nav_Label];
UIView * Line = [[UIView
alloc]initWithFrame:CGRectMake(0,
63.5, self.view.bounds.size.width,
0.5)];
Line.backgroundColor = [UIColor
lightGrayColor];
[self.view
addSubview:Line];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4
* NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
});
}
- (void)didReceiveMemoryWarning {
[super
didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)makefourbtn{
NSArray * WkWeb_Title =
@[@"重载",@"后退",@"前进",@"跳转"];
for (int i=
0 ; i<4; i ++) {
UIButton * button = [UIButton
buttonWithType:UIButtonTypeCustom];
button.frame =
CGRectMake(10+i*((self.view.bounds.size.width-50)/4+10),
self.view.bounds.size.height -
45, (self.view.bounds.size.width-50)/4,
40);
[button setTitle:WkWeb_Title[i]
forState:UIControlStateNormal];
button.layer.borderWidth =
0.5;
[button setTitleColor:[UIColor
blackColor] forState:UIControlStateNormal];
button.tag = i;
[button addTarget:self
action:@selector(ClicK:)
forControlEvents:UIControlEventTouchUpInside];
[self.view
addSubview:button];
}
}
-(void)ClicK:(UIButton *)Btn{
switch (Btn.tag) {
case 0:{
// //这个是带缓存的验证
// [self.ZSJ_WkwebView reloadFromOrigin];
//
是不带缓存的验证,刷新当前页面
[self.ZSJ_WkwebView
reload];
}
break;
case 1:{
// 后退
//
首先判断网页是否可以后退
if (self.ZSJ_WkwebView.canGoBack) {
[self.ZSJ_WkwebView
goBack];
}
}
break;
case 2:{
// 前进
// 判断是否可以前进
if (self.ZSJ_WkwebView.canGoForward) {
[self.ZSJ_WkwebView
goForward];
}
}
break;
case 3:{
//进行跳转,我们设置跳转的返回到第一个界面
NSLog(@"%@",self.ZSJ_WkwebView.backForwardList.backList);
if (self.ZSJ_WkwebView.backForwardList.backList.count
>2) {
[self.ZSJ_WkwebView
goToBackForwardListItem:self.ZSJ_WkwebView.backForwardList.backList[0]];
}
}
break;
default:
break;
}
}
-(void)loadinteger:(NSInteger)integer{
switch (integer) {
case 0:{
//创建一个NSURLRequest
的对象
NSURLRequest * Request_zsj = [NSURLRequest
requestWithURL:[NSURL
URLWithString:@"http://image.baidu.com/search/index?tn=baiduimage&ct=201326592&lm=-1&cl=2&ie=gbk&word=%C3%C0%C5%AE%CD%BC%C6%AC%B4%F3%CD%BC&fr=ala&ala=1&alatpl=cover&pos=0#z=0&pn=&ic=0&st=-1&face=0&s=0&lm=-1"]];
//加载网页
[self.ZSJ_WkwebView
loadRequest:Request_zsj];
}
break;
case 1:{
// 获取文件路径
NSString *resourcePath = [ [NSBundle
mainBundle] resourcePath];
NSString *filePath = [resourcePath
stringByAppendingPathComponent:@"test.html"];
NSString *htmlstring =[[NSString
alloc] initWithContentsOfFile:filePath
encoding:NSUTF8StringEncoding
error:nil];
[self.ZSJ_WkwebView
loadHTMLString:htmlstring baseURL:[NSURL
URLWithString:[[NSBundle
mainBundle] bundlePath]]];
}
break;
case 2:{
}
break;
case 3:{
}
break;
default:
break;
}
}
//这个是网页加载完成,导航的变化
-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
/*
主意:这个方法是当网页的内容全部显示(网页内的所有图片必须都正常显示)的时候调用(不是出现的时候就调用),,否则不显示,或则部分显示时这个方法就不调用。
*/
NSLog(@"加载完成调用");
// 获取加载网页的标题
NSLog(@"加载的标题:%@",self.ZSJ_WkwebView.title);
}
//开始加载
-(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
//开始加载的时候,让加载进度条显示
self.ProgressView.hidden =
NO;
NSLog(@"开始加载的时候调用。。");
NSLog(@"%lf",
self.ZSJ_WkwebView.estimatedProgress);
}
//内容返回时调用
-(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{
NSLog(@"当内容返回的时候调用");
NSLog(@"%lf",
self.ZSJ_WkwebView.estimatedProgress);
}
-(void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{
NSLog(@"这是服务器请求跳转的时候调用");
}
-(void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error{
// 内容加载失败时候调用
NSLog(@"这是加载失败时候调用");
NSLog(@"%@",error);
}
-(void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error{
NSLog(@"通过导航跳转失败的时候调用");
}
-(void)webViewDidClose:(WKWebView *)webView{
NSLog(@"网页关闭的时候调用");
}
-(void)webViewWebContentProcessDidTerminate:(WKWebView *)webView{
NSLog(@"%lf", webView.estimatedProgress);
}
-(void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo
*)frame completionHandler:(void (^)(void))completionHandler{
//
获取js 里面的提示
}
-(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo
*)frame completionHandler:(void (^)(BOOL))completionHandler{
// js
信息的交流
}
-(void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText
initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *
_Nullable))completionHandler{
// 交互。可输入的文本。
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString
*,id> *)change context:(void *)context{
// 首先,判断是哪个路径
if ([keyPath isEqualToString:@"estimatedProgress"]) {
//
判断是哪个对象
if (object ==
self.ZSJ_WkwebView) {
NSLog(@"进度信息:%lf",self.ZSJ_WkwebView.estimatedProgress);
if (self.ZSJ_WkwebView.estimatedProgress ==
1.0) {
//隐藏
self.ProgressView.hidden =
YES;
}else{
// 添加进度数值
self.ProgressView.progress =
self.ZSJ_WkwebView.estimatedProgress;
}
}
}
}
//注意,观察的移除
-(void)dealloc{
[self
removeObserver:self
forKeyPath:@"estimatedProgress"];
}
@end
三、效果图。
一、WKWebView新特性
在性能、稳定性、功能方面有很大提升(最直观的体现就是加载网页是占用的内存,模拟器加载百度与开源中国网站时,WKWebView占用23M,而UIWebView占用85M);
允许JavaScript的Nitro库加载并使用(UIWebView中限制);
支持了更多的HTML5特性;
高达60fps的滚动刷新率以及内置手势;
将UIWebViewDelegate与UIWebView重构成了14类与3个协议;
二、代码实现。
// Created by 周双建 on 15/12/21.
// Copyright © 2015年
周双建. All rights reserved.
//
#import "ViewController.h"
//要导入其框架
#import <WebKit/WKWebView.h>
#import <WebKit/WebKit.h>
typedef enum {
URL_load = 0,
HTML_load ,
Data_load ,
Fiel_load,
}WkwebLoadType;
@interface
ViewController ()<WKNavigationDelegate,WKUIDelegate>
//创建一个实体变量
@property(nonatomic,strong)
WKWebView * ZSJ_WkwebView;
// 加载type
@property(nonatomic,assign)
NSInteger IntegerType;
// 设置加载进度条
@property(nonatomic,strong)
UIProgressView * ProgressView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super
viewDidLoad];
[self makeNav];
//
创建进度条
if (!self.ProgressView) {
self.ProgressView = [[UIProgressView
alloc]initWithProgressViewStyle:UIProgressViewStyleDefault];
self.ProgressView.frame =
CGRectMake(0,
64, self.view.bounds.size.width,
1);
//
设置进度条的色彩
[self.ProgressView
setTrackTintColor:[UIColor
clearColor]];
self.ProgressView.progressTintColor = [UIColor
magentaColor];
[self.view
addSubview:self.ProgressView];
}
//初始化webview
if (!self.ZSJ_WkwebView) {
//设置网页的配置文件
WKWebViewConfiguration * Configuration = [[WKWebViewConfiguration
alloc]init];
//允许视频播放
Configuration.allowsAirPlayForMediaPlayback =
YES;
//
允许在线播放
Configuration.allowsInlineMediaPlayback =
YES;
// 允许可以与网页交互,选择视图
Configuration.selectionGranularity =
YES;
//创建更改数据源
NSString * JS = [NSString
stringWithFormat:@"loadDetail(\"%d\")",70];
WKUserScript * script = [[WKUserScript
alloc] initWithSource:JS
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
forMainFrameOnly:YES];
WKUserContentController * UserContentController = [[WKUserContentController
alloc]init];
[UserContentController addUserScript:script];
//
是否支持记忆读取
Configuration.suppressesIncrementalRendering =
YES;
//
允许用户更改网页的设置
Configuration.userContentController = UserContentController;
self.ZSJ_WkwebView = [[WKWebView
alloc]initWithFrame:CGRectMake(0,
66, self.view.bounds.size.width,
self.view.bounds.size.height -111)
configuration:Configuration];
// 设置代理
self.ZSJ_WkwebView.navigationDelegate =
self;
self.ZSJ_WkwebView.UIDelegate =
self;
//
添加进度监控
/*
NSKeyValueObservingOptionNew
把更改之前的值提供给处理方法
NSKeyValueObservingOptionOld
把更改之后的值提供给处理方法
NSKeyValueObservingOptionInitial
把初始化的值提供给处理方法,一旦注册,立马就会调用一次。通常它会带有新值,而不会带有旧值。
NSKeyValueObservingOptionPrior
分2次调用。在值改变之前和值改变之后。
*/
[self.ZSJ_WkwebView
addObserver:self
forKeyPath:@"estimatedProgress"
options:NSKeyValueObservingOptionNew
context:nil];
//开启手势触摸
self.ZSJ_WkwebView.allowsBackForwardNavigationGestures
= YES;
//
设置 可以前进
和
后退
//适应你设定的尺寸
[self.ZSJ_WkwebView
sizeToFit];
//选择加载方式
[self
loadinteger:HTML_load];
//添加到主控制器上
[self.view
addSubview:self.ZSJ_WkwebView];
[self makefourbtn];
}
// Do any additional setup after loading the view, typically from a nib.
}
-(void)makeNav{
UILabel * Nav_Label = [[UILabel
alloc]initWithFrame:CGRectMake(self.view.center.x-100,
20, 200,
44)];
Nav_Label.text =
@"成功QQ吧提供";
Nav_Label.textAlignment =
NSTextAlignmentCenter;
Nav_Label.font = [UIFont
italicSystemFontOfSize:22];
[self.view
addSubview:Nav_Label];
UIView * Line = [[UIView
alloc]initWithFrame:CGRectMake(0,
63.5, self.view.bounds.size.width,
0.5)];
Line.backgroundColor = [UIColor
lightGrayColor];
[self.view
addSubview:Line];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4
* NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
});
}
- (void)didReceiveMemoryWarning {
[super
didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)makefourbtn{
NSArray * WkWeb_Title =
@[@"重载",@"后退",@"前进",@"跳转"];
for (int i=
0 ; i<4; i ++) {
UIButton * button = [UIButton
buttonWithType:UIButtonTypeCustom];
button.frame =
CGRectMake(10+i*((self.view.bounds.size.width-50)/4+10),
self.view.bounds.size.height -
45, (self.view.bounds.size.width-50)/4,
40);
[button setTitle:WkWeb_Title[i]
forState:UIControlStateNormal];
button.layer.borderWidth =
0.5;
[button setTitleColor:[UIColor
blackColor] forState:UIControlStateNormal];
button.tag = i;
[button addTarget:self
action:@selector(ClicK:)
forControlEvents:UIControlEventTouchUpInside];
[self.view
addSubview:button];
}
}
-(void)ClicK:(UIButton *)Btn{
switch (Btn.tag) {
case 0:{
// //这个是带缓存的验证
// [self.ZSJ_WkwebView reloadFromOrigin];
//
是不带缓存的验证,刷新当前页面
[self.ZSJ_WkwebView
reload];
}
break;
case 1:{
// 后退
//
首先判断网页是否可以后退
if (self.ZSJ_WkwebView.canGoBack) {
[self.ZSJ_WkwebView
goBack];
}
}
break;
case 2:{
// 前进
// 判断是否可以前进
if (self.ZSJ_WkwebView.canGoForward) {
[self.ZSJ_WkwebView
goForward];
}
}
break;
case 3:{
//进行跳转,我们设置跳转的返回到第一个界面
NSLog(@"%@",self.ZSJ_WkwebView.backForwardList.backList);
if (self.ZSJ_WkwebView.backForwardList.backList.count
>2) {
[self.ZSJ_WkwebView
goToBackForwardListItem:self.ZSJ_WkwebView.backForwardList.backList[0]];
}
}
break;
default:
break;
}
}
-(void)loadinteger:(NSInteger)integer{
switch (integer) {
case 0:{
//创建一个NSURLRequest
的对象
NSURLRequest * Request_zsj = [NSURLRequest
requestWithURL:[NSURL
URLWithString:@"http://image.baidu.com/search/index?tn=baiduimage&ct=201326592&lm=-1&cl=2&ie=gbk&word=%C3%C0%C5%AE%CD%BC%C6%AC%B4%F3%CD%BC&fr=ala&ala=1&alatpl=cover&pos=0#z=0&pn=&ic=0&st=-1&face=0&s=0&lm=-1"]];
//加载网页
[self.ZSJ_WkwebView
loadRequest:Request_zsj];
}
break;
case 1:{
// 获取文件路径
NSString *resourcePath = [ [NSBundle
mainBundle] resourcePath];
NSString *filePath = [resourcePath
stringByAppendingPathComponent:@"test.html"];
NSString *htmlstring =[[NSString
alloc] initWithContentsOfFile:filePath
encoding:NSUTF8StringEncoding
error:nil];
[self.ZSJ_WkwebView
loadHTMLString:htmlstring baseURL:[NSURL
URLWithString:[[NSBundle
mainBundle] bundlePath]]];
}
break;
case 2:{
}
break;
case 3:{
}
break;
default:
break;
}
}
//这个是网页加载完成,导航的变化
-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
/*
主意:这个方法是当网页的内容全部显示(网页内的所有图片必须都正常显示)的时候调用(不是出现的时候就调用),,否则不显示,或则部分显示时这个方法就不调用。
*/
NSLog(@"加载完成调用");
// 获取加载网页的标题
NSLog(@"加载的标题:%@",self.ZSJ_WkwebView.title);
}
//开始加载
-(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
//开始加载的时候,让加载进度条显示
self.ProgressView.hidden =
NO;
NSLog(@"开始加载的时候调用。。");
NSLog(@"%lf",
self.ZSJ_WkwebView.estimatedProgress);
}
//内容返回时调用
-(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{
NSLog(@"当内容返回的时候调用");
NSLog(@"%lf",
self.ZSJ_WkwebView.estimatedProgress);
}
-(void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{
NSLog(@"这是服务器请求跳转的时候调用");
}
-(void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error{
// 内容加载失败时候调用
NSLog(@"这是加载失败时候调用");
NSLog(@"%@",error);
}
-(void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error{
NSLog(@"通过导航跳转失败的时候调用");
}
-(void)webViewDidClose:(WKWebView *)webView{
NSLog(@"网页关闭的时候调用");
}
-(void)webViewWebContentProcessDidTerminate:(WKWebView *)webView{
NSLog(@"%lf", webView.estimatedProgress);
}
-(void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo
*)frame completionHandler:(void (^)(void))completionHandler{
//
获取js 里面的提示
}
-(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo
*)frame completionHandler:(void (^)(BOOL))completionHandler{
// js
信息的交流
}
-(void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText
initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *
_Nullable))completionHandler{
// 交互。可输入的文本。
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString
*,id> *)change context:(void *)context{
// 首先,判断是哪个路径
if ([keyPath isEqualToString:@"estimatedProgress"]) {
//
判断是哪个对象
if (object ==
self.ZSJ_WkwebView) {
NSLog(@"进度信息:%lf",self.ZSJ_WkwebView.estimatedProgress);
if (self.ZSJ_WkwebView.estimatedProgress ==
1.0) {
//隐藏
self.ProgressView.hidden =
YES;
}else{
// 添加进度数值
self.ProgressView.progress =
self.ZSJ_WkwebView.estimatedProgress;
}
}
}
}
//注意,观察的移除
-(void)dealloc{
[self
removeObserver:self
forKeyPath:@"estimatedProgress"];
}
@end
三、效果图。
相关文章推荐
- iOS开发系列--并行开发其实很容易
- 【iOS】判断viewcontroller 来源(展示出来)的4个方法
- iOS - layoutSubviews、drawRect、awakeFromNib和 loadNibNamed解释
- iOS NavigationController 右滑手势问题
- 海康威视 DVR IPC, IOS系统的SDK包。用于二次开发
- iOS 中KVC、KVO、NSNotification、delegate 总结及区别
- iOS中的2x,3x问题
- iOS中的汉字转换成拼音
- speex编译静态库for iOS
- ios7之后导航栏状态栏小记
- 仿ios日期选择器
- iOS获取一个控件的子控件的方法
- iOS9 企业级账号 无法安装的问题
- iOS证书及ipa包重签名探究
- iOS 计算器
- iOS之H5和Native混合开发
- iOS开发实用技术之第三方登陆
- TableView的重用机制
- iOS仿滚动轮盘键盘
- ios...参数(不定参数)