【iOS - 周总结】开发中遇到的小知识点(2018.12.03-2018.12.08)
补充:本文也是拖迟一周才更新的。也是由于项目原因。
时间:2018.12.03-2018.12.08
1.在主线程操作UI
在开发中我们一般只在主线程操作UI,但是在一些方法中我们会调用一下UI处理。这时候就会报出一些错误警告等。
1. UI API called from background thread Group
在本周开发中我就遇到这个问题,在一个异步网络请求中,刷新UI结果报警告。解决方法如下:
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView.mj_header endRefreshing];
[self.tableView reloadData];
});
之前我也遇到过这个问题,就是在开启指纹解锁后,根据结果来控制是否打开指纹解锁开关。也是这样解决的。
2.在带有tabbar的APP中打开子界面返回时tabbar图片位置上移。
如上所述,在一个带有tabbar的APP中,打开子界面,子界面不含有tabbar,在从子界面返回时,有时候会发现tabbar上的item的图片上移,有的还会超出tabbar范围。这个问题很好解决。
[[UITabBar appearance] setTranslucent:NO];
只要设置上上面这行代码就可以。但是有时候不设置也可以。有点迷。如果你出现了这个问题就可以设置试试。
3.WKWebView的使用。
WKWebView是iOS8之后推出的一个类。在本周我是打算写一个通用web页。由于项目基于iOS9之后开发,就使用了WKWebView。直接附上代码。代码里有注释。
#import "CustomWebViewController.h"
#import <WebKit/WebKit.h>
#import <JavaScriptCore/JavaScriptCore.h> @interface CustomWebViewController ()<WKNavigationDelegate, WKUIDelegate, WKScriptMessageHandler> @property (nonatomic, strong) WKWebView *webview; @end @implementation CustomWebViewController - (void)viewDidLoad {
[super viewDidLoad]; } #pragma mark - Base Action//初始化视图
- (void)initContentView {
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init]; configuration.preferences = [WKPreferences new];
configuration.userContentController = [WKUserContentController new]; /*
// 需要将被js调用的方法注册进去
[configuration.userContentController addScriptMessageHandler:self name:@"selectWayPay"];
[configuration.userContentController addScriptMessageHandler:self name:@"ios_logIn"];
*/ self.webview = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];
self.webview.navigationDelegate = self;
self.webview.UIDelegate = self;
[self.view addSubview:self.webview]; if (!WCYIsEmpty(self.urlStr)) {
NSURL *url = [NSURL URLWithString:self.urlStr];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60]; [self.webview loadRequest:request];
}
} #pragma mark - 设置标题
- (void)setWebTitle {
self.navigationItem.title = self.webview.title;
} #pragma mark - 页面消失 清除缓存
- (void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
[self deleteWebCache];
} - (void)deleteWebCache {
NSSet *websiteDataTypes = [NSSet setWithArray:@[WKWebsiteDataTypeDiskCache,WKWebsiteDataTypeMemoryCache]];
NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0];
[[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^{
}];
} #pragma mark - WKScriptMessageHandler
//WKScriptMessageHandler协议方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
// 收到 js的交互
// 需要在 configuration生成是注册 这种方法message.body必填
} #pragma mark - WKUIDelegate
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
// js 里面的alert实现,如果不实现,网页的alert函数无效 } - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {
// js 里面的alert实现,如果不实现,网页的alert函数无效 ,
} #pragma mark - WKNavigationDelegate /*
1 在请求发送之前,决定是否跳转
2 页面开始加载时调用
3 在收到响应后,决定是否跳转
4 内容开始加载时调用
5 接收到服务器跳转请求之后调用(不一定调用该方法)
5 页面加载完成时调用
6 请求失败时调用
*/ // 在请求发送之前,决定是否跳转 -> 该方法如果不实现,系统默认跳转。如果实现该方法,则需要设置允许跳转,不设置则报错。
// decisionHandler(WKNavigationActionPolicyAllow);
// 该方法执行在加载界面之前
// Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Completion handler passed to -[ViewController webView:decidePolicyForNavigationAction:decisionHandler:] was not called' - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { /*
//允许跳转
decisionHandler(WKNavigationActionPolicyAllow); //不允许跳转
// decisionHandler(WKNavigationActionPolicyCancel);
NSLog(@"在请求发送之前,决定是否跳转。 1");
*/ NSURL *URL = navigationAction.request.URL;
NSString *scheme = [URL scheme];
UIApplication *app = [UIApplication sharedApplication]; // 打电话
if ([scheme isEqualToString:@"tel"]) {
if ([app canOpenURL:URL]) {
[app openURL:URL];
// 一定要加上这句,否则会打开新页面
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}
} // 页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
NSLog(@"页面开始加载时调用。 2");
} // 页面加载完成时调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
[self setWebTitle];
NSLog(@"页面加载完成时调用。 5");
} // 请求失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {
NSLog(@"error1:%@",error);
} -(void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {
NSLog(@"error2:%@",error);
} //内容返回时调用,得到请求内容时调用(内容开始加载) -> view的过渡动画可在此方法中加载
- (void)webView:(WKWebView *)webView didCommitNavigation:( WKNavigation *)navigation {
NSLog(@"内容返回时调用,得到请求内容时调用。 4");
} // 在收到响应后,决定是否跳转(同上)
// 该方法执行在内容返回之前
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
//允许跳转
decisionHandler(WKNavigationResponsePolicyAllow);
//不允许跳转
// decisionHandler(WKNavigationResponsePolicyCancel);
NSLog(@"在收到响应后,决定是否跳转。 3"); } // 接收到服务器跳转请求之后调用
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation {
NSLog(@"接收到服务器跳转请求之后调用 不一定有");
} -(void)webViewWebContentProcessDidTerminate:(WKWebView *)webView {
NSLog(@"webViewWebContentProcessDidTerminate");
}@end
参考文档:博客一
4.设置tableview 索引
直接上代码
#import "SelectCityViewController.h" @interface SelectCityViewController ()<UITableViewDelegate,UITableViewDataSource>@property (nonatomic, strong) UITableView *tableView; @property (nonatomic, strong) NSMutableArray *indexArray; // index 数组
@property (nonatomic, strong) NSMutableDictionary *dataDic; @end @implementation SelectCityViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
} #pragma mark - Base Action
//初始化数据
- (void)initContentData {
self.indexArray = [NSMutableArray array];
self.dataDic = [NSMutableDictionary dictionary];
} //初始化视图
- (void)initContentView {
[self changeNavi]; [self.view addSubview:self.tableView]; [self configTable]; } - (void)changeNavi {
self.title = @"选择";
} #pragma mark - 加载 刷新
- (void)configTable { CFRefreshGifHeader *mj_header = [CFRefreshGifHeader headerWithRefreshingBlock:^{ [self loadNewData];
}]; mj_header.mj_h = 80;
self.tableView.mj_header = mj_header; [self.tableView.mj_header beginRefreshing];
} - (void)loadNewData {
[WCYNetWorking getWithUrl:@"链接" refreshCache:YES success:^(id response) {
// 刷新 清除之前数据
[self.dataDic removeAllObjects];
[self.indexArray removeAllObjects]; NSArray *array = [CityListModel mj_objectArrayWithKeyValuesArray:response]; for (CityListModel *city in array) {
NSString *firstChar = [self firstCharactor:city.name];
if ([self.dataDic containsObjectForKey:firstChar]) {
// 包含
NSMutableArray *array = [NSMutableArray arrayWithArray:[self.dataDic objectForKey:firstChar]];
[array addObject:city];
[self.dataDic setObject:array forKey:firstChar];
} else {
// 不包含
NSArray *array = @[city];
[self.dataDic setObject:array forKey:firstChar];
}
} self.indexArray = [NSMutableArray arrayWithArray:[[self.dataDic allKeys] sortedArrayUsingSelector:@selector(compare:)]]; [self.tableView reloadData]; [self.tableView.mj_header endRefreshing]; } fail:^(NSError *error) {
[self.view makeToast:[error.userInfo objectForKey:@"NSLocalizedDescription"]];
[self.tableView.mj_footer endRefreshing];
}];
} #pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.indexArray.count;
} - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSArray *array = [self.dataDic objectForKey:self.indexArray[section]];
return array.count;
} - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return AdaptedWidth(45);
} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:GET_CLASS_NAME(UITableViewCell)];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:GET_CLASS_NAME(UITableViewCell)];
} NSArray *array = [self.dataDic objectForKey:self.indexArray[indexPath.section]];
CityListModel *model = array[indexPath.row];
cell.textLabel.text = model.name;
cell.textLabel.textColor = [UIColor colorWithHexString:@"081E3C"];
cell.textLabel.font = AdaptedFontSize(14);
return cell;
} // 索引
- (NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return self.indexArray;
} - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return index;
} #pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
} #pragma mark - Lazy Setter- (UITableView *)tableView {
if (!_tableView) {
_tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, SCREENT_WIDTH, SCREENT_HEIGHT - TopNavHeight) style:UITableViewStylePlain];
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
_tableView.sectionHeaderHeight = 0.001;
_tableView.sectionFooterHeight = 0.001;
_tableView.backgroundColor = VIEW_BACKGROUNDCOLOR;
_tableView.tableHeaderView = self.tableHead; // //修改右边索引的背景色
// _tableView.sectionIndexBackgroundColor = [UIColor greenColor];
//修改右边索引字体的颜色
_tableView.sectionIndexColor = [UIColor colorWithHexString:@"081E3C"];
// //修改右边索引点击时候的背景色
// _tableView.sectionIndexTrackingBackgroundColor = [UIColor orangeColor]; }
return _tableView;
} #pragma mark - 右侧索引所需方法
- (NSString *)firstCharactor:(NSString *)aString{
//转成了可变字符串
NSMutableString *str = [NSMutableString stringWithString:aString];
//先转换为带声调的拼音
CFStringTransform((CFMutableStringRef)str,NULL, kCFStringTransformMandarinLatin,NO);
//再转换为不带声调的拼音
CFStringTransform((CFMutableStringRef)str,NULL, kCFStringTransformStripDiacritics,NO);
//转化为大写拼音
NSString *pinYin = [str capitalizedString];
//获取并返回首字母
return [pinYin substringToIndex:1];
} @end
上面代码还是比较简单的就是需要注意在获取数据后对数据的处理。
5.xcode10如何reset模拟器
如上所述,在之前的xcode中我们在模拟器用多了有了很多APP后,会点击reset来重置模拟器。可是在xcode10中没有这一选项。那么该如何重置呢?

【iOS - 周总结】开发中遇到的小知识点(2018.12.03-2018.12.08)的更多相关文章
- iOS开发中关于UIImage的知识点总结
UIImage是iOS中层级比较高的一个用来加载和绘制图像的一个类,更底层的类还有 CGImage,以及iOS5.0以后新增加的CIImage.今天我们主要聊一聊UIImage的三个属性: image ...
- Android开发中实现桌面小部件
详细信息请参考原文:Android开发中实现桌面小部件 在Android开发中,有时候我们的App设计的功能比较多的时候,需要根据需要更简洁的为用户提供清晰已用的某些功能的时候,用桌面小部件就是一个很 ...
- Hybrid App 应用开发中 9 个必备知识点复习(WebView / 调试 等)
前言 我们大前端团队内部 ?每周一练 的知识复习计划继续加油,本篇文章是 <Hybrid APP 混合应用专题> 主题的第二期和第三期的合集. 这一期共整理了 10 个问题,和相应的参考答 ...
- JAVA开发中遇到的小白点
这里主要是自己个人开发中遇到的一些小问题,自己攒起来,来弥补自己薄弱的JAVA基础,大神不要见笑 1. DateFormat格式化的HH和hh区别: public static boolean com ...
- iOS静态库开发中对Bitcode的支持
1.bitcode bitcode是LLVM编译器将C/C++/OC/Swift等前端变成语言编译成多种不同芯片上的机器指令过程中的中间代码.并且这个中间代码是CPU无关的. 原本我们的APP里要包含 ...
- Hybird App 应用开发中5个必备知识点复习
前言 我们大前端团队内部 ?每周一练 的知识复习计划还在继续,本周主题是 <Hybird APP 混合应用专题> ,这期内容比较多,篇幅也相对较长,每个知识点内容也比较多. 之前分享的每周 ...
- 【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习
前言 我们大前端团队内部 ?每周一练 的知识复习计划还在继续,本周主题是 <Hybird APP 混合应用专题> ,这期内容比较多,篇幅也相对较长,每个知识点内容也比较多. 之前分享的每周 ...
- easyui中的combobox小知识点~~
一直使用的easyui中,一些不为人知的小知识点,与君共勉: 1.combobox设置高度:使用panelHeight属性: 2.combobox本身自带“自动补全”功能,但是在浏览器中是有限制的,在 ...
- C#、Java中的一些小知识点总结(持续更新......)
前言:在项目中,有时候一些小的知识,总是容易让人忽略,但是这些功能加在项目中往往十分的有用,因此笔者在这里总结项目中遇到的一些实用的小知识点,以备用,并持续更新...... 1.禁用DataGridV ...
- 开发中常用的JS知识点集锦
索引 1.对象深拷贝 2.网络图片转base64, 在线图片点击下载 3.常用CSS样式记录(超出宽高省略展示/播放icon/按钮背景颜色渐变...) 4.对象深拷贝 5.对象深拷贝 6.对象深拷贝 ...
随机推荐
- Server-sent-events与 WebSocket的区别是什么?
SSE 与 WebSocket 作用相似,都是建立浏览器与服务器之间的通信渠道,然后服务器向浏览器推送信息.总体来说,WebSocket更强大和灵活.因为它是全双工通道,可以双向通信:SSE是单向通道 ...
- 前端ast
什么是抽象语法树 抽象语法树 Abstract Syntax Tree 简称AST,是源代码语法结构的一种抽象表示. 比如 const a = 123; ,用ast可以表示为 ast json表示为 ...
- 斐讯n1刷openWrt
恩山论坛 如果你想搞路由器,那去这个不得不提的恩山论坛就对了. 混软路由圈的人都知道f大(flippy). 他制作的镜像传播甚是广泛. 翻阅他的留下的文档或这里可知,大佬的镜像最后一版是2023年放出 ...
- CF2092F Andryusha and CCB 题解
CF2092F Andryusha and CCB CF 官解感觉跳了很多步啊,自己写一篇造福后人. 首先肯定是不能直接求的,考虑转化贡献体.对划分的段数转化贡献依旧不好求,考虑对每个子串的美感度转化 ...
- centos如何部署vue项目
centos如何部署vue项目 前言 最近做了一个AI应用,通过大模型可以生成图片.并合成适视频,也有一点有趣. 后端是基于fastapi的,前端是vue. 但是在部署vue的是时候,有点犯难. 职业 ...
- 前端开发系列129-进阶篇之Throttle And Debounce
本文讨论前端开发中 函数防抖 和 函数节流,它们的应用.区别以及简单实现. 在前端开发中我们可能经常需要给(页面)标签绑定一些持续触发的事件,如 resize.scroll.input.mousemo ...
- 使用IntelliJ IDEA 配置Maven项目
今天准备写个Java Web项目,决定用新安装的IntelliJ IDEA来试试,毕竟听别人说这个IDEA管理Maven项目比Eclipse方便,于是乎在网上找到了一篇超级有用的入门级配置教程,接下来 ...
- 模拟退火解 深圳杯2020C题
简介 下面链接有赛题和数据 http://www.m2ct.org/view-page.jsp?editId=12&uri=0D00233&gobackUrl=modular-list ...
- ETL数据集成丨建设BI的关键前提是ETL数据集成?
背景 很多企业都购买了商业智能(BI)来加速数字化转型,但是发现仅仅依赖BI效果往往不太好.虽然通过BI,企业能够快速分析和可视化数据,然而,BI并不是一个万能工具,它虽然能帮助企业解读数据,但其有效 ...
- SciTech-Mathematics-Probability+Statistics-Statistical Proofs-[THREE types of Probability]{Subjective:Choices/Decisions/Conclusions, Theoretical, Empirical}
Links Bayes, Empirical Bayes and Moderated Methods Empirical and theoretical prior distribution | Th ...