项目源码下载地址:

  https://github.com/ShayneYeorg/Meditashayne

1、首先一开始设计这个App的时候,我就希望它能比系统自带的备忘录更方便:比如备忘录需要手动去点击一下保存,我希望我的App可以省略掉点击保存这一步,只需要退出随笔的详情页面便可自动保存内容。

  那么退出详情页面有两种方式:左上角的“返回”以及UIViewController自带的左划退出。

  (1)、在处理完“返回”按钮之后,发现了第一个问题:自定义NavigationController上的BarButtonItem后,UIViewController自带的左划手势失效了。

  最后处理方法是在MDSNavigationController(自定义的NavigationController)里增加以下方法,并在viewDidLoad中调用,左划手势重新生效:

  (2)、考虑到刚进入随笔详情页面的时候,页面里还未有内容,这时就不应该存储没有内容的随笔,即是不能允许使用“返回”按钮或左划返回上一页面。

  然后使用了以下方法来灵活地开启或关闭当前控制器的左划功能

  (3)、然后发现把退出和保存两个功能捆绑在一起这种处理方式存在问题:

  如果我是不小心点到“新建”按钮进入新建随笔详情页面的,那么根据(2)我需要填写点内容才能退出,而退出的时候我填写的这些内容会被自动保存,可是我一开始是误点进来的,我并不想保存任何内容的,这就出现了矛盾。

  或者当我点击某篇随笔进入编辑随笔详情页面并做了改动之后,如果我想放弃这些改动,我发现此时就找不到方法来放弃了,直接退出会把我所做的改动保存起来,这也是一样的矛盾。

  即是说,当把退出和保存两个功能捆绑在一起之后,App便丧失了“退出但不保存”的功能。虽然可以通过退出的时候弹框提示是否要保存来处理,但是这样的话就会使得退出操作更繁琐,与设计这个功能时为了操作更简便的初衷相违背了。

  基于以上考虑,最终去除了“退出同时保存”的功能,使用了在NavigationController上的按钮来进行保存。

2、关于上拉加载更多控件,这个控件仿写公司项目使用的上拉加载更多控件的,使用的时候需要注意:在ScrollView或者TableView有数据之后,即是有了contentSize.height之后,需要再去调用一下控件的setState方法(直接或间接调用),方能让控件显示正确的状态。

3、在随笔列表页面,我希望App能全量展示所有的随笔内容,不希望点击某一条随笔进入随笔详情才看到所有内容。那么cell的高度便是不固定的了,需要用到动态高度的cell。

  (1)、为cell定义一个属性article,用来存放随笔模型,然后在setArticle方法内,使用以下方法来动态计算cell的高度,其中contentView是显示内容的TextView:

  之所以高度要加1是为了给下分割线空出空间。

  这个功能的参考文档:http://www.cocoachina.com/industry/20140604/8668.html

  (2)、然后发现,虽然cell能动态计算高度了,但是计算只是依据随笔内容的段落数。即是如果随笔内容是两段,而每一段文字的长度都超过了屏幕的宽度,那么cell计算出来的内容高度只是两行的高度。因为systemLayoutSizeFittingSize:方法并不知道TextView的宽度,也就无法知道在哪里需要换行。于是将计算cell高度的代码修改如下:

4、在进行3(2)的操作时,约束也要相应配合更改。我一开始给UITextView添加了宽度约束后,忘了将UITextView与右边的边距约束去掉,导致执行时出现了以下约束冲突的错误

2016-02-21 15:21:03.443 Meditashayne[4685:225763] Unable to simultaneously satisfy constraints.

                  Probably at least one of the constraints in the following list is one you don't want.

                  Try this:

                                    (1) look at each constraint and try to figure out which you don't expect;

                                    (2) find the code that added the unwanted constraint or constraints and fix it.

                  (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)

(

    "<NSAutoresizingMaskLayoutConstraint:0x7fbf4b5b5ec0 h=-&- v=-&- MDSSearchView:0x7fbf4b5ec510.width == UIView:0x7fbf4b41cd10.width>",

    "<NSLayoutConstraint:0x7fbf4b5ee5a0 H:[UITextField:0x7fbf4b5ed780(264)]>",

    "<NSLayoutConstraint:0x7fbf4b5f1490 H:|-(8)-[UITextField:0x7fbf4b5ed780]   (Names: '|':UIView:0x7fbf4b5ed610 )>",

    "<NSLayoutConstraint:0x7fbf4b5f14e0 H:[UITextField:0x7fbf4b5ed780]-(8)-|   (Names: '|':UIView:0x7fbf4b5ed610 )>",

    "<NSLayoutConstraint:0x7fbf4b5cdb40 H:[UIView:0x7fbf4b5ed610]-(20)-|   (Names: '|':UIView:0x7fbf4b5ed4a0 )>",

    "<NSLayoutConstraint:0x7fbf4b5a62a0 H:|-(20)-[UIView:0x7fbf4b5ed610]   (Names: '|':UIView:0x7fbf4b5ed4a0 )>",

    "<NSLayoutConstraint:0x7fbf4b5fa280 H:[UIView:0x7fbf4b5ed4a0]-(0)-|   (Names: '|':MDSSearchView:0x7fbf4b5ec510 )>",

    "<NSLayoutConstraint:0x7fbf4b5ed140 H:|-(0)-[UIView:0x7fbf4b5ed4a0]   (Names: '|':MDSSearchView:0x7fbf4b5ec510 )>",

    "<NSLayoutConstraint:0x7fbf4b616a70 'UIView-Encapsulated-Layout-Width' H:[UIView:0x7fbf4b41cd10(375)]>"

)

Will attempt to recover by breaking constraint

<NSLayoutConstraint:0x7fbf4b5ee5a0 H:[UITextField:0x7fbf4b5ed780(264)]>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.

The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

  原因就在于UITextView设置了与superView的左右边距,又设置了宽度为264,导致了冲突。

5、在动态计算高度的cell里面,要把UITextView的Scrolling Enable设为NO,否则TextView的高度不会跟着内容变化,只会取一个最小的高度;同时也要把UITextView的user interaction enable也设为NO,否则TextView会拦截掉cell的点击事件,选中cell变成了编辑TextView。

6、在做完动态高度的cell之后,发现在真机上App打开后加载数据的时候非常慢。我一开始以为是Core Data的问题,于是自定义了一个加载的浮框控件,在打开App的时候,新开一条线程去Core Data取数据,主线程显示加载控件,样式如下:

  但是发现问题仍然存在,打开App之后仍然是会卡住一段时间,并且卡住的是主线程上的加载控件,甚至当时页面上只有1个cell,都整整卡住了8秒钟。那就很明显问题不在于Core Data了,而在于主线程上。

  于是我一步一步排查,首先发现耗时操作主要在于获取到数据后刷新TableView的reloadData方法上,再进一步排查发现耗时主要发生在这个方法里:

  reloadData方法会调用tableView:cellForRowAtIndexPath:方法,下一步就有可能会调用到上面的loadNibName:owner:options:方法,而主要的耗时就发生在这个方法里。于是着重研究这个xib文件,最后发现问题出在两个地方:

  (1)、xib里显示随笔标题的UILabel使用了“苹方”这种字体,而真机是iOS 8系统的,手机系统里匹配不到“苹方”字体,最终使用了系统默认的字体,这个匹配的过程造成了大部分的耗时,最终将UILabel的字体设为系统默认字体,解决了这部分耗时;

  (2)、xib里显示随笔内容的UITextView默认的text写了中文,导致了小部分的耗时,将默认text改成英文就解决了这部分耗时。

  然后发现仍然有改进的空间:

  现在cell的高度cellHeight是在cell设置随笔模型的setArticle:方法里去计算的,每次调用setArticle:方法都会计算一次,而setArticle:方法调用在tableView:cellForRowAtIndexPath:方法里,即是,每次调用tableView:cellForRowAtIndexPath:都会计算一次cell高度。

  进入App的时候,在tableView:heightForRowAtIndexPath:会去根据IndexPath取出对应cell,再返回它的高度,这个方法这里也是调用了tableView:cellForRowAtIndexPath:方法去取cell的,所以就造成了这么个情况:进入App的时候,每个cell的高度都会被计算两次。

  (3)、于是就使用了以下这个方法预估cell的高度,减少了一次cell高度的计算,又优化了一小部分耗时:

  做完这些优化之后,发现加载数据的时间已经非常短了,以至于根本不需要一个加载浮框了,于是就把加载浮框移除掉了。

7、在真机上跑App的时候发现了另一个问题:拖动TableView的时候会卡顿。原因还是在于cell高度的计算上,由于拖动TableView的时候,哪怕这个cell之前已经显示过了,新出现的cell还是会调用tableView:cellForRowAtIndexPath:方法,这样就多次计算了一个cell的高度。而这些能耗在iOS 8系统的iPhone 4S上显得特别明显。

  于是我开始思考是否有办法让所有cell都只计算一次,毕竟对于已经计算过高度的cell,是完全没有必要再重复去计算高度的了。最终使用了以下的方法来处理:

  (1)、在cell里单独提供一个计算高度的方法,不再在设置随笔模型的setArticle:方法里去计算cell的高度:

  (2)、在随笔列表控制器里新增一个属性:

  这个属性用来存放cell的高度,以IndexPath.row为key,对应cell的高度为value存在这个字典里。

  (3)、然后将tableView:cellForRowAtIndexPath:方法修改如下:

  (4)、最后将tableView:heightForRowAtIndexPath:修改如下,这样,所有的cell就只会计算一次了:

8、创建了搜索栏之后,我希望能只点击搜索栏右上方的Handler拖动这个搜索栏,而在Handler左右方的透明部分则不拦截任何手势

  在搜索栏中重写了这个方法完成了这个功能:

9、当搜索栏调出了键盘后,控制器接收到UIKeyboardWillShowNotification通知后在self.view上会添加一层蒙板,用以点击时收起键盘,同时也将蒙板自身remove掉。但是在真机上,发现点击了蒙板后虽然键盘会收起,但是self.view却没有任何点击反应了,似乎它并没有将自身remove掉。

  最终排查之后发现,问题出在UIKeyboardWillShowNotification通知上。在iOS 8 系统下,中文键盘出现时会发送3次UIKeyboardWillShowNotification通知,这样就使得页面上添加了3层蒙板,导致了页面点击无反应。

  最终在UIKeyboardWillShowNotification通知的处理方法里,处理成先移除已有蒙板再添加新蒙板,解决了这个问题。

所闻所获6:meditashayne项目总结的更多相关文章

  1. 所闻所获5:关于iOS的证书

    去年做ondine时,被iOS的证书搞得很是头大,做完了之后感觉一片混乱,印象也不是很深.最近又发布了meditashayne,个人的第二个App,也就重温了一下证书的一些相关操作.这一次的理解比较深 ...

  2. VS Bug 当获取其他项目的代码时, F5 无法进入调试模式. 也不报错....

    在64位的机子下, 被获用的项目使用X86时会出现. 就会出现   F5 无法进入调试模式. 也不报错.... 打断点也没有用. 在不加入X86项目的代码时, 又可以运行..   解决方案:   检查 ...

  3. BPM始终服务于人,落脚于人

    数字经济时代下,云计算.大数据.移动互联已经成为当下企业必须采取的武装力量.随着互联网+.中国制造2025.工业4.0等国家战略的引导与支持,无数的企业在这场数字化浪潮中使尽浑身解数,想要抓住机遇奋力 ...

  4. 20145227《Java程序设计》课程总结

    20145227<Java程序设计>课程总结 每周读书笔记链接汇总 20145227 <Java程序设计>第1周学习总结 20145227 <Java程序设计>第2 ...

  5. PSP总结报告1

    回答作业问题 1.回想一下你曾经对计算机专业的畅想 我高考后报考的是计算机科学与技术,当时对计算机技术基本了解为零,当时以为什么东西都会用到计算机,学计算机以后不会找不到工作,刚开学的时候对计算机一窍 ...

  6. Prism 4 文档 ---第7章 组成用户界面

    一个应用程序的用户界面(UI)可以通用以下几种模式之一来构建: 窗体所需要所有的控件都包含在一个单独的XAML文件中,在设计时组合这个窗体. 窗体的逻辑区域被分割到单独的部分中,通常指哟过户控件.这些 ...

  7. 走,去出海,一起“Copy to World” | 36氪出海行业报告

    http://www.sohu.com/a/200845344_114778 从工具类产品在海外聚集大量流量到新闻.社交游戏等内容类产品在海外取得优异成绩,中国正在完成从Copy to China向C ...

  8. 2017年度最具商业价值人工智能公司TOP50 榜单发布

    2017年度最具商业价值人工智能公司TOP50 榜单发布 未来最有赚钱潜力的50个人工智能项目都在这里了. 经过了60年的发展,人工智能在2017年,正式走向应用的元年. 从今年起,人工智能首次被写入 ...

  9. 华策光通信: LED可见光通信室内定位项目获最具投资价值奖

    3月21日上午,一场持续3个多小时的O2O领域的创业DemoShow在深圳科兴科学园会议中心激烈上演.来自华策光通信的基于LED可见光通信室内精准定位项目作为LED与室内定位领域的跨界融合项目经过精彩 ...

随机推荐

  1. 腾讯TT浏览器应用程序发生异常(0xc0000409) 位置为0x027a1f7f 的解决办法

    2013年8月26日下午,腾讯TT浏览器 4.8版1000 出现“应用程序发生异常(0xc0000409)  位置为0x027a1f7f ”的错误,导致浏览器自动关闭. 无论重新卸载安装还是 清理系统 ...

  2. PHP批量审核后台

    /*批量审核方法*/ function setOn_all() { if($_POST) { $p=M('news'); $data=array(); $i=0; foreach ($_POST as ...

  3. ubuntu 14.04 下 yii2 下载安装

    先安装composer ,安装了curl的情况下: curl -s http://getcomposer.org/installer | php mv composer.phar /usr/local ...

  4. qt model/view 架构基础介绍之QListWidget

    # -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' from PyQt4.QtGui import  * from Py ...

  5. 使用<base target="_self" /> IE6 cann't open the Internet site 已终止操作

    今日发现一个问题,我的网页需要用到<base target="_self" />,经测试IE8,9  谷歌   火狐全都正常,但是IE6 showModalDialog ...

  6. 分享一个3D球面标签云

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. [视频] x264 压缩笔记

    转载本站文章请注明,转载自:扶凯[http://www.php-oa.com] 本文链接: http://www.php-oa.com/2009/03/22/x264.html 象x264本身是不能直 ...

  8. Oracle—RMAN备份(二)

    在Oracle  RMAN备份(一)中,对各种文件在RMAN中备份进行了说明, 一.备份集的复制 在RMAN 备份中,可以备份其自己的备份,即备份一个文件放在多个目录下,oralce支持最多备份四个. ...

  9. java第二周学习日记

    day01 1.抽象类 (1)抽象类的应用场景: 我们在描述一类事物的时候,发现该种事物确实存在着某种行为,但是这种行为目前不是具体的,那么我们可以抽取这种行为的声明,但是不去实现该种行为,这时候这种 ...

  10. css-下拉菜单案例

    <!DOCTYPE html>CSS4-布局2-display下拉菜单案例 <style>.xiala{width:200px;background:#ddd;}.xiala ...