UIWebView 操作
网络开发中,当公司已经使用 HTML5 技术实现同时适应 Android 和 iOS 等多个平台的网页时,这时往往需要我们 iOS 平台能够嵌入网页并进行各种交互,那我们应该怎么做来实现这种需求呢?
这里我们考虑的方案就是:使用 UIWebView 网页控件
然而考虑使用 UIWebView 进行混合编程的场景特点有:
(1)排版复杂:通常包括图片和文字的混排,还有可能包括链接需要支持点击操作。如果自己用原生控件拼装实现,由于界面元素过多,做起来会很困难。就算是使用 CoreText 来实现,也需要自己实现相当多的复杂排版逻辑。
(2)界面的变动需求频繁:例如淘宝 App 的彩票页面,可能常常需要更新界面以推出不同的活动。采用 UIWebView 嵌套页面实现后,这类页面不需要向 App Store 提交新的版本就可以动态地更新,而原生控件实现的界面很难达到如此高的灵活性。
(3)界面对用户的交互需求不复杂:因为 UIWebView 实现的交互效果与原生效果相比还是会大打折扣,所以这类界面通常都没有复杂的交互效果。这也是主流 App 大多采用混合 UIWebView 来实现界面而不是使用纯 UIWebView 来实现界面的原因之一,另外的原因是纯 UIWebView 实现的性能也没原生的好,而且纯 UIWebView 实现的话根本无法通过 App Store 的审核,他会建议您搞 Web App。
本随笔简单介绍如何使用 UIWebView 网页控件:
(1)简单浏览器
file://WhatsNewIniPhoneOS.pdf 读取本地资源文件
http://www.apple.com 读取网站内容
KenmuHuang 读取百度搜索网站相关查询内容
(2)页面交互;可以考虑使用模版引擎库 GRMustache:https://github.com/groue/GRMustache,方便阅读和更改渲染内容
(3)页面调用 OC 方法;可以考虑使用 JS 与 OC 交互库「WebViewJavascriptBridge」:https://github.com/marcuswestin/WebViewJavascriptBridge,方便 JS 与 OC 之间发送消息进行交互
效果如下:


ViewController.h
#import <UIKit/UIKit.h> @interface ViewController : UITableViewController
@property (copy, nonatomic) NSArray *arrSampleName; - (instancetype)initWithSampleNameArray:(NSArray *)arrSampleName; @end
ViewController.m
#import "ViewController.h"
#import "SimpleBrowserViewController.h"
#import "PageInteractionViewController.h"
#import "PageCallOCFunctionViewController.h" @interface ViewController ()
- (void)layoutUI;
@end @implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad]; [self layoutUI];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} - (instancetype)initWithSampleNameArray:(NSArray *)arrSampleName {
if (self = [super initWithStyle:UITableViewStyleGrouped]) {
self.navigationItem.title = @"UIWebView 操作";
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:nil action:nil]; _arrSampleName = arrSampleName;
}
return self;
} - (void)layoutUI { } #pragma mark - UITableViewController相关方法重写
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 0.1;
} - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return ;
} - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_arrSampleName count];
} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = _arrSampleName[indexPath.row];
return cell;
} - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
switch (indexPath.row) {
case : {
SimpleBrowserViewController *simpleBrowserVC = [SimpleBrowserViewController new];
[self.navigationController pushViewController:simpleBrowserVC animated:YES];
break;
}
case : {
PageInteractionViewController *pageInteractionVC = [PageInteractionViewController new];
[self.navigationController pushViewController:pageInteractionVC animated:YES];
break;
}
case : {
PageCallOCFunctionViewController *pageCallOCFunctionVC = [PageCallOCFunctionViewController new];
[self.navigationController pushViewController:pageCallOCFunctionVC animated:YES];
break;
}
default:
break;
}
} @end
PrefixHeader.pch
#define kTitleOfSimpleBrowser @"简单浏览器"
#define kTitleOfPageInteraction @"页面交互"
#define kTitleOfPageCallOCFunction @"页面调用 OC 方法" #define kApplication [UIApplication sharedApplication]
SimpleBrowserViewController.h
#import <UIKit/UIKit.h> @interface SimpleBrowserViewController : UIViewController <UISearchBarDelegate, UIWebViewDelegate>
@property (strong, nonatomic) UISearchBar *searchBar;
@property (strong, nonatomic) UIWebView *webView;
@property (strong, nonatomic) UIToolbar *toolbar;
@property (strong, nonatomic) UIBarButtonItem *barBtnBack;
@property (strong, nonatomic) UIBarButtonItem *barBtnForward; @end
SimpleBrowserViewController.m
#import "SimpleBrowserViewController.h" @interface SimpleBrowserViewController ()
- (void)webViewBack;
- (void)webViewForward;
- (void)layoutUI;
- (void)sendRequest:(NSString *)requestURLStr;
- (void)changeBarButtonStatus;
@end @implementation SimpleBrowserViewController - (void)viewDidLoad {
[super viewDidLoad]; [self layoutUI];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} - (void)webViewBack {
[_webView goBack];
} - (void)webViewForward {
[_webView goForward];
} - (void)layoutUI {
self.navigationItem.title = kTitleOfSimpleBrowser;
self.automaticallyAdjustsScrollViewInsets = NO; //是否自动适应滚动视图的内嵌入;默认为YES,这里设置为NO,避免网页控件中_UIWebViewScrollView的UIWebBrowserView位置偏移 CGRect rect = [[UIScreen mainScreen] bounds];
static const CGFloat heightOfStatusBarAndNavigationBar = 64.0;
CGFloat widthOfScreen = rect.size.width;
CGFloat heightOfScreen = rect.size.height; //添加搜索栏
_searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0, heightOfStatusBarAndNavigationBar, widthOfScreen, 44.0)];
_searchBar.delegate = self;
_searchBar.placeholder = @"请输入以file://或http开头的地址";
[self.view addSubview:_searchBar]; //添加工具栏和左右按钮(回退和前进)
_toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, heightOfScreen - 44.0,
widthOfScreen, 44.0)];
rect = CGRectMake(0.0, 0.0, 32.0, 32.0);
UIButton *btnBack = [UIButton buttonWithType:UIButtonTypeCustom];
btnBack.frame = rect;
[btnBack setImage:[UIImage imageNamed:@"LastPageNormal"] forState:UIControlStateNormal];
[btnBack setImage:[UIImage imageNamed:@"LastPageDisabled"] forState:UIControlStateDisabled];
[btnBack addTarget:self
action:@selector(webViewBack)
forControlEvents:UIControlEventTouchUpInside];
_barBtnBack = [[UIBarButtonItem alloc] initWithCustomView:btnBack];
_barBtnBack.enabled = NO; UIBarButtonItem *barBtnSpacing=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; UIButton *btnForward = [UIButton buttonWithType:UIButtonTypeCustom];
btnForward.frame = rect;
[btnForward setImage:[UIImage imageNamed:@"NextPageNormal"] forState:UIControlStateNormal];
[btnForward setImage:[UIImage imageNamed:@"NextPageDisabled"] forState:UIControlStateDisabled];
[btnForward addTarget:self
action:@selector(webViewForward)
forControlEvents:UIControlEventTouchUpInside];
_barBtnForward = [[UIBarButtonItem alloc] initWithCustomView:btnForward];
_barBtnForward.enabled = NO; _toolbar.items = @[ _barBtnBack, barBtnSpacing, _barBtnForward ];
[self.view addSubview:_toolbar]; //添加网页控件
CGFloat heightOfWebView = heightOfScreen - _searchBar.frame.origin.y - _searchBar.frame.size.height - _toolbar.frame.size.height;
_webView = [[UIWebView alloc] initWithFrame:CGRectMake(0.0, heightOfStatusBarAndNavigationBar + _searchBar.frame.size.height,
widthOfScreen, heightOfWebView)];
_webView.dataDetectorTypes = UIDataDetectorTypeAll;
_webView.delegate = self;
[self.view addSubview:_webView];
} - (void)sendRequest:(NSString *)requestURLStr {
if (requestURLStr.length > ) {
NSURL *requestURL; //加载bundle中的文件;网页控件打开本地pdf、word文件依靠的并不是他自身解析,而是依靠MIME Type识别文件类型并调用对应应用打开
if ([requestURLStr hasPrefix:@"file://"]) {
NSRange range = [requestURLStr rangeOfString:@"file://"];
NSString *fileName = [requestURLStr substringFromIndex:range.length];
requestURL = [[NSBundle mainBundle] URLForResource:fileName
withExtension:nil];
} else {
//加载百度搜索网站的内容
if (![requestURLStr hasPrefix:@"http"]) {
requestURLStr = [NSString stringWithFormat:@"https://www.baidu.com/s?wd=%@", requestURLStr];
}
//最终加载的还是HTTP或者HTTPS协议的网站内容,进行编码操作
requestURLStr = [requestURLStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
requestURL = [NSURL URLWithString:requestURLStr];
} //加载请求地址内容
[_webView loadRequest:[NSURLRequest requestWithURL:requestURL]];
}
} - (void)changeBarButtonStatus {
_barBtnBack.enabled = _webView.canGoBack;
_barBtnForward.enabled = _webView.canGoForward;
} #pragma mark - UIWebViewDelegate
- (void)webViewDidStartLoad:(UIWebView *)webView {
kApplication.networkActivityIndicatorVisible = YES;
} - (void)webViewDidFinishLoad:(UIWebView *)webView {
kApplication.networkActivityIndicatorVisible = NO;
[self changeBarButtonStatus];
} - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
NSLog(@"Error: %@", error);
kApplication.networkActivityIndicatorVisible = NO;
UIAlertView *alertVCustom = [[UIAlertView alloc] initWithTitle:@"提示信息"
message:@"网络连接错误"
delegate:nil
cancelButtonTitle:@"确定"
otherButtonTitles:nil, nil];
[alertVCustom show];
} #pragma mark - UISearchBarDelegate
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[self sendRequest:searchBar.text];
[_searchBar resignFirstResponder];
} @end
PageInteractionViewController.h
#import <UIKit/UIKit.h> @interface PageInteractionViewController : UIViewController<UIWebViewDelegate>
@property (strong, nonatomic) UIWebView *webView; @end
PageInteractionViewController.m
#import "PageInteractionViewController.h" @interface PageInteractionViewController ()
- (void)layoutUI;
- (void)sendRequest;
@end @implementation PageInteractionViewController - (void)viewDidLoad {
[super viewDidLoad]; [self layoutUI]; [self sendRequest];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} - (void)layoutUI {
self.navigationItem.title = kTitleOfPageInteraction;
self.automaticallyAdjustsScrollViewInsets = NO; //是否自动适应滚动视图的内嵌入;默认为YES,这里设置为NO,避免网页控件中_UIWebViewScrollView的UIWebBrowserView位置偏移 CGRect rect = [[UIScreen mainScreen] bounds];
static const CGFloat heightOfStatusBarAndNavigationBar = 64.0;
//添加网页控件
_webView = [[UIWebView alloc] initWithFrame:CGRectMake(0.0, heightOfStatusBarAndNavigationBar,
rect.size.width, rect.size.height - heightOfStatusBarAndNavigationBar)];
_webView.dataDetectorTypes = UIDataDetectorTypeAll;
_webView.delegate = self;
self.automaticallyAdjustsScrollViewInsets = NO;
[self.view addSubview:_webView];
} - (void)sendRequest {
NSString *htmlStr=@"<html>\
<head><title>KenmuHuang's Blog</title></head>\
<body style=\"color:#0044AA;\">\
<h3 id=\"header\">I'm KenmuHuang</h3>\
<p>More coding, more thinking. Stay hungry, stay foolish.</p>\
<span>http://www.cnblogs.com/huangjianwu/</span>\
</body>\
</html>";
[_webView loadHTMLString:htmlStr baseURL:nil];
} #pragma mark - UIWebViewDelegate
- (void)webViewDidStartLoad:(UIWebView *)webView {
kApplication.networkActivityIndicatorVisible = YES;
} - (void)webViewDidFinishLoad:(UIWebView *)webView {
kApplication.networkActivityIndicatorVisible = NO;
NSLog(@"%@",[_webView stringByEvaluatingJavaScriptFromString:@"document.title"]); //打印内容为html的title标签内容:KenmuHuang's Blog
NSLog(@"%@",[_webView stringByEvaluatingJavaScriptFromString:@"document.getElementById('header').innerHTML='KenmuHuang\\'s Blog';"]); //必须使用双反斜杆来转译单引号
} - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
NSLog(@"Error: %@", error);
kApplication.networkActivityIndicatorVisible = NO;
UIAlertView *alertVCustom = [[UIAlertView alloc] initWithTitle:@"提示信息"
message:@"网络连接错误"
delegate:nil
cancelButtonTitle:@"确定"
otherButtonTitles:nil, nil];
[alertVCustom show];
} @end
RedirectURL.js
function showSheet(title, cancelButtonTitle, destructiveButtonTitle, otherButtonTitle) {
var url = 'KMActionSheet://?';
var paramas = title + '&' + cancelButtonTitle + '&' + destructiveButtonTitle;
if(otherButtonTitle) {
paramas += '&' + otherButtonTitle;
}
window.location.href = url + encodeURIComponent(paramas);
}
var header = document.getElementById('header');
if(header) {
header.onclick = function(){
showSheet('系统提示', '取消', '确定', null);
};
}
PageCallOCFunctionViewController.h
#import <UIKit/UIKit.h> @interface PageCallOCFunctionViewController : UIViewController<UIWebViewDelegate>
@property (strong, nonatomic) UIWebView *webView; @end
PageCallOCFunctionViewController.m
#import "PageCallOCFunctionViewController.h" @interface PageCallOCFunctionViewController ()
- (void)layoutUI;
- (void)sendRequest;
- (void)showActionSheetWithTitle:(NSString *)title cancelButtonTitle:(NSString *)cancelButtonTitle destructiveButtonTitle:(NSString *)destructiveButtonTitle otherButtonTitle:(NSString *)otherButtonTitle;
@end @implementation PageCallOCFunctionViewController - (void)viewDidLoad {
[super viewDidLoad]; [self layoutUI]; [self sendRequest];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} - (void)layoutUI {
self.navigationItem.title = kTitleOfPageCallOCFunction;
self.automaticallyAdjustsScrollViewInsets = NO; //是否自动适应滚动视图的内嵌入;默认为YES,这里设置为NO,避免网页控件中_UIWebViewScrollView的UIWebBrowserView位置偏移 CGRect rect = [[UIScreen mainScreen] bounds];
static const CGFloat heightOfStatusBarAndNavigationBar = 64.0;
//添加网页控件
_webView = [[UIWebView alloc] initWithFrame:CGRectMake(0.0, heightOfStatusBarAndNavigationBar,
rect.size.width, rect.size.height - heightOfStatusBarAndNavigationBar)];
_webView.dataDetectorTypes = UIDataDetectorTypeAll;
_webView.delegate = self;
self.automaticallyAdjustsScrollViewInsets = NO;
[self.view addSubview:_webView];
} - (void)sendRequest {
NSString *htmlStr=@"<html>\
<head><title>KenmuHuang's Blog</title></head>\
<body style=\"color:#0044AA;\">\
<h3 id=\"header\">I'm KenmuHuang, click me to show action sheet.</h3>\
<p>More coding, more thinking. Stay hungry, stay foolish.</p>\
<span>http://www.cnblogs.com/huangjianwu/</span>\
</body>\
</html>";
[_webView loadHTMLString:htmlStr baseURL:nil];
} - (void)showActionSheetWithTitle:(NSString *)title cancelButtonTitle:(NSString *)cancelButtonTitle destructiveButtonTitle:(NSString *)destructiveButtonTitle otherButtonTitle:(NSString *)otherButtonTitle{
UIActionSheet *actionSheet=[[UIActionSheet alloc] initWithTitle:title
delegate:nil
cancelButtonTitle:cancelButtonTitle
destructiveButtonTitle:destructiveButtonTitle
otherButtonTitles:otherButtonTitle, nil];
[actionSheet showInView:self.view];
} #pragma mark - UIWebViewDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
BOOL isStartLoad = YES;
if ([request.URL.scheme isEqualToString:@"kmactionsheet"]) { //request.URL.scheme 返回全小写的内容
NSString *paramContent = request.URL.query;
NSArray *arrParam = [[paramContent stringByRemovingPercentEncoding] componentsSeparatedByString:@"&"];
NSString *otherButtonTitle = nil;
if (arrParam.count > ) {
otherButtonTitle = arrParam[];
} [self showActionSheetWithTitle:arrParam[]
cancelButtonTitle:arrParam[]
destructiveButtonTitle:arrParam[]
otherButtonTitle:otherButtonTitle];
isStartLoad = NO;
}
return isStartLoad;
} - (void)webViewDidStartLoad:(UIWebView *)webView {
kApplication.networkActivityIndicatorVisible = YES;
} - (void)webViewDidFinishLoad:(UIWebView *)webView {
kApplication.networkActivityIndicatorVisible = NO; //加载用于重定向地址的JavaScript内容
NSString *jsPath = [[NSBundle mainBundle] pathForResource:@"RedirectURL.js" ofType:nil];
NSString *jsContent = [NSString stringWithContentsOfFile:jsPath
encoding:NSUTF8StringEncoding
error:nil];
[_webView stringByEvaluatingJavaScriptFromString:jsContent];
} - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
NSLog(@"Error: %@", error);
kApplication.networkActivityIndicatorVisible = NO;
UIAlertView *alertVCustom = [[UIAlertView alloc] initWithTitle:@"提示信息"
message:@"网络连接错误"
delegate:nil
cancelButtonTitle:@"确定"
otherButtonTitles:nil, nil];
[alertVCustom show];
} @end
AppDelegate.h
#import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) UINavigationController *navigationController; @end
AppDelegate.m
#import "AppDelegate.h"
#import "ViewController.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
ViewController *viewController = [[ViewController alloc]
initWithSampleNameArray:@[ kTitleOfSimpleBrowser,
kTitleOfPageInteraction,
kTitleOfPageCallOCFunction ]];
_navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
_window.rootViewController = _navigationController;
//[_window addSubview:_navigationController.view]; //当_window.rootViewController关联时,这一句可有可无
[_window makeKeyAndVisible];
return YES;
} - (void)applicationWillResignActive:(UIApplication *)application {
} - (void)applicationDidEnterBackground:(UIApplication *)application {
} - (void)applicationWillEnterForeground:(UIApplication *)application {
} - (void)applicationDidBecomeActive:(UIApplication *)application {
} - (void)applicationWillTerminate:(UIApplication *)application {
} @end
UIWebView 操作的更多相关文章
- 【IOS 开发】基本 UI 控件详解 (UIDatePicker | UIPickerView | UIStepper | UIWebView | UIToolBar )
转载注明出处 : http://blog.csdn.net/shulianghan/article/details/50348982 一. 日期选择器 (UIDatePicker) UIDatePic ...
- [Xcode 实际操作]四、常用控件-(13)使用UIWebView控件加载网页
目录:[Swift]Xcode实际操作 本文将演示网页视图的使用. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UIKit class ViewC ...
- [Xcode 实际操作]四、常用控件-(14)使用UIWebView控件加载本地HTML
目录:[Swift]Xcode实际操作 本文将演示使用网页视图,加载并渲染网页代码. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UIKit im ...
- iOS网络3—UIWebView与WKWebView使用详解
一.整体介绍 UIWebView自iOS2就有,WKWebView从iOS8才有,毫无疑问WKWebView将逐步取代笨重的UIWebView.通过简单的测试即可发现UIWebView占用过多内存,且 ...
- UIwebView 和 H5交互详情
背景: 最近公司准备上一个只有原生登录界面 + H5网页 ,并且支持ios7.0 以上系统的混合app;这可把我难住了,原生的UI界面我可以正写反写各种style把界面搭建起来.而要这个app的难点在 ...
- IOS 错误 [UIWebView cut:]: unrecognized selector sent to instance
那在什么场景中会出现这种情况呢? 如果一个包含文字的输入元素有焦点,然后按钮的点击会导致输入失去焦点,然后接下来在输入时双按会重新得到焦点并从弹出bar中选择剪切复制粘贴,就会导致此error. 也就 ...
- UIWebView的使用
iOS中UIWebView的使用详解 一.初始化与三种加载方式 UIWebView继承与UIView,因此,其初始化方法和一般的view一样,通过alloc和init进行初始化,其加载数据的方式有三种 ...
- (转)UIWebView全部API学习
网上找的收藏一下 http://www.myexception.cn/web/1888974.html 最生僻的API做了下划线以及粗体的标注.百度上查了全是拷贝的同一份代码,而且只有代码没有解释,很 ...
- cell嵌套UIWebView遇到的几个问题
一.防止死循环问题 方法一:使用动画块 [self.myTableView beginUpdates];[self.myTableView endUpdates]; 在下面的代 ...
随机推荐
- Android开发学习总结(六)—— APK反编译
学习和开发Android应用有一段时间了,今天写一篇博客总结一下Android的apk文件反编译.我们知道,Android应用开发完成之后,我们最终都会将应用打包成一个apk文件,然后让用户通过手机或 ...
- ueditor样式过滤问题
1.4.3版本样式过滤处理如下: if (domUtils.isEmptyNode(me.body)) { //alert("xx"); //me.body.inner ...
- HTML5 ——本地存储
目录 一.HTML4客户端存储 1.1.提交表单发送到服务器的信息 1.2.客户端本地存储概要 二.localStorage 2.1.添加 2.2.取值 2.3.修改 2.4.删除 2.5.跨页面与跨 ...
- atitit.导航的实现最佳实践and声明式编程
atitit.导航的实现最佳实践and声明式编程 1. 顶部水平栏导航 1 2. 竖直/侧边栏导航 1 3. 选项卡导航 1 4. 面包屑导航 1 5. 标签导航 1 6. 搜索导航 2 7. 分面/ ...
- Python框架之Tornado(四)源码之褪去模板外衣
上一篇介绍了客户端请求在tornado框架中的生命周期,其本质就是利用epoll和socket来获取并处理请求.在上一篇的内容中,我们只是给客户端返回了简单的字符串,如:“Hello World”,而 ...
- 出现Bad command or the file name的原因
出现Bad command or file name的原因 中文释义:错误的命令或文件名 . 错误原因:不能识别输入的命令 . 方法:检查所输入的指令是否正确,包括拼写和大小写等情况.
- android: SQLite使用 SQL 操作数据库
虽然 Android 已经给我们提供了很多非常方便的 API 用于操作数据库,不过总会有一些 人不习惯去使用这些辅助性的方法,而是更加青睐于直接使用 SQL 来操作数据库.这种人 一般都是属于 SQL ...
- C#中的串口通信
关于串行接口 串行接口(Serial port)又称“串口”,主要用于串行式逐位数据传输.常见的有一般电脑应用的RS-232(使用 25 针或 9 针连接器)和工业电脑应用的半双工RS-485与全双工 ...
- Andorid--java0
java code: public class Hello{ public static void main(String argv[]) { System.out.printl ...
- 诚聘:全栈开发人员,三线城市10-16K
北京快鸽联盟信息技术有限公司成立于2013年,专注于校园及社区快递和增值服务.目前已有十余家各地分部,并与上百所大学,各大快递和电商公司有密切合作,年处理快件量超千万,长期处于行业领先地位. 诚聘全栈 ...