ios_iostream - CSDN
ios 订阅
iOS是由苹果公司开发的移动操作系统 [1]  。苹果公司最早于2007年1月9日的Macworld大会上公布这个系统,最初是设计给iPhone使用的,后来陆续套用到iPod touch、iPad上。iOS与苹果的macOS操作系统一样,属于类Unix的商业操作系统。原本这个系统名为iPhone OS,因为iPad,iPhone,iPod touch都使用iPhone OS,所以2010年WWDC大会上宣布改名为iOS(iOS为美国Cisco公司网络设备操作系统注册商标,苹果改名已获得Cisco公司授权)。2016年1月,随着iOS 9.2.1版本的发布,苹果修复了一个存在了3年的漏洞 [2]  。2018年9月22日,美国苹果公司在最新的操作系统中秘密加入了基于iPhone用户和该公司其他设备使用者的“信任评级”功能。 展开全文
iOS是由苹果公司开发的移动操作系统 [1]  。苹果公司最早于2007年1月9日的Macworld大会上公布这个系统,最初是设计给iPhone使用的,后来陆续套用到iPod touch、iPad上。iOS与苹果的macOS操作系统一样,属于类Unix的商业操作系统。原本这个系统名为iPhone OS,因为iPad,iPhone,iPod touch都使用iPhone OS,所以2010年WWDC大会上宣布改名为iOS(iOS为美国Cisco公司网络设备操作系统注册商标,苹果改名已获得Cisco公司授权)。2016年1月,随着iOS 9.2.1版本的发布,苹果修复了一个存在了3年的漏洞 [2]  。2018年9月22日,美国苹果公司在最新的操作系统中秘密加入了基于iPhone用户和该公司其他设备使用者的“信任评级”功能。
信息
软件语言
Swift,Objective-C、C、C++
软件大小
1.2 GB
开发商
Apple - 苹果
软件授权
仅苹果移动设备使用
更新时间
2020年7月16日
中文名
苹果移动设备操作系统
最新正式版
iOS 13.6(17G68)
全    称
iPhone Operation System
最新测试版
iOS 14.0 Beta3(18A5332f)
外文名
iOS
iOS发展历程
2007年1月9日苹果公司在Macworld展览会上公布,随后于同年的6月发布第一版iOS操作系统,最初的名称为“iPhone Runs OS X”。2007年10月17日,苹果公司发布了第一个本地化iPhone应用程序开发包(SDK),并且计划在2月发送到每个开发者以及开发商手中。2008年3月6日,苹果发布了第一个测试版开发包,并且将“iPhone runs OS X”改名为“iPhone OS”。2008年9月,苹果公司将iPod touch的系统也换成了”iPhone OS“。2010年2月27日,苹果公司发布iPad,iPad同样搭载了”iPhone OS”。这年,苹果公司重新设计了“iPhone OS”的系统结构和自带程序。2010年6月,苹果公司将“iPhone OS”改名为“iOS”,同时还获得了思科iOS的名称授权。2010年第四季度,苹果公司的iOS占据了全球智能手机操作系统26%的市场份额。2011年10月4日,苹果公司宣布iOS平台的应用程序已经突破50万个。2012年2月,应用总量达到552,247个,其中游戏应用最多,达到95,324个,比重为17.26%;书籍类以60,604个排在第二,比重为10.97%;娱乐应用排在第三,总量为56,998个,比重为10.32%。2012年6月,苹果公司在WWDC 2012上发布了iOS 6,提供了超过200项新功能。2012年9月20日,苹果发布iOS 6正式版,本次更新拥有超过200项新功能。这其中尤其加强了针对中国用户的定制功能,包括Siri开始支持中文语言,系统整合新浪微博、163邮箱等方面。 [3]  2013年6月10日,苹果公司在WWDC 2013上发布了iOS 7,几乎重绘了所有的系统App,去掉了所有的仿实物化,整体设计风格转为扁平化设计。将于2013年秋正式开放下载更新。 [4]  2013年9月19日,苹果发布iOS 7正式版,带来超过200项全新功能。 [5]  2014年6月3日(西八区时间2014年6月2日),苹果公司在WWDC 2014上发布了iOS 8,并提供了开发者预览版更新。 [6]  2014年9月17日,苹果发布iOS 8正式版。 [7]  2015年9月17日,苹果发布iOS 9正式版。 [8]  2016年9月14日,苹果发布iOS 10正式版,这是苹果推出移动操作系统以来最大的一次更新,尤其增加了很多特别适应中国国情的功能,比如骚扰电话识别、苹果地图进一步本地化等。 [9-10]  2017年9月20日,苹果发布iOS 11正式版,iOS 11为iPad带来了更强大的生产力,具体是通过新的Dock栏、文件App、多任务处理、拖拽等功能来实现的。另外,iOS 11重要的一项新功能便是AR功能,这使得该平台成为世界最大的AR平台,用户只需用手机便可享受AR的无穷乐趣。除此之外,iOS 11还带来了更生动更有趣的Live Photo、相机扫码、App Store、控制中心、锁屏、勿扰模式等。 [11-12]  2018年9月18日,苹果发布iOS 12正式版,主要为旧iPhone设备带来性能提升,以及带来了部分全新功能。 [13-14]  2018年9月13日,2018苹果秋季新品发布会上,苹果CEO库克介绍了苹果生态的一些数据。他表示,搭载苹果iOS系统设备已达20亿部。 [15]  2019年9月11日,苹果宣布于2019年9月19日推送iOS 13正式版,支持iPhone 6S及后续机型。 [16]  2019年6月4日,苹果公司在WWDC 2019上发布了iOS 13。2019年9月20日,苹果发布iOS 13正式版,iOS 13推出的"深色"模式为iPhone带来了全然不同的新风格,提供了浏览和编辑照片的全新方式,并新增了保护隐私的登录方式,轻点一下即可登录App和网站。iOS 13速度更快、响应更迅速。系统经整体优化后,App启动速度提升、App下载大小缩减,同时面容ID也变得更快。 [17-18]  2019年9月25日,苹果发布iOS 13.1正式版,实现了诸多问题修复和功能改进,包括iPhone 11、iPhone 11 Pro和iPhone 11 Pro Max上采用超宽频技术的隔空投送、快捷指令App中建议的自动化操作,以及地图App中的共享到达时间。 [19]  美国西部时间2019年9月27日上午10点(北京时间28日凌晨一点),苹果发布了iOS 13.1.1 / iPadOS 13.1.1 正式版更新。 [20]  2019年10月29日,苹果发布iOS 13.2正式版,在iPhone 11、iPhone 11 Pro和iPhone 11 Pro Max上推出了先进的图像处理系统Deep Fusion,它使用A13仿生神经网络引擎拍摄纹理及细节更出众、低光环境下噪点更少的照片。其他功能包括更新和新增的表情符号、AirPods信息播报,并支持AirPods Pro、HomeKit安全视频、具有HomeKit功能的路由器以及新的Siri隐私设置。本更新还包括错误修复和改进。 [21]  2019年12月11日,苹果发布iOS 13.3正式版,包括了改进和错误修复,并在“屏幕使用时间”中新增了更多家长控制。根据苹果发布的最新支持文档,iOS 13.3正在进行改进以最大程度地减少信息App中的垃圾短信等内容。 [22]  2020年3月18日,苹果宣布将于北京时间3月25日为iPhone、iPad和iPod touch用户推送iOS 13.4和iPadOS 13.4正式版。除了重新设计的邮件工具栏和iCloud文件夹共享功能之外,iPadOS 13.4还为iPad平台带来触控板和鼠标支持。 [23]  2020年3月19日,苹果发布iOS 13.4 Beta6(GM版),此前iOS 13.4/iPadOS 13.4已经历经了5次Beta预览测试。Golden Master版本(最终测试版)的出现意味着iOS 13.4正式版到来,优先面向开发者/公开测试版渠道用户推送。而最广泛的iOS 13.4/iPadOS 13.4正式版将在3月25日面向普通用户推送。 [24]  2020年3月25日,苹果发布iOS 13.4正式版,在此次更新中苹果主要推出了新的拟我表情贴纸和从“文件”App共享iCloud云盘文件夹的功能,同时iPad更新后支持搭配使用鼠标和触控板了。 [25]  2020年5月21日,苹果发布iOS 13.5正式版,iOS 13.5加快了配备面容ID的设备在用户佩戴口罩时显示密码栏的速度,并加入了“暴露通知”API以支持来自公共卫生管理机构的COVID-19接触追踪App。本更新还增加了控制FaceTime群聊期间视频拼贴自动突显的选项并包括错误修复和其他改进。 [26]  2020年7月16日,苹果发布iOS 13.6正式版,iOS 13.6支持数字车钥匙,并在“健康”App中包含新的症状类别。本更新还包括错误修复和改进。 [27]  2020年6月23日,苹果公司在WWDC 2020上发布了iOS 14,它为iOS主屏幕带来了多年来最大的变化:小插件。 [28]  Java [6]  苹果仍没有宣布任何让iPhone运行Java的计划。但太阳微系统已宣布其将会发布能在iPhone上运行的Java虚拟机(JVM)的计划,它是基于Java的Micro Edition版本。这将让用Java应用程序得以在iPhone和iPod Touch上运行。在这个计划发表之后,熟悉iOS软件开发协议的程序员们相信虽然iOS软件开发协议不允许应用程序后台运行(比如说在接电话的时候仍然运行程序), 但却允许自带的应用程序从其他的来源下载代码,而且它们还能与第三方应用程序相互作用(比如说Safari和Java虚拟机), 这可能会阻碍不与苹果合作的Java虚拟机的发展。 很明显,在iPhone运行的Java在iOS软件开发协议所规定的范畴以外。FlashiOS不支持Flash。Adobe计划在iPhone发行第三方Flash Lite软件程序,但现时仍未有计划。以现时来说,只支持标准Flash。现时可以使用iPhone第三方程序jailbreak观看flash动画。但不支持在线播放。SwiftSwift,苹果于2014年WWDC(苹果开发者大会)发布的新开发语言,可与Objective-C共同运行于Mac OS和iOS平台,用于搭建基于苹果平台的应用程序。Swift是苹果公司在WWDC2014上发布的全新开发语言。从演示视频及随后在App Store上线的标准文档看来,语法内容混合了OC,JS,Python,语法简单,使用方便,并可与OC混合使用。作为一项苹果独立发布的支持型开发语言,已经有了数个应用演示及合作开发公司的测试,相信将在未来得到更广泛的应用。某种意义上Swift作为苹果的新商业战略,将吸引更多的开发者入门,从而增强App Store和Mac Store本来就已经有的应用数量基础。
收起全文
  • 本课程讲述如何使用OC 实现1V1 iOS端实时音视频通信 包括如何使用nodejs开发WebSocket信令服务器 理解WebRTC媒体的交互流程 coturn服务器搭建 iOS音视频客户端开发
  • 本课程详细介绍了IOS开发环境搭建及开发工具的使用,讲解了IOS开发常用视图控件的使用 ,还讲解了一个实用的功能实例:APP启动引导页的开发。
  • 本课程主要介绍了开发iOS app的一些基本情况。例如,需要的硬件和软件条件,如何申请开发者账号,XCode的常用功能介绍。后给出一个iOS App的案例来演示开发App的过程。
  • 推荐一些我个人认为非常经典,值得关注的博客: OneV's Den 大家尊称为喵神 @onevcat 的博客。对 Swift 技术在国内的推广做了很大的贡献。...Casa 对架构有很深的理解,《iOS 应用架构谈》系列文章影响深...

    推荐一些我个人认为非常经典,值得关注的博客:

    OneV's Den

    大家尊称为喵神 @onevcat 的博客。对 Swift 技术在国内的推广做了很大的贡献。

    Limboy’s HQ

    李忠关于 RAC 、组件化的文章流传很广。博客中对架构、编程的思考都很精髓。听说现在转管理后不太更新技术文了。

    Casa Taloyum

    Casa 对架构有很深的理解,《iOS 应用架构谈》系列文章影响深远。

    bang’s blog

    JSPatch 作者 bang 的博客。稳定更新,每篇文章质量都很高。

    Garan no dou | 一只魔法师的工坊

    YYKit 作者的博客,很多文章如《iOS 保持界面流畅的技巧》《深入理解RunLoop》等都有极高的实用价值。

    Draveness’s Blog

    被人称为灯塔的 Draveness 的博客。Draveness 涉猎很广,文章也很有深度,一半以上的文章我连标题都看不懂。

    Halfrost-Field

    人称“霜神”冰霜的博客,冰霜的文章针对某个问题总是能有深入、全面的剖析。

    星光社

    滴滴技术专家戴铭的博客,每篇都是精品。

    玉令天下

    腾讯杨萧玉的博客,底层细节能深入到汇编的实现,令人惊叹。

    MrPeak杂货铺

    Peak 以一系列 TCP/IP 相关的文章让人折服,之前博客更新频率很高,多有涉猎。17 年底去 facebook 赚奶粉钱后更新频率有所下降,望早日回归。

    Bestswifter

    @bestswifter 张星宇的博客,《让 BAT 的 offer 不再难拿》介绍了他在大学时准备面试最后进入百度的经历,这篇文章也引起了不小的积极反响。博客除了如 《深入理解 iOS 开发中的锁》 iOS 开发也有不少工程化话题的文章。

    故胤道长

    顶级 iOS 开发者,曾就职于 Uber,现就职于美帝亚马逊。文风流畅,博客也会谈到不少中美编程文化的差异。

    iOS程序犭袁

    CYLTabBarController 作者,博客也是篇篇经典。

    sunnyxx

    滴滴技术专家孙源的博客,对于 OC 语言特性有深入研究。不过整个 17 年没有更新博客。

    雷纯锋的技术博客

    有多篇经典的博客,如《谈谈 iOS 中图片的解压缩》《MVVM With ReactiveCocoa》。不过 17 年只更新了一篇文章。

    瓜地

    冬瓜的博客,作为曾经 acm‘er 的素质与修养,博客总是能够深入底层。

    Joy_xx

    被人称为架构 joy 的博客,有不少关于 APM 的好文。

    J_Knight_

    J_Knight的文章总是清晰易懂,更新的也很勤快。

     

    更新:

    1、专栏整理,内容相当丰富,主要涉及iOS中架构、性能优化、APM、底层原理等高级进阶知识:来自-乐少的Github

    2、大厂公开演讲、技术分享资料,包括PPT和视频等资料:大厂公开演讲、技术分享-Github

    3、众多经典三方库源码解析,来自Draveness:源码解析-Github

     

    参考:https://www.jianshu.com/p/ea9fabdc12ed
     

    展开全文
  • 本视频教程拥有180节课程,包含iOS开发的方方面面:iOS开发基础理论知识、 视图、视图控制器、多媒体、数据处理、常用插件、信用卡卡号识别、自动化测试、网络访问、多线程、ShareSDK社会化分享、CoreImage、...
  • IOS APP 架构设计一,APP架构概述 一,APP架构概述 IOS 架构的5中模式: 标准的CocoaModel-View-Controller(MVC)是Apple在示例项目中所采用的设计模 式。它是 Cocoa app 中最为常⻅的架构,同时也是在 Cocoa 中讨论...

    一,APP架构概述

    1. 应用架构

    App 架构是软件设计的一个分支,它关心如何设计一个 app 的结构。具体来说,它关注于两个 方面:如何将 app 分解为不同的接口和概念层次部件,以及这些部件之间和自身的不同操作中 所使用的控制流和数据流路径。
    我们通常使用简单的框图来解释 app 的架构。比如,Apple 的 MVC 模式可以通过 model、 view 和 controller 三层结构来描述。

    在这里插入图片描述
    上面框图中的模块展示了这个模式中不同名字的三个层次。在一个 MVC 项目中,绝大部分的代 码都会落到其中某个层上。箭头表示了这些层进行连接的方式。
    但是,这种简单的框图几乎无法解释在实践中模式的操作方式。这是因为在实际的 app 架构中, 部件的构建有非常多的可能性。事件流在层中穿梭的方式是什么?部件之间是否应该在编译期 间或者运行时持有对方?要怎么读取和修改不同部件中的数据?以及状态的变更应该以哪条路 径在 app 中穿行?

    2.Model 和 View

    在最高的层级上,app 架构其实就是一套分类,app 中不同的部件会被归纳到某个类型中去。 在本书中,我们将这些不同的种类叫做层次:一个层次指的是,遵循一些基本规则并负责特定 功能的接口和其他代码的集合。
    Model 层和 View 层是这些分类中最为常⻅的两个。
    Model 层是 app 的内容,它不依赖于 (像 UIKit 那样的) 任何 app 框架。也就是说,程序员对 model 层有完全的控制。Model 层通常包括 model 对象 (在录音 app 中的例子是文件夹和录音对象) 和协调对象 (比如我们的 app 例子中的负责在磁盘上存储数据的 Store 类型)。被存储在 磁盘上的那部分 model 我们称之为文档 model (documentation model)。
    View 层是依赖于 app 框架的部分,它使 model 层可⻅,并允许用戶进行交互,从而将 model 层转变为一个 app。当创建 iOS 应用时,view 层几乎总是直接使用 UIKit。不过,我们也会看 到在有些架构中,会使用 UIKit 的封装来实现不同的 view 层。另外,对一些其他的像是游戏这 样的自定义应用,view 层可以不是 UIKit 或者 AppKit,它可能是 SceneKit 或者 OpenGL 的某 种封装。
    有时候,我们选择使用结构体或者枚举来表示 model 或者 view 的实例,而不使用类的对象。 在实践中,类型之间的区别非常重要,但是当我们在 model 层中谈到对象、结构体和枚举时, 我们会将三者统一地称为 model 对象。类似地,我们也会把 view 层的实例叫做 view 对象,实 际上它们也可能是对象、结构体或者枚举。
    View 对象通常会构成一个单一的 view 层级,在这个层级中,所有的 view 对象通过树结构的方 式连接起来。在树的根部是整个屏幕,屏幕中存在若干窗口,接下来在树的分支和叶子上是更 多的小 view。类似地,view controller 也通常会形成 view controller 层级。不过,model 对 象却不需要有明确的层级关系,在程序中它们可以是互不关联的独立 model。
    当我们提到 view 时,通常指的是像一个按钮或者一个文本 label 这样的单一 view 对象。当我 们提到 model 时,我们通常指的也是像一个 Recording 实例或者 Folder 实例这样的单个 model 对象。在该话题的大多数文献中,“model” 在不同上下文中指的可能是不同的事情。它 可以指代一个 model 层,model 层中的具体的若干对象,文档 model,或者是 model 层中不 关联的文档。虽然可能会显得啰嗦,我们还是会尝试在本书中尽量明确地区分这些不同含义。

    为什么 Model 和 View 的分类会被认为是基础中的基础

    当然啦,就算不区分 model 层和 view 层,写出一个 app 也是绝对可能的。比如说,在一个简 单的对话框中,通常就没有独立的 model 数据。在用戶点击 OK 按钮的时候,我们可以直接从 用戶界面元素中读取状态。不过通常情况下,model 层的缺失,会让程序的行为缺乏对于清晰 规则的依据,这会使得代码难以维护。
    定义一个 model 层的最重要的理由是,它为我们的程序提供一个表述事实的单一来源,这会让 逻辑清晰,行为正确。这样一来,我们的程序便不会被应用框架中的实现细节所支配。
    应用框架为我们提供了构建 app 所需要的基础设施。在本书中,我们使用 Cocoa - 或者更精确 说,根据目标平台,使用 UIKit,AppKit 或者 WatchKit - 来作为应用框架。

    如果 model 层能做到和应用框架分离,我们就可以完全在 app 的范围之外使用它。我们可以很 容易地在另外的测试套件中运行它,或者用一个完全不同的应用框架重写新的 view 层。这个 model 层将能够用于 Android,macOS 或者 Windows 版本的 app 中。

    3.App 的本质是反馈回路

    View 层和 model 层需要交流。所以,两者之间需要存在连接。假设 view 层和 model 层是被清
    晰地分开,而且不存在无法解耦的联结的话,两者之间的通讯就需要一些形式的翻译:
    在这里插入图片描述

    从根本上说,用戶界面是一个同时负责展示和输入功能的反馈设备,所以毫无疑问,这导致的 结果就是一个反馈回路。每个 app 设计模式所面临的挑战是如何处理这张图表中箭头所包含的 交流,依赖和变换。
    在 model 层和 view 层之间不同的路径拥有不同的名字。用戶发起的事件会导致 view 的响应, 我们把由此引起的代码路径称为 view action,像是点击按钮或者选中 table view 中的某一行 就属于 view action。当一个 view action 被送到 model 层时,它会被转变为 model action (或 者说,让 model 对象执行一个 action 或者进行更新的命令)。这种命令也被叫做一个消息 (特别 在当 model 是被 reducer 改变时,我们会这么称呼它)。将 view action 转变为 model action 的操作,以及路径上的其他逻辑被叫做交互逻辑。

    一个或者多个 model 对象上状态的改变叫做 model 变更。Model 的变更通常会触发一个
    model 通知,比如说从 model 层发出一个可观测的通知,它描述 model 层中什么内容发生了 改变。当 view 依赖于 model 数据时,通知会触发一个 view 变更,来更改 view 层中的内容。 这些通知可以以多种形式存在:Foundation 中的 Noti?cation,代理,回调,或者是其他机制, 都是可以的。将 model 通知和数据转变为 view 更改的操作,以及路径上的其他逻辑被叫做表 现逻辑。
    根据 app 模式的不同,有些状态可能是在文档 model 之外进行维护的,这样一来,更新这些状 态的行为就不会追随文档 model 的路径。在很多模式中的导航状态就这种行为的一个常⻅例 子,在 view 层级中的某个部分 (或者按照 Cocoa Storyboard 中使用的术语,将它称为 scene) 可能会被换出或者换入层级中。
    在 app 中非文档 model 的状态被叫做 view state。在 Cocoa 里,大部分 view 对象都管理着它 们自己的 view state,controller 对象则管理剩余的 view state。在 Cocoa view state 的框图 中,通常会有加在反馈回路上的捷径,或者单个层自身进行循环。在有一些架构中,view state 不属于 controller 层,而是属于 model 层的部分 (不过,根据定义,view controller 并不是文 档 model 的一部分)。
    当所有的状态都在 model 层中被维护,而且所有的变更都通过完整的反馈回路路径进行传递 时,我们就将它称为单向数据流。当任意的 view 对象或者中间层对象只能够通过 model 发出 的通知来进行创建和更新 (换句话说,view 或者中间层不能通过捷径来更新自身或者其他的 view) 时,这个模式通常就是单向的。

    4.架构技术

    Apple 平台的标准 Cocoa 框架提供了一些架构工具。Noti?cation 将值从单一源广播给若干个 收听者。键值观察 (KVO) 可以将某个对象上属性的改变报告给另一个对象。然而,Cocoa 中的 架构工具十分有限,我们将会使用到一些额外的框架。
    本书中使用到的第三方技术中包含了响应式编程。响应式编程也是一种用来交流变更的工具, 不过和通知或者 KVO 不同的是,它专注于在源和目标之间进行变形,让逻辑可以在部件之间传 输信息的同时得以表达。
    我们可以使用像是响应式编程或者 KVO 这样的技术创建属性绑定。绑定接受一个源和一个目 标,无论何时,只要源发生了变化,目标也将被更新。这和手动进行观察在语法上有着不同, 我们不再需要写观察的逻辑,而只需要指定源和目标,接下来框架将会为我们处理其余部分的 工作。

    macOS 上的 Cocoa 包含有 Cocoa 绑定技术,它是一种双向绑定,所有的可观察对象同时也是 观察者,在一个方向上建立绑定连接,会在反方向也创建一个连接。不论是 (在MVVM-C 的章
    节中用到的) RxCocoa,还是 (MAVB 章节 中用到的) CwlViews,都不是双向绑定的。所以,在
    本书中,所有关于绑定的讨论都只涉及到单向绑定。

    5.App 任务

    要让程序正常工作,view 必须依赖于 model 数据来生成和存在,我们配置 view,让它可以对
    model 进行更改,并且能在 model 更新时也得到更新。 所以,我们需要决定在 app 中如何执行下列任务:

    1. 构建—谁负责构建model和view,以及将两者连接起来?
    2. 更新model—如何处理viewaction?
    3. 改变view—如何将model的数据应用到view上去?
    4. viewstate—如何处理导航和其他一些modelstate以外的状态?
    5. 测试—为了达到一定程度的测试覆盖,要采取怎样的测试策略?

    对于上面五个问题的回答,是构成 app 设计模式的基础要件。在本书中,我们会逐一研究这些 设计模式。

    6.IOS 架构的5中模式:

    IOS 架构的5中模式:

    • 标准的CocoaModel-View-Controller(MVC)是Apple在示例项目中所采用的设计模 式。它是 Cocoa app 中最为常⻅的架构,同时也是在 Cocoa 中讨论架构时所采用的基 准线。
    • Model-View-ViewModel+协调器(MVVM-C)是MVC的变种,它拥有单独的 “view-model” (视图模型) 和一个用来管理 view controller 的协调器。MVVM 使用数据 绑定 (通常会和响应式编程一起使用) 来建立 view-model 层和 view 层之间的连接。
    • Model-View-Controller+ViewState(MVC+VS)这种模式将所有的viewstate集中到 一个地方,而不是让它们散落在 view 和 view controller 中。这和 model 层所遵循的规 则相同。
    • Model适配器-View绑定器(ModelAdapter-ViewBinder,MAVB)是本书的一位作者所 使用的实验性质的架构。MAVB 专注于构建声明式的 view,并且抛弃 controller,采用 绑定的方式来在 model 和 view 之间进行通讯。
    • Elm架构(TEA)与MVC或者MVVM这样的常⻅架构完全背道而驰。它使用虚拟view 层级来构建 view,并使用 reducer 来在 model 和 view 之间进行交互。

    二,APP设计常用的5种模式概览

    1. Model-View-Controller

    在 Cocoa MVC 中,一小部分 controller 对象负责处理 model 或者 view 层范畴之外的所有任 务。
    这意味着,controller 层接收所有的 view action,处理所有的交互逻辑,发送所有的 model action,接收所有的 model 通知,对所有用来展示的数据进行准备,最后再将它们应用到 view 的变更上去。如果我们去看一下介绍一章中的 app 反馈回路的图,会发现在 model 和 view 之
    间的箭头上,几乎每个标签都是 controller。而且要知道,在这幅图中,构建和导航任务并没有 标注出来,它们也会由 controller 来处理。
    下面是 MVC 模式的框图,它展示了一个 MVC app 的主要通讯路径:

    在这里插入图片描述
    图中的虚线部分代表运行时的引用,view 层和 model 层都不会直接在代码中引用 controller。 实线部分代表编译期间的引用,controller 实例知道自己所连接的 view 和 model 对象的接口。
    如果我们在这个图标外部描上边界的话,就得到了一个 MVC 版本的 app 反馈回路。注意在图 表中其他的路径并不参与整个反馈回路的路径 (也就是 view 层和 controller 层上那些指向自身 的箭头)。

    1. 构建
      App 对象负责创建最顶层的 view controller,这个 view controller 将加载 view,并且知道应 该从 model 中获取哪些数据,然后把它们显示出来。Controller 要么显式地创建和持有 model 层,要么通过一个延迟创建的 model 单例来获取 model。在多文档配置中,model 层由更低层 的像是 UIDocument 或 NSDocument 所拥有。那些和 view 相关的单个 model 对象,通常会 被 controller 所引用并缓存下来。
    2. 更改 Model
      在 MVC 中,controller 主要通过 target/action 机制和 (由 storyboard 或者代码进行设置的) delegate 来接收 view 事件。Controller 知道自己所连接的 view,但是 view 在编译期间却没有 关于 controller 接口的信息。当一个 view 事件到达时,controller 有能力改变自身的内部状态, 更改 model,或者直接改变 view 层级。
    3. 更改 View
      在我们所理解的 MVC 中,当一个更改 model 的 view action 发生时,controller 不应该直接去 操作 view 层级。正确的做法是,controller 去订阅 model 通知,并且在当通知到达时再更改 view 层级。这样一来,数据流就可以单向进行:view action 被转变为 model 变更,然后 model 发送通知,这个通知最后被转为 view 变更。
    4. View State
      View state 可以按需要被 store 在 view 或者 controller 的属性中。相对于影响 model 的 view action,那些只影响 view 或 controller 状态的 action 则不需要通过 model 进行传递。对于 view state 的存储,可以结合使用 storyboard 和 UIStateRestoring 来进行实现,storyboard 负责记录活跃的 controller 层级,而 UIStateRestoring 负责从 controller 和 view 中读取数据。
    5. 测试
      在 MVC 中,view controller 与 app 的其他部件紧密相连。边界的缺失使得为 controller 编写 单元测试和接口测试十分困难,集成测试是余下的为数不多的可行测试手段之一。在集成测试 中,我们构建相连接的 view、model 和 controller 层,然后操作 model 或者 view,来测试是 否能得到我们想要的结果。
      集成测试的书写非常复杂,而且它涵盖的范围太广了。它不仅仅测试逻辑,也测试部件是如何 连接的 (虽然在一些情况下和 UI 测试的⻆度并不相同)。不过,在 MVC 中通过集成测试,通常 达到 80% 左右的测试覆盖率是有可能的。
    • MVC 的重要性

    因为 Apple 在所有的实例项目中都使用了这种模式,加上 Cocoa 本身就是针对这种模式设计 的,所以 Cocoa MVC 成为了 iOS,macOS,tvOS 和 watchOS 上官方认证的 app 架构模式。

    • 历史

    MVC 这个名字第一次被提出是在 1979 年,Trygve Reenskaug 用它来描述 Smalltalk-76 上已 经存在的 “template pattern” 应用。在他和 Adele Goldberg 讨论了术语方面的问题后,MVC 的名字被确定下来 (之前的名字包括 Model-View-Editor 和 Model-View-Tool-Editor 等)。
    在原本的构想中,view 是直接 “附着” 在 model 层上,并观察所有 model 变化的。Controller 存在的目的仅仅是捕捉用戶事件,并把它们转发给 model。这两个特性都是 Smalltalk 运行方 式的产物,它们并不是为了现代的 app 框架所设计的,所以今天这种 MVC 的原始构想已经几 乎绝迹了。
    Cocoa 中的 MVC 实现可以追溯到大约 1997 年的 NeXTSTEP 4 的年代。在那之前,所有现在 controller 所担当的⻆色,通常都由一个 (像是 NSWindow 那样的) 高层 view 类来扮演。之后, 从原始的 Smalltalk 的 MVC 实现中所发展出的理念是分离展示部分,也就是 view 层和 model 层应该被完全隔离开,这带来了一个强烈的需求,那就是要引入一个支持对象来辅助两者之间 的通讯。NeXTSTEP 中 controller 的概念和 Taligent 稍早的 Model-View-Presenter 中的 presenter (展示器) 很相似。不过,在现在 Model-View-Presenter 这个名字通常被用来指代那 些通过协议从 controller 中将 view 抽象出来的类似 MVC 的模式。

    2. Model-View-ViewModel+协调器

    MVVM 和 MVC 类似,也是通过基于场景 (scene,view 层级中可能会在导航发生改变时切入或者换出的子树) 进行的架构。相较于 MVC,MVVM 在每个场景中使用 view-model 来描述场景中的表现逻辑和交互逻辑。

    View-model 在编译期间不包含对 view 或者 controller 的引用。它暴露出一系列属性,用来描 述每个 view 在显示时应有的值。把一系列变换运用到底层的 model 对象后,就能得到这些最 终可以直接设置到 view 上的值。实际将这些值设置到 view 上的工作,则由预先建立的绑定来 完成,绑定会保证当这些显示值发生变化时,把它设定到对应的 view 上去。响应式编程是用来 表达这类声明和变换关系的很好的工具,所以它天生就适合 (虽说不是严格必要) 被用来处理
    view-model。在很多时候,整个 view-model 都可以用响应式编程绑定的方式,以声明式的形 式进行表达。

    在理论上,因为 view-model 不包含对 view 层的引用,所以它是独立于 app 框架的,这让对于 view-model 的测试也可以独立于 app 框架。
    由于 view-model 是和场景耦合的,我们还需要一个能够在场景间切换时提供逻辑的对象。在 MVVM-C 中,这个对象叫做协调器 (coordinator)。协调器持有对 model 层的引用,并且了解 view controller 树的结构,这样,它能够为每个场景的 view-model 提供所需要的 model 对象。
    和 MVC 不同,MVVM-C 中的 view controller 从来都不会直接引用其他的 view controller (所 以,也不会引用其他的 view-model)。View controller 通过 delegate 的机制,将 view action 的信息告诉协调器。协调器据此显示新的 view controller 并设置它们的 model 数据。换句话 说,view controller 的层级是由协调器进行管理的,而不是由 view controller 来决定的。

    这些特性所形成的架构的总体结构如下图所示:

    在这里插入图片描述

    如果我们忽略掉协调器,那么这张图表就很像 MVC 了,只不过在 view controller 和 model 之 间加入了一个阶段。MVVM 将之前在 view controller 中的大部分工作转移到了 view-model 中,但是要注意,view-model 并不会在编译时拥有对 view controller 的引用。
    View-model 可以从 view controller 和 view 中独立出来,也可以被单独测试。同样,view controller 也不再拥有内部的 view state,这些状态也被移动到了 view-model 中。在 MVC 中 view controller 的双重⻆色 (既作为 view 层级的一部分,又负责协调 view 和 model 之间的交 互),减少到了单一⻆色 (view controller 仅仅只是 view 层级的一部分)。
    协调器模式的加入进一步减少了 view controller 所负责的部分:现在它不需要关心如何展示其 他的 view controller 了。因此,这实际上是以添加了一层 controller 接口为代价,降低了 view controller 之间的耦合。

    1. 构建
      对于 model 的创建和 MVC 中的保持不变,通常它是一个顶层 controller 的职责。不过,单独
      的 model 对象现在属于 view-model,而不属于 view controller。
      初始的 view 层级的创建和 MVC 中的一样,通过 storyboard 或者代码来完成。和 MVC 不同的 是,view controller 不再直接为每个 view 获取和准备数据,它会把这项工作交给 view-model。 View controller 在创建的时候会一并创建 view-model,并且将每个 view 绑定到 view-model 所暴露出的相应属性上去。
    2. 更改 Model
      在 MVVM 中,view controller 接收 view 事件的方式和 MVC 中一样 (在 view 和 view controller 之间建立连接的方式也相同)。不过,当一个 view 事件到达时,view controller 不会 去改变自身的内部状态、view state、或者是 model。相对地,它立即调用 view-model 上的方 法,再由 view-model 改变内部状态或者 model。
    3. 更改 View
      和 MVC 不同,view controller 不监听 model。View-model 将负责观察 model,并将 model 的通知转变为 view controller 可以理解的形式。View controller 订阅 view-model 的变更,这 通常通过一个响应式编程框架来完成,但也可以使用任意其他的观察机制。当一个 view-model 事件来到时,由 view controller 去更改 view 层级。
      为了实现单向数据流,view-model 总是应该将变更 model 的 view action 发送给 model,并 且仅仅在 model 变化实际发生之后再通知相关的观察者。
    4. View State
      View state 要么存在于 view 自身之中,要么存在于 view-model 里。和 MVC 不同,view controller 中不存在任何 view state。View-model 中的 view state 的变更,会被 controller 观 察到,不过 controller 无法区分 model 的通知和 view state 变更的通知。当使用协调器时, view controller 层级将由协调器进行管理。
    5. 测试
      因为 view-model 和 view 层与 controller 层是解耦合的,所以可以使用接口测试来测试 view-model,而不需要像 MVC 里那样使用集成测试。接口测试要比集成测试简单得多,因为 不需要为它们建立完整的组件层次结构。
      为了让接口测试尽可能覆盖更多的范围,view controller 应当尽可能简单,但是那些没有被移 出 view controller 的部分仍然需要单独进行测试。在我们的实现中,这部分内容包括与协调器 的交互,以及初始时负责创建工作的代码。
    • MVVM 的重要性

    MVVM 是 iOS 上最流行的 MVC 的非直接变形的 app 设计模式。换言之,它和 MVC 相比,并没有非常大的不同;两者都是围绕 view controller 场景构建的,而且所使用的机制也大都相同。

    最大的区别可能在于 view-model 中对响应式编程的使用了,它被用来描述一系列的转换和依 赖关系。通过使用响应式编程来清晰地描述 model 对象与显示值之间的关系,为我们从总体上 理解应用中的依赖关系提供了重要的指导。

    iOS 中的协调器是一种很有用的模式,因为管理 view controller 层级是一件非常重要的事情。 协调器在本质上并没有和 MVVM 绑定,它也能被使用在 MVC 或者其他模式上。

    • 历史

    MVVM 由 Ken Cooper 和 Ted Peters 提出,他们当时在微软工作,负责后来变成 Windows Presentation Foundation (WPF) 的项目,这是微软.NET 的 app 框架,并于 2005 年正式发布。

    WPF 使用一种基于 XML,被称为 XAML 的描述性语言来描述 view 所绑定的某个 view-model 上的属性。在 Cocoa 中,没有 XAML,我们必须使用像是 RxSwift 这样的框架和一些 (通常存 在于 controller 中的) 代码来完成 view-model 和 view 的绑定。

    MVVM 和我们在 MVC 历史中提到的 MVP 模式非常类似. 不过,在 Cooper 和 Peters 的论述中, MVVM 中 view 和 view-model 的绑定需要明确的框架支持,但 presenter 是通过传统的手动 方式来传递变化。

    iOS 中的协调器则是最近才 (重新) 流行起来的,Soroush Khanlou 在 2015 年时在他的网站上描述了这个想法。协调器基于 app controller 这样的更古老的模式,而它们在 Cocoa 和其他平台上已经存在了有数十年之久。

    3. Model-View-Controller+ViewState

    MVC+VS 是为标准的 MVC 带来单向数据流方式的一种尝试。在标准的 Cocoa MVC 中,view state 可以由两到三种不同的路径进行操作,MVC+VS 则试图避免这点,让 view state 的处理 更加易于管理。在 MVC+VS 中,我们明确地在一个新的 model 对象中,对所有的 view state 进行定义和表达,我们把这个对象叫做 view state model。

    在 MVC+VS 中,我们不会忽略任何一次导航变更,列表选择,文本框编辑,开关变更,model 展示或者滚动位置变更 (或者其他任意的 view state 变化)。我们将这些变更发送给 view state model。每个 view controller 负责监听 view state model,这样变更的通讯会非常直接。在表现或者交互逻辑部分,我们不从 view 中去读取 view state ,而是从 view state model 中去获 取它们:

    在这里插入图片描述

    结果所得到的图表和 MVC 类似,但 controller 的内部反馈回路的部分 (被用来更新 view state) 有所不同,现在它和 model 的回路类似,形成了一个独立的 view state 回路。

    1. 构建
      和传统的 MVC 一样,将文档 model 数据应用到 view 上的工作依然是 view controller 的责任, view controller 还会使用和订阅 view state 。因为 view state model 和文档 model 都需要观 察,所以相比于典型的 MVC 来说,我们需要多得多的通过通知进行观察的函数。
    2. 更改 Model
      当 view action 发生时,view controller 去变更文档 model (这和 MVC 保持不变) 或者变更 model state。我们不会去直接改变 view 层级,所有的 view 变更都要通过文档 model 和 view state model 的通知来进行。
    3. 更改 View
      Controller 同时对文档 model 和 view state model 进行观察,并且只在变更发生的时候更新 view 层级。
    4. View State
      View State 被明确地从 view controller 中提取出来。处理的方法和 model 是一样的: controller 观察 view state model,并且对应地更改 view 层级。
    5. 测试
      在 MVC+VS 中,我们使用和 MVC 里类似的集成测试,但是测试本身会非常不同。所有的测试 都从一个空的根 view controller 开始,然后通过设定文档 model 和 view state model,这个 根 view controller 可以构建出整个 view 层级和 view controller 层级。MVC 的集成测试中最困 难的部分 (设定所有的部件) 在 MVC+VS 中可以被自动完成。要测试另一个 view state 时,我 们可以重新设置全局 view state,所有的 view controller 都会调整自身。
      一旦 view 层级被构建,我们可以编写两种测试。第一种测试负责检查 view 层级是不是按照我 们的期望被建立起来,第二种测试检查 view action 有没有正确地改变 view state。
    • MVC+VS 的重要性

    MVC+VS 主要是用来对 view state 进行教学的工具。
    在一个非标准 MVC 的 app 中,添加一个 view state model,并且在每个 view controller 中 (在已经对 model 进行观察的基础上) 观察这些 view state model,提供了不少优点:任意的状 态恢复 (这种恢复不依赖于 storyboard 或者 UIStateRestoration),完整的用戶界面日志,以及 为了调试目的,在不同的 view state 间进行跳转的能力。

    • 历史

    这种特定的体系是 Matt Gallagher 在 2017 年开发的教学工具,它被用来展示单向数据流和用 戶界面的时间旅行等概念。这个模式的目标是,在传统的 Cocoa MVC app 上通过最小的改动, 实现对 view 的状态在每个 action 发生时都可以进行快照。

    4. Model 适配器-View 绑定器 (MAVB)

    MAVB 是一种以绑定为中心的实验模式。在这个模式中,有三个重要的概念:view 绑定器, model 适配器,以及绑定。

    View 绑定器是 view (或者 view controller) 的封装类:它构建 view,并且为它暴露出一个绑定 列表。一些绑定为 view 提供数据 (比如,一个标签的文本),另一些从 view 中发出事件 (比如, 按钮点击或者导航变更)。

    虽然 view 绑定器可以含有动态绑定,但是 view 绑定器本身是不可变的。这让 MAVB 也成为了 一种声明式的模式:你声明 view 绑定器和它们的 action,而不是随着时间去改变 view 绑定器。

    Model 适配器是可变状态的封装,它是由所谓的 reducer 进行实现的。Model 适配器提供了一 个 (用于发送事件的) 输入绑定,以及一个 (用于接收更新的) 输出绑定。

    在 MAVB 中,你不会去直接创建 view;相对地,你只会去创建 view 绑定器。同样地,你也从 来不会去处理 model 适配器以外的可变状态。在 view 绑定器和 model 适配器之间的 (两个方 向上的) 变换,是通过 (使用标准的响应式编程技术) 来对绑定进行变形而完成的。

    MAVB 移除了对 controller 层的需求。创建逻辑通过 view 绑定器来表达,变换逻辑通过绑定来 表达,而状态变更则通过 model 适配器来表达。结果得到的框图如下:

    在这里插入图片描述

    1. 构建
      Model 适配器 (用来封装主 model ) 和 view state 适配器 (封装顶层的 view state) 通常是在
      main.swift 文件中进行创建的,这早于任何的 view。
      View 绑定器使用普通的函数进行构建,这些函数接受必要的 model 适配器作为参数。实际的
      Cocoa view 则由框架负责进行创建。 2. 更改 Model
      当一个 view (或者 view controller) 可以发出 action 时,对应的 view 绑定允许我们指定一个 action 绑定。在这里,数据从 view 流向 action 绑定的输出端。典型情况下,输出端会与一个 model 适配器相连接,view 事件会通过绑定进行变形,成为 model 适配器可以理解的一条消 息。这条消息随后被 model 适配器的 reducer 使用,并改变状态。
    2. 更改 View
      当 model 适配器的状态发生改变时,它会通过输出信号产生通知。在 view 绑定器中,我们可 以将 model 适配器的输出信号进行变形,并将它绑定到一个 view 属性上去。这样一来,view 属性就会在一个通知被发送时自动进行变更了。
    3. View State
      View state 被认为是 model 层的一部分。View state action 以及 view state 通知和 model action 以及 model 通知享有同样的路径。
    4. 测试
      在 MAVB 中,我们通过测试 view 绑定器来测试代码。由于 view 绑定器是一组绑定的列表,我 们可以验证绑定包含了我们所期望的条目,而且它们的配置正确无误。我们可以和使用绑定来 测试初始构建以及发生变化时的情况。
      在 MAVB 中进行的测试,与在 MVVM 中的测试很相似。不过,在 MVVM 中,view controller 有可能会包含逻辑,这导致在 view-model 和 view 之间有可能会存在没有测试到的代码。而 MAVB 中不存在 view controller,绑定代码是 model 适配器和 view 绑定器之间的唯一的代码, 这样一来,保证完整的测试覆盖要简单得多。
    • MAVB 的重要性
      在我们所讨论的主要模式之中,MAVB 没有遵循某个直接的先例,它既不是从其他平台移植过 来的模式,也不是其他模式的变种。它自成一派,用于试验目的,而且一些奇怪。我们在这儿 介绍它的意义在于,它展示了一些很不一样的东西。不过,这并不是说这个模式没有从其他模 式中借鉴经验教训:像是绑定、响应式编程、领域专用语言以及 reducer 都是已经被熟知的想 法了。
    • 历史
      MAVB 是 Matt Gallagher 在 Cocoa with Love 网站上首先提出的。这个模式参照了 Cocoa 绑 定、函数式响应动画、ComponentKit、XAML、Redux 以及成千上万行的使用 Cocoa view controller 的经验。
      本书中的实现使用了 CwlViews 框架来处理 view 构建、绑定器和适配器的实现等工作。

    5. Elm 架构 (TEA)

    TEA 和 MVC 有着根本上的不同。在 TEA 中,model 和所有的 view state 被集成为一个单个状 态对象,所有 app 中的变化都通过向状态对象发送消息来发生,一个叫做 reducer 的状态更新 函数负责处理这些消息。
    在 TEA 中,每个状态的改变会生成一个新的虚拟 view 层级,它由轻量级的结构体组成,描述 了 view 层级应该看上去的形式。虚拟 view 层级让我们能够使用纯函数的方式来写 view 部分 的代码;虚拟 view 层级总是直接从状态进行计算,中间不会有任何副作用。当状态发生改变 时,我们使用同样的函数重新计算 view 层级,而不是直接去改变 view 层级。
    Driver 类型 (这是 TEA 框架中的一部分,它负责持有对 TEA 中其他层的引用) 将对虚拟 view 层 级和 UIView 层级进行比较,并且对它进行必要的更改,让 view 和它们的虚拟版本相符合。这 个 TEA 框架中的 driver (驱动) 部件是随着我们 app 的启动而被初始化的,它自身并不知道要对 应哪个特定的 app。我们要在它的初始化方法中传入这些信息:包括 app 的初始状态,一个通 过消息更新状态的函数,一个根据给定状态渲染虚拟 view 层级的函数,以及一个根据给定状态 计算通知订阅的函数 (比如,我们可以订阅某个 model store 更改时所发出的通知)。
    从框架的使用者的视⻆来看,TEA 的关于更改部分的框图是这样的:

    在这里插入图片描述
    如果我们追踪这张图表的上面两层,我们会发现在 view 和 model 之间存在我们在本章开头是 就说过的反馈回路;这是一个从 view 到状态,然后再返回 view 的回路 (通过 TEA 框架进行协 调)。
    下面的回路代表的是 TEA中处理副作用的方式 (比如将数据写入磁盘中):当在状态更新方法中 处理消息时,我们可以返回一个命令,这些命令会被 driver 所执行。在我们的例子中,最重要 的命令是更改 store 中的内容,store 反过来又被 driver 所持有的订阅者监听。这些订阅者可 以触发消息来改变状态,状态最终触发 view 的重新渲染作为响应。
    这些事件回路的结构让 TEA 成为了遵守单向数据流原则的设计模式的另一个例子。

    1. 构建
      状态在启动时被构建,并传递给运行时系统 (也就是 driver)。运行时系统拥有状态,store 是一 个单例。
      初始的 view 层级和之后更新时的 view 层级是通过同样的路径构建的:通过当前的状态,计算 出虚拟 view 层级,运行时系统负责更新真实的 view 层级,让它与虚拟 view 层级相匹配。
    2. 更改 Model
      虚拟 view 拥有与它们所关联的消息,这些消息在一个 view 事件发生时会被发送。Driver 可以 接收这些消息,并使用更新方法来改变状态。更新方法可以返回一个命令 (副作用),比如我们
      想在 store 中进行的改动。Driver 会截获该命令并执行它。TEA 让 view 不可能直接对状态或者 store 进行更改。
    3. 更改 View
      运行时系统负责这件事。改变 view 的唯一方式是改变状态。所以,初始化创建 view 层级和更
      新 view 层级之间没有区别。 4. View State
      View state 是包含在整体的状态之中的。由于 view 是直接从状态中计算出来的,导航和交互状 态也同样会被自动更新。
    4. 测试
      在大多数架构中,让测试部件彼此相连往往要花费大量努力。在 TEA 中,我们不需要对此进行 测试,因为 driver 会自动处理这部分内容。类似地,我们不需要测试当状态变化时 view 会正确 随之变化。我们所需要测试的仅仅是对于给定的状态,虚拟 view 层级可以被正确计算。
      要测试状态的变更,我们可以创建一个给定的状态,然后使用 update 方法和对应的消息来改 变状态。然后通过对比之前和之后的状态,我们就可以验证 update 是否对给定的状态和消息 返回了所期望的结果。在 TEA 中,我们还可以测试对应给定状态的订阅是不是正确。和 view 层级一样,update 函数和订阅也都是纯函数。
      因为所有的部件 (计算虚拟 view 层级,更新函数和订阅) 都是纯函数,我们可以对它们进行完 全隔离的测试。任何框架部件的初始化都是不需要的,我们只用将参数传递进去,然后验证结 果就行了。我们 TEA 实现中的大多数测试都非常直截了当。
    • Elm 架构的重要性
      TEA 最早是在 Elm 这⻔函数式语言中被实现的。所以 TEA 是一种如何用函数式的方法表达 GUI 编程的尝试。TEA 同时也是最为古老的单向数据流架构。

    • 历史
      Elm 是 Evan Czaplicki 所设计的函数式编程语言,它最初的目的是为了构建前端 web app。 TEA 是归功于 Elm 社区的一个模式,它的出现是语言约束和目标环境相互作用的自然结果。它 背后的思想影响了很多其他的基于 web 的框架,其中包括 React、Redux 和 Flux 等。在 Swift 中,还没有 TEA 的权威实现,不过我们可以找到不少研究型的项目。在本书中,我们使用 Swift 按我们自己的理解实现了这个模式。主要的工作由 Chris Eidhof 于 2017 年完成。虽然我 们的这个实现还并不是 “产品级” 的,但是许多想法是可以用在生产代码中的。

    三,其他APP架构模式

    1. Model-View-Presenter

    Model-View-Presenter (MVP) 是一种在 Android 上很流行的模式,在 iOS 中,也有相应的实 现。在总体结构和使用的技术上,它粗略来说是一种位于标准 MVC 和 MVVM 之间的模式。

    MVP 使用单独的 presenter 对象,它和 MVVM 中 view-model 所扮演的⻆色一样。相对 view-model 而言,presenter 去除了响应式编程的部分,而是把要展示的值暴露为接口上的属 性。不过,每当这些值需要变更的时候,presenter 会立即将它们推送到下面的 view 中去 (view 将自己作为协议暴露给 presenter)。
    从抽象的观点来看,MVP 和 MVC 很像。Cocoa 的 MVC,除了名字以外,就是一个 MVP - 它是 从上世纪九十年代 Taligent 的原始的 MVP 实现中派生出来的。View,状态和关联的逻辑在两 个模式中都是一样的。不同之处在于,现代的 MVP 中有一个分离的 presenter 实体,它使用协 议来在 presenter 和 view controller 之间进行界定,Cocoa 的 MVC 让 controller 能够直接引 用 view,而 MVP 中的 presenter 只能知道 view 的协议。

    有些开发者认为协议的分离对于测试是必要的。当我们在讨论测试时,我们会看到标准的 MVC 在没有任何分离的情况下,也可以被完整测试。所以,我们感觉 MVP 并没有太大不同。如果我 们对测试一个完全解耦的展示层有强烈需求的话,我们认为 MVVM 的方式更简单一些:让 view controller 通过观察去从 view-model 中拉取值,而不是让 presenter 将值推送到一个协 议中去。

    2. VIPER,Riblets,和其他 “Clean” 架构

    VIPER,Riblets 和其他类似的模式尝试将 Robert Martin 的 “Clean Architecture” 从 web app 带到 iOS 开发中,它们主要把 controller 的职责分散到三到四个不同的类中,并用严格的顺序 将它们排列起来。在序列中的每个类都不允许直接引用序列中前面的类。

    为了强制单方向的引用这一规则,这些模式需要非常多的协议,类,以及在不同层中传递数据 的方式。由于这个原因,很多使用这些模式的开发者会去使用代码生成器。我们的感觉是,这 些代码生成器,以及任何的繁杂到需要生成器的模式,都产生了一些误导。将 “Clean” 架构带 到 Cocoa 的尝试通常都宣称它们可以管理 view controller 的 “肥大化” 问题,但是让人啼笑皆 非的是,这么做往往让代码库变得更大。

    虽然将接口分解是控制代码尺寸的一种有效手段,但是我们认为这应该按需进行,而不是教条 式地对每个 view controller 都这么操作。分解接口需要我们对数据以及所涉及到的任务有清楚 的认识,只有这样,我们才能达到最优的抽象,并在最大程度上降低代码的复杂度。

    3. 基于组件的架构 (React Native)

    如果你选择使用 JavaScript 而不是 Swift 编程,或者你的 app 重度依赖于 web API 的交互, JavaScript 会是更好的选择,这时你可能会考虑 React Native。不过,本书是专注于 Swift 和 Cocoa 的,所以我们将探索模式的界限定在了这些领域内。

    如果你想要找一些类似 React Native,但是是基于 Swift 的东西的话,可以看看我们对 TEA 的 探索。MAVB 的实现也从 ComponentKit 中获得了一些启发,而 ComponentKit 本身又从 React 中获取灵感:它使用类 DSL 的语法来进行声明式和可变形的 view 构建,这和 React 中 Component 的 render 方法及其相似。

    展开全文
  • 一、 js 与 原生OC交互方式: ...在iOS 7 之后Apple添加了一个新的库JavaScriptCore,用来做js交互。 首先导入JavaScriptCore 库,然后在OC 中获取上下文对象。在定义好JS需要调用的方法。JSContext对象conte...

    一、 js 与 原生OC交互方式:

           1.JS发起一个假请求,然后用UIwebView的代理方法拦截这起请求,再做相应的处理

           2.在iOS 7 之后Apple添加了一个新的库JavaScriptCore,用来做js交互。

           首先导入JavaScriptCore 库,然后在OC 中获取上下文对象。在定义好JS需要调用的方法。JSContext对象context[@”share”] 等于一个返回值为空的block。这个block 在子线程中调用,因此执行UI 操作需要回到主线程

    二、 OC调用JS

           1、webView stringByEvaluatingJavaScriptFromString:jsStr];

           2、继续使用JavaScriptCore库  JSContext 对象调用 evaluateScript:方法

           以上两个方法都是同步方法,如果JS方法比较耗时会造成界面卡顿。

           所以可以使用wkwebview 的 evaluateJavaScript:代替

          

    WKWebView优势:

    运行速度更快,占用内存低,大概是UIwebView 的四分之一到三分之一

    多进程,在APP的主进程之外执行;为空webView为多进程组件,他会从APP内存中分离内存到单独的进程中。当内存超过了系统分配给为空webView的内存时候,会导致为空webView浏览器崩溃白屏,但是APP不会crash。(APP会收到系统通知,并且尝试去重新加载页面)

    相反的UIwebView 和APP同一个进程,内存不够用时就会crash ,从而导致APP crash

    wkwebview 使用和手机Safari浏览器一样的nitro JavaScript引擎,相比于UIwebView的javaScript 引擎有非常大的性能提升

    wkwebview 是异步处理APP原生代码与JavaScript之间的通信,因此普遍上执行速度会更快

    消除了触摸延迟

    缺点:

    不能截屏

    不支持记录webkit 的请求

    APP退出会清湖HTML5的本地存储数据

    不支持accept cookies 的设置

    需要iOS 9 或更高版本

     

    三、线程

           线程安全

           1、互斥锁     @synchronized(所对象){}

           atomic  原子属性  为setter方法加锁   线程安全需要消耗大量的资源

           nonatomic  非原子属性

           2、NSLock

    3、递归锁 NSRecursivelock

    4、NSConditionLock条件锁

    5、GCD 信号量  dispatch_semaphore

    6、自选锁

    1、@synchronized 的效率最低,不过它的确用起来最方便,所以如果没什么性能瓶颈的话,可以选择使用 @synchronized。
    2、当性能要求较高时候,可以使用 pthread_mutex 或者 dispath_semaphore,由于 OSSpinLock 不能很好的保证线程安全,而在只有在 iOS10 中才有 os_unfair_lock ,所以,前两个是比较好的选择。既可以保证速度,又可以保证线程安全。
    3、对于 NSLock 及其子类,速度来说 NSLock < NSCondition < NSRecursiveLock < NSConditionLock 。

    线程间通信:

    两个线程之间要想互相通信,可以使用:NSMachPort 

    //1. 创建主线程的port    // 子线程通过此端口发送消息给主线程    NSPort *myPort = [NSMachPort port];

        //2. 设置port的代理回调对象    myPort.delegate = self;

        //3. 把port加入runloop,接收port消息    [[NSRunLoop currentRunLoop] addPort:myPort forMode:NSDefaultRunLoopMode];

        NSLog(@"---myport %@", myPort);

        //4. 启动次线程,并传入主线程的port    MyWorkerClass *work = [[MyWorkerClass alloc] init];

    (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;

    - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;

    进程间通信;

    共享存储系统消息传递系统管道:以文件系统为基础

    URL scheme

    Keychain

    Uipasteboard

    UIDocumentInteractionController

    Local socket

    Airdrop

    UiactivityViewController

    APPgroups

     

     

    线程保活:

    循环

    runloop

    1.获取RunLoop只能使用 [NSRunLoop currentRunLoop] 或 [NSRunLoop mainRunLoop];

    2.即使RunLoop开始运行,如果RunLoop 中的 modes 为空,或者要执行的mode里没有item,那么RunLoop会直接在当前loop中返回,并进入睡眠状态。

    3.自己创建的Thread中的任务是在kCFRunLoopDefaultMode这个mode中执行的。

    4.在子线程创建好后,最好所有的任务都放在AutoreleasePool中。

    如果不执行下列语句:

    [runLoop addPort:[NSMachPort port] forMode:NSRunLoopCommonModes];

     

     

    Runloop

    就是运行循环。保持程序的持续运行、处理APP中的各种事件(手势定时器等)

    节省CPU资源提高程序的性能,在有任务的时候做任务 ,在没任务的时候休息 空转

    runloop 和线程是一对一的

    系统默认五个mode

    NSDefaultRunloopMode

    UITrackingRunloopMode  为了保证滑动ScrollView滑动不受影响,在滑动的时候就主动切换到这个mode运行

    UITInitializationRunLoopMode  在刚启动APP的时候第一次进入的mode

    GSEventReceive  接收系统内部事件

    Common    包含default 和UItrackingMode  

    应用:

    1、延迟显示UIimageView 用runloop   performSelector:withObject:afterDelay:inmodes:

    2、NSTimer  需要加入mode

    3、常驻线程  线程保活

    4、在创建场主线程的时候加入 @autoreleasepool,在runloop睡眠的时候释放

     

    定时器:

    1. NSTimer 通过runloop来是实现,一般情况下较为准确,但当当前循环耗时操作较多时会出现延时的问题。同事也受所加入的runloopmode 的影响,commonmode(包含default、UItracking)
    2. CADisplayLink是基于屏幕刷新的周期,所以其一般很准时,每秒60次。其本质也是通过runloop,所以存在和NSTimer相同的问题
    3. GCD定时器是dispatch_source_t类型的变量,其可以实现更加精准的定时效果。GCD定时器实际上是使用了dispatch源(dispatch source),dispatch源监听系统内核对象并处理。通过系统级调用更加精准   (dispatch类似生产者消费者模式,通过监听系统内核对象,在生产者生产数据后自动通知相应的dispatch队列执行,后者充当消费者)。GCD通过dispatch_suspend()释放定时器

     

    ViewDidload 什么时候调用:(界面初始话操作,加载数据等)在view创建完毕后,不管是通过xib、Storyboard还是loadview自定义view

    1. view被加载的时候
    2. view Controller 用代码创建的时候
    3. view Controller通过nib解析的时候

    在UIViewController 的初始化方法中访问实例变量view,会导致延迟加载机制失效,会受到内存警告

    当访问UIViewController中的self.view时,如果view为nil 就会调用loadview

     

     

    iOS 程序在main 函数之前:

    1. 首先加载可执行文件
    2. 然后加载苹果的动态链接器dyld,(dyld是一个专门用来加载动态链接库的库)
    3. 执行从dyld开始,dyld从可执行的文件开始,递归加载所有的依赖动态链接库
    4. 动态链接库包括:iOS中用到的所以系统的framework,加载OC runtime方法的libobjec,系统级别的libSystem
    5. 所有动态链接库和我们APP的静态库.a和所有类文件编译后的.o文件,最终都由dyld 加载到内存中

    整个事件由苹果的动态链接器主导,完成运行环境的初始化后,配合imageLoader将二进制文件按格式加载到内存。

     

    OC 方法调用的过程原理:

    OC中的所有方法调用,最终都是转换成runtime中的一个C语言消息分发函数:objc_msgSend(消息接收者,方法名 ,参数。。。)

    这条消息发送之后,系统会在receiver的类对象的方法了吧中找这个方法,如果没找到,再到receiver的父类的方法列表中找,如此直到根类至找到为止,如果还没有找到会报出错误。(缓存:方法第一次被调用之后,方法会被存入一张缓存表,之后如果再被调用时就直接从缓存表中取出,以提高效率)。

    Runtime中对调用过程做了缓存,在抛出错误之前会进行动态决议和消息转发过程。

    若对象无法响应某个选择子,则进入消息转发流程:

    1、动态方法解析:+bool) resolveInstanceMethod:(SEL)selector

                               +(bool)resolvelassMethod:(SEL)selector

    2、备用接受者:

    • (id)forwardingargetForSelector(SEL)slector  (把这条消息转发给其他对象处理)
    1. 获取方法签名进行消息转发

    - (NSMethodSignature*)methodSignatureForSelector:

    1. 完整的消息转发

    - (void)forwardingInvocation(NSInvocation*)invocateion

     1、通过运行期的动态方法解析功能,我们可以在需要某个方法是在将其加入类中

    2、对象可以把其无法解读的某些消息转交给其他对象来处理

    3、经过上述两步后,如果还是没有办法处理消息,那就启动完整的消息转发机制

     

     

    OC类结构

    OC类是objc_class结构体

    它里面有isa指针、指向父类的super_class 指针、类名、类的版本信息、该类的实例变量大小、类信息供运行期使用的一些标识符、类的成员变量链表、方法定义的链表、方法缓存、协议链表

     

     

    UIView 和 CALayer

    所有的view都是由一个底层的Layer来驱动。Layer侧重于图形的显示,而view相当于layer的管理者。

    UIView 继承与UIResponder 而 CALayer 继承于NSObject。所以UIView 可以响应事件,而CALayer 则不能。

    每个UIView内部都有一个CALayer在背后提供内容的绘制和显示。两者都有树状层级结构,layer 内部有sublayers,view 内部有subviews

    layer 内部维护着三份layer tree ,分别是动画树、模型树、渲染树,在iOS 做动画的时候,我们修改动画的属性,在动画的其实是动画树,而最终展示在界面上的其实是提供view的modelayer

     

    设计模式

    1. 单例模式: 确保程序运行期某个类只有一个实例对象,用于资源共享控制
    2. 代理模式:一对一反向传值。当一个类的某些功能需要别的类来实现,但是又不确定具体会是哪个类实现
    3. 观察者模式:

    通知:  notification通知中心,注册通知中心,任何位置可以发送消息,注册观察者的对象可以接收。

    KVO 键值对改变  通知观察者

           4、工厂模式:工厂方式创建类的实例

    5、MVC 模式 :model 、view 、control  模型、视图、控制器对应用程序进行数据处理、业务逻辑和视图展示解耦

    6、MVVM模式: model、view、viewModel  将MVC中controller的业务逻辑提取到viewModel层,进行解耦合

    设计模式:并不是一种新技术,而是一种编码经验。 mvc设计模式 :模型,视图,控制器,可以将整个应用程序在思想上分成三大块,对应是的数据的存储或处理,前台的显示,业务逻辑的控制。  代理模式:代理模式给某一个对象提供一个代理对象,并由代理对象控制对源对象的引用单例模式:说白了就是一个类不通过alloc方式创建对象,而是用一个静态方法返回这个类的对象。系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为,比如想获得[UIApplication sharedApplication];任何地方调用都可以得到 UIApplication的对象,这个对象是全局唯一的。  观察者模式: 当一个物体发生变化时,会通知所有观察这个物体的观察者让其做出反应。实现起来无非就是把所有观察者的对象给这个物体,当这个物体的发生改变,就会调用遍历所有观察者的对象调用观察者的方法从而达到通知观察者的目的。  工厂模式:可以简单概括为同类型不同型号的产品有各自对应的工厂进行生产。

     

     

    @autoreleasepool

    1. 是自动释放池,让我们更自由的管理内存
    2. 当我们手动创建了一个@autoreleasepool,里面创建了很多临时变量,当@autoreleasepool结束的时候,里面的内存就回回收
    3. ARC 系统自动管理自己的autoreleasepool,runloop就开始iOS 中的消息循环机制,当一个runloop结束时系统才会一次性清理掉呗autoreleasepool 处理过的对象,其实本质上说是在本次runloop迭代结束时清理掉本次迭代期间被放到autoreleasepool中的对象。至于何时runloop结束并没有固定的duration。

     

    会产生大量临时变量的时候使用@autoreleasepool

    循环中创建了很多的临时对象,使用@autoreleasepool

    你生成了一个辅助数据线程,使用 @autoreleasepool

    长期在后台运行的任务

     

     

     

    Static

    Static 修饰局部变量 ,只会初始化一次,并且在程序中只有一份内存,可以延长局部变量的生命周期,改变了知道整个项目结束时才会被销毁

    Static修饰全局变量时,作用域仅限于当前文件

    1).函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值; 2).在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问; 3).在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内; 4).在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝; 5).在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量。

     

     

     

    Http 请求方式:

    1. opions  返回服务器针对特定资源所支持的HTML请求方法 或 允许客户端查看服务器性能
    2. get 向特定资源发出请求
    3. post 向指定资源提交数据(提交表单、上传文件)
    4. put 向指定资源位置上上传其最新内容
    5. head  与get请求类似,返回的响应中没有具体内容,用于获取报头
    6. delete 请求服务器删除request-URl所表示的资源
    7. trace 回显服务器收到的请求,用于测试和诊断
    8. connect 能够将连接改为管道方式的代理服务器

     

    在项目什么时候选择使用GCD,什么时候选择NSOperation?
    答: 项目中使用NSOperation的优点是NSOperation是对线程的高度抽象,在项目中使用它,会使项目的程序结构更好,子类化NSOperation的设计思路,是具有面向对象的优点(复用、封装),使得实现是多线程支持,而接口简单,建议在复杂项目中使用。
    项目中使用GCD的优点是GCD本身非常简单、易用,对于不复杂的多线程操作,会节省代码量,而Block参数的使用,会是代码更为易读,建议在简单项目中使用


     

    线程与进程的区别和联系

    1). 进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性 2). 进程和线程的主要差别在于它们是不同的操作系统资源管理方式。 3). 进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。 4.)线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉。所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。 5). 但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

     

    一、TCP 是传输控制协议  transport control protocol  ,基于字节流传输,有连接,可以提供可靠地通信传输

           TCP充分实现了数据传输时的各种控制功能,可以进行丢包的重发,还可以对次序乱掉的分包进行顺序控制。TCP 作为一种面向连接的传输协议,只有在确认通信端存在时才会发送数据,从而避免数据流量的浪费。TCP 通过检验和、序列号、确认应答 和重发控制等机制实现可靠性传输。TCP 连接只能是点到点

    二、UDP 是用户数据协议 user data protocol ,基于数据报,无连接,不可靠

          UDP将部分控制转移到应用程序去处理,自己只提供作为传输层协议的最基本功能。对丢包乱序不做处理,UDP 支持 一对一、一对多、多对一、多对多通信

     

    编程步骤: TCP  1、创建一个socket    2、设置socket属性   3、绑定IP地址 端口信息到socket 上bind()    4、设置要连接的对方的IP地址和端口号   5、连接服务器 connect()   6、收发数据  receive ()  send() 7、关闭网络连接

             UDP  1、创建一个socket    2、设置socket属性   3、绑定IP地址 端口信息到socket 上bind()    4、设置要连接的对方的IP地址和端口号   5、发送数据 sendto()    6、关闭网络连接

     

    Viewcontroller 生命周期

    当一个视图控制器被创建,并在屏幕上现实的时候

    1、alloc   2、init  3、loadview  4、viewdidload  5、viewwillappear  6、viewdidappear

    当一个视图被移除屏幕并且销毁的时候的执行顺序

    1、viewwilldisappear   2、viewdiddisappear   3、dealloc

    关于viewdidunload  在发生内存警告的时候如果本视图不是当前屏幕正在显示的视图的话,viewdidunload将会被执行,本视图的所有子视图将被销毁已释放内存,此时开发者需要手动释放该控制器中创建的对象。

     

    iOS  APP性能测试:

    instrument

    1、leaks 内存泄漏  ,一般查看内存的使用情况,检查泄漏的内存,并提供了所有活动的分配和泄漏模块的类对象分配统计信息以及内存地址历史记录

    2、time profile 时间探测: 分析代码的执行时间,找出导致程序变慢的原因

    3、allocations 内存分配:检测内存使用、分配情况。跟踪工程的匿名虚拟内存和堆的对象提供类名和可选保留释放历史

     

    事件的分发和传递

    1. 当iOS 程序中发生触摸事件后,系统会将事件加入到UIApplication管理的一个任务队列中
    2. UIApplication将处于任务队列最前端的事件向下分发。即UIWindow
    3. UIWindow将事件向下分发,即UIView
    4. UIView 首先看自己是否能处理事件,触摸点是否在自己身上。如果能,那么继续寻找子视图
    5. 遍历子控件,重复以上两步
    6. 如果没有找到,那么自己就是事件处理者
    7. 如果自己不能处理,那么不做任何事情
    8. 该事件被废弃

    其中UIView 不接受事件处理的情况主要有一下三种:alph< 0.01   userinteractionEnable = NO   hidden = yes

     

    这个从父控件到子控件寻找处理时间最合适的view过程,如果父视图不接受事件处理,则子视图也不能接收事件

     

           响应者链:

           响应链是从最合适的view开始传递,处理事件传递给下一个响应者,响应者链的传递方向是事件传递的反方向,如果所有响应者都不处理事件,则事件被丢弃。

     

     

    数据持久化

    1、属性列表plist   用于存储在程序中不经常修改、数据量小的数据,不支持自定义对象存储

    2、nsuserdefautls  同样适合于存储轻量级数据,本质上就是一个plist ,也不支持自定义对象存储

    3、归档序列化存储

    可以直接将对象存储为文件,也可将文件直接解归档为对象,相对于plist文件与nsuserdefault  存储更加多样,支持自定义对象存储,归档后的文件是加密的,也更加安全

    4、Core data 

    5、数据库  FMDB

     

    谓词 NSPredicate 

    通过设置逻辑条件 对数据进行过滤

     

    volatile  是一个类型修饰符。该变量可能会被意想不到的改变。优化器在使用个这个变量时必须每次都小心的重新读取这个变量的值,而不是使用保存在寄存器里的备份。

    1. 并行设备的硬件寄存器
    2. 一个中断服务子程序中会访问到的非自动变量
    3. 多线程应用中被几个任务共享的变量

     

    一个参数既可以是const 还可以是volatile。一个例子是只读的状态寄存器,他可能会被意想不到的改变,而程序不应该视图去修改他

    一个指针可以使volatile。当一个中断服务子程序修改一个指向一个buffer的指针时

     

    什么是push

    客户端程序留下后门端口,客户端总是监听针对这个后门的请求,于是 服务器可以主动像这个端口推送消息

     

     

    常见第三方库:afnetworking 、SDWebImageView、Reactive Cocoa、 React Native

     

    block 本质: 是带有函数执行上下文环境的结构体,其中包含被调函数的指针

     

    离屏渲染:

    离屏渲染指的是GPU在当前屏幕缓冲区意外开辟了一个缓冲区进行渲染操作。对性能的影响主要是因为:创建了新的缓冲区以及上下文的频繁切换

    导致离屏渲染的原因:

    shouldRasterize 光栅化、遮罩masks、shadows 阴影、edgeantialiasing 抗锯齿、不透明、复杂形状设置圆角等、渐变

     

     

    UIView 的绘制原理

    当我们调用[UIView setNeedsDisplay]这个方法时 ,其实并没有立即进行绘制工作,系统会立即调用CALayer的同名方法,并且会在当前layer上打上一个标记,然后会在当前runloop将要结束的时候调用【CALayer display】这个方法 然后进入视图的真正绘制过程

    在CALayer display 这个方法的内部实现中会判断这个layer的delegate是否响应displaylayer这个方法,如果不响应这个方法,就回进入到系统会址流程中,如果响应这个方法,那么就会为我们提供异步绘制的入口

    异步绘制

    1假如我们在某一个时机调用了【view setNeedsDisplay】这个方法,系统会在当前runloop将要结束的时候调用【CALayer display】方法,然后如果我们这个layer的代理实现了【view displayerlayer】这个方法

    2、然后会通过子线程的切换,我们在子线程中去做一个位图的绘制,主线程可以去做一些其他的操作

    3、 在子线程中创建一个位图的上下文,然后通过CoregraphIC API 可以做当前UI空间的一些绘制工作,最后再通过CGBitmapContextCreateImage()这个函数来根据当前所绘制的上下文来生成一张cgimage图片

           4、最后回到主线程来提交这个位图,设置layer的contents属性,这样就完成了一个UI控件的异步绘制

     

     

    分类的实现原理:

    分类在编译过程中,会生成  类方法列表、实例方法列表、属性列表等,但是却没有 实例变量列表,分类所属类是存在实例变量列表的。对比实例方法列表,可以发现 分类的实例方法列表中,并未对分类属性生成getter /setter方法

    分类是在运行时进行加载的。

    把分类的饿实例方法、属性、协议 添加到类的实例对象中原本存储的实例方法、属性、协议列表的前面

    把分类的类方法和协议添加到类的元类上

     

     

    应用多线程的时候会出现什么问题,应如何避免问题的发生?

    多线程容易导致资源争抢,发生死锁现象.死锁通常是一个线程锁定了一个资源A,而又想去锁定资源B;在另一个线程中,锁定了资源B,而又想去锁定资源A以完成自身的操作,两个线程都想得到对方的资源,而不愿释放自己的资源,造成两个线程都在相互等待,造成了无法执行的情况。 

    避免死锁的一个通用的经验法则是:当几个线程都要访问共享资源A、B、C时,保证使每个线程都按照同样的顺序去访问它们,比如都先访问A,在访问B和C

    采用GCD中的栅栏方法,用并行队列去装载事件并异步去执行

     

    构建缓存时选用NSCache而非NSDictionary

    当系统资源将要耗尽时,NSCache可以自动删减缓存。如果采用普通的字典,那么就要自己编写挂钩,在系统发出"低内存"通知时手工删减缓存,NSCache会先行删减"最久未使用的"对象。

    NSCache并不会"拷贝"键,而是会"保留"它。此行为用NSDictionary也可以实现,但是需要编写比较复杂的代码。NSCache对象不拷贝键的原因在于:很多时候,键都是由不支持拷贝操作的对象来充当的。因此,NSCache对象不会自动拷贝键,所以说,在键不支持拷贝操作的情况下,该类用起来比字典更方便。

    NSCache是线程安全的,NSDictionary不是。在开发者自己不编写加锁代码的前提下,多个线程便可以同时访问NSCache。对缓存来说,线程安全通常很重要,因为开发者可能要在某个线程中读取数据,此时如果发现缓存里找不到指定的键,那么就要下载该键所对应的数据了。

    Static

    1).函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值; 2).在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问; 3).在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内; 4).在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝; 5).在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量。

     

    AsyncDisplayKit的使用

    它是一个UI框架,能在异步线程绘制修改UI,然后统一添加进内存 渲染出来。

    造成卡顿的原因:CPU 或 GPU消耗过大,导致再一次同步信号之间没有准备完成,没有内容提交,导致掉帧问题。

    优化原理:

    1. 布局:iOS 自带的autolayout在布局上存在性能瓶颈,并且只能在主线程进行计算。因此asdk弃用了autolayout自己设计了一套布局方案
    2. 渲染:对于大量文本、图片等的渲染,uikit组件只能在主线程并且可能会造成GPU绘制的资源紧张。ASDK 使用了一些方法,如图层的预混合、并且异步在后台绘制图层,不阻塞主线程的运行
    3. 系统对象创建与销毁:uikit组件封装了CALayer图层的对象,在创建、调整销毁的时候,都会在主线程消耗资源。ASDK设计了一套NODE机制,也能够调用

    ASDK最大特点就是异步。将消耗时间的渲染、布局、图片解码、及其他UI操作全部移出主线程,这样主线程就可以及时响应用户的操作,来达到流畅运行的目的

     

    iOS 应用加密技术防止反编译

    1. 本地数据加密
    2. URL编码加密
    3. 网络传输数据加密
    4. 方法体、方法名高度混淆
    5. 程序结构混排加密
    展开全文
  • iOS 各种项目源码集

    2018-07-20 15:00:49
    一:源代码实例 ...2:高仿美团iOS版 地址:https://github.com/lookingstars/meituan 3:模仿网易新闻做的精仿网易新闻 地址:https://github.com/dsxNiubility/SXNews 4:支付宝高仿版 地址:h...

    一:源代码实例

    1:快速搭建项目源代码

    地址:https://github.com/wujunyang/MobileProject

    2:高仿美团iOS版

    地址:https://github.com/lookingstars/meituan

    3:模仿网易新闻做的精仿网易新闻

    地址:https://github.com/dsxNiubility/SXNews

    4:支付宝高仿版

    地址:https://github.com/gsdios/GSD_ZHIFUBAO

    5:高仿百度传课iOS版

    地址:https://github.com/lookingstars/chuanke

    6:模仿一元云购

    地址:https://github.com/JxbSir/YiYuanYunGou

    7:wordpress源代码

    地址:https://github.com/wordpress-mobile/WordPress-iOS

    8:v2ex源代码(文章类型,若报SVProgressHUD错,则把Podfile中的SVProgressHUD移除)

    地址:https://github.com/singro/v2ex

    9:PHPHub客户端(IOS8.0以上)

    地址:https://github.com/Aufree/phphub-ios

    10:Coding.NET客户端

    地址:https://coding.net/u/coding/p/Coding-iOS/git

    11:如何优化UITableView中Cell加载图片的实例

    地址:https://github.com/allenhsu/UIScrollView-Samples/tree/master/LazyLoad

    12:开源的IOS代码集合

    地址:https://github.com/dkhamsing/open-source-ios-apps

    二:辅助软件

    1:XCODE文档注解插件VVDocumenter

    地址:https://github.com/onevcat/VVDocumenter-Xcode

    2:将JSON格式化输出为模型的属性

    地址:https://github.com/EnjoySR/ESJsonFormat-Xcode

    3:图片提示插件

    地址:https://github.com/ksuther/KSImageNamed-Xcode

    4:图片转换插件

    地址:https://github.com/rickytan/RTImageAssets

    5:测试模拟苹果通知

    地址:https://github.com/KnuffApp/Knuff

    6: HOStringSense可以在弹出框写NSString,所见及所得

    地址:https://github.com/holtwick/HOStringSense-for-Xcode

    7:cocoapods-xcode-plugin  pod相关的操作可以在xcode菜单进行

    地址:https://github.com/kattrali/cocoapods-xcode-plugin

    8:switch枚举的时候会自动生成代码

    地址:https://github.com/stefanceriu/SCXcodeSwitchExpander

    9:Git中关于各个语言的gitignore

    地址:https://github.com/github/gitignore

    10:FLEX(Flipboard Explorer)是Flipboard官方发布的一组专门用于iOS开发的应用内调试工具

    地址:https://github.com/Flipboard/FLEX

    11:ponyDebugger是一个远程调试工具包,通过使用Chrome开发者工具来调试iOS应用的网络流量和数据存储

    地址:https://github.com/square/PonyDebugger

    12: OC编码风格规范

    地址:https://github.com/NYTimes/objective-c-style-guide

    13:FBMemoryProfiler:Facebook出品的一个实时监测内存使用的库。相比于Xcode自带的Instruments

    地址:https://github.com/facebook/FBMemoryProfiler

    14:app卡顿问题检测--KMCGeigerCounter(实例可以网上搜索)

    地址:https://github.com/kconner/KMCGeigerCounter/

    15:生成类的关系图KSHObjcUML

    地址:https://github.com/kimsungwhee/KSHObjcUML

    16:realm-cocoa实体映射数据库,有自个的数据库(可以替换SQLITE,速度比较快)

    地址:https://github.com/realm/realm-cocoa

    17:创建文档API,可以快速让APP先调用,并行开发

    地址:https://apiary.io/

    18:直接查看虚拟器上的沙盒路径simpholders

    地址:http://www.maczapp.com/simpholders

    19:FastStub实现了类似的功能,能自动解析出某个类头文件,父类,所有protocol里面还没有被实现的方法(ctrl+cmd+k)

    地址:https://github.com/music4kid/FastStub-Xcode

    三:第三方插件

    1:基于响应式编程思想的oc

    地址:https://github.com/ReactiveCocoa/ReactiveCocoa

    2:hud提示框

    地址:https://github.com/jdg/MBProgressHUD

    3:XML/HTML解析

    地址:https://github.com/topfunky/hpple

    4:有文字输入时,能根据键盘是否弹出来调整自身显示内容的位置

    地址:https://github.com/michaeltyson/TPKeyboardAvoiding

    5:状态栏提示框

    地址:https://github.com/jaydee3/JDStatusBarNotification

    6:block工具包。将很多需要用delegate实现的方法整合成了block的形式

    地址:https://github.com/zwaldowski/BlocksKit

    7:图片加载

    地址:https://github.com/rs/SDWebImage

    8:正则表达式

    地址:https://github.com/wezm/RegexKitLite

    9:Masonry代码布局

    地址:https://github.com/SnapKit/Masonry

    10:弹出窗

    地址:https://github.com/sberrevoets/SDCAlertView

    11:Button的样式

    地址:https://github.com/mattlawer/BButton

    12:验证网络连接状态

    地址:https://github.com/tonymillion/Reachability

    13:自动计算表格行高

    地址:https://github.com/forkingdog/UITableView-FDTemplateLayoutCell

    14:关键帧基础动画框架,如动画效果的启动页

    地址:https://github.com/IFTTT/JazzHands

    15:iOS快速简单集成国内三大平台分享

    地址:https://github.com/xumeng/XMShareModule

    16:五项能力值展示的五边形

    地址:https://github.com/dsxNiubility/SXFiveScoreShow

    17:自动识别网址号码邮箱和表情的label

    地址:https://github.com/molon/MLEmojiLabel

    18:IM对话功能的封装

    地址:https://github.com/ZhipingYang/UUChatTableView

    19:字典转模型框架

    地址:https://github.com/CoderMJLee/MJExtension

    20:下拉上拉刷数据

    地址:https://github.com/CoderMJLee/MJRefresh

    21:表格行左右划动菜单

    地址:https://github.com/MortimerGoro/MGSwipeTableCell

    22:图文混搭

    地址:https://github.com/zhouande/TLAttributedLabel

    23:可以简单展示在UINavigationBar下方,类似Music app的播放列表视图,弹出菜单视图

    地址:https://github.com/DrummerB/BFNavigationBarDrawer

    24:比如筛选、模糊、优化、蒙版、调整大小、旋转以及保存等等。同时还提供了一个UIImageView子类从URL异步加载图片,并在下载完毕时展示图片。

    地址:https://github.com/Nyx0uf/NYXImagesKit

    25:底部TabBar

    地址:https://github.com/robbdimitrov/RDVTabBarController

    26:表情面版

    地址:https://github.com/ayushgoel/AGEmojiKeyboard

    27:记录框架

    地址:https://github.com/CocoaLumberjack/CocoaLumberjack

    28:IOS与JavaScript交互

    地址:https://github.com/marcuswestin/WebViewJavascriptBridge

    29:图表统计展示

    地址:https://github.com/kevinzhow/PNChart(或https://github.com/danielgindi/ios-charts)

    30:appStore评分

    地址:https://github.com/arashpayan/appirater

    31:iOS-Categories扩展类大全

    地址:https://github.com/shaojiankui/IOS-Categories

    32:扫描二维码,仿微信效果,带有扫描条

    地址:https://github.com/JxbSir/JxbScanQR

    33:动效弹出视图(弹出窗里面为文字,可以定义弹出的方向,及显示的时间)--AMPopTip

    地址:https://github.com/andreamazz/AMPopTip

    34:基于Masonry自动计算行高扩展

    地址:https://github.com/632840804/HYBMasonryAutoCellHeight

    35:模仿新浪微博弹出菜单

    地址:https://github.com/wwdc14/HyPopMenuView

    36:搜索历史标签

    地址:https://github.com/zhiwupei/SearchHistory

    37:快速集成新手引导的类库

    地址:https://github.com/StrongX/XSportLight

    38:设置页面的封装

    地址:https://github.com/renzifeng/ZFSetting

    39:带箭头的弹出视图插件

    地址:https://github.com/xiekw2010/DXPopover

    40:下拉菜单插件

    地址:https://github.com/dopcn/DOPDropDownMenu/

    41:表格空白提示插件

    地址:https://github.com/dzenbot/DZNEmptyDataSet

    42:给任意UIView视图四条边框加上阴影,可以自定义阴影的颜色、粗细程度、透明程度以及位置(上下左右边框)

    地址:https://github.com/Seitk/UIView-Shadow-Maker

    43:不错的日期时间插件

    地址:https://github.com/CoderXL/UUDatePicker

    44:底部弹出选择

    地址:https://github.com/skywinder/ActionSheetPicker-3.0

    45:比较不错的引导页面插件

    地址:https://github.com/ealeksandrov/EAIntroView

    46:两个APP跳转的插件

    地址:https://github.com/usebutton/DeepLinkKit

    47:本地存取NSUserDefaults插件

    地址:https://github.com/gangverk/GVUserDefaults

    48:NSArray和NSDictionary关于LINQ的操作方式,封装一些常用的操作

    地址:https://github.com/ColinEberhardt/LinqToObjectiveC

    49:可以监控网络请求的内容

    地址:https://github.com/coderyi/NetworkEye

    50:时间帮助插件,可以快速获取时间,比较,增加等操作

    地址:https://github.com/MatthewYork/DateTools

    51:不错的链式动作

    地址:https://github.com/jhurray/JHChainableAnimations

    52:弹出层视图,背景效果(可以自定义视图的内容)

    地址:https://github.com/HJaycee/JCAlertView

    53:圆形进度条的显示,中间可显示值

    地址:https://github.com/mdinacci/MDRadialProgress

    54:很帅的数据加载动画(可以用于数据列表加载的展现)

    地址:https://github.com/NghiaTranUIT/FeSpinner

    55:一个开源的AFnetworking上层的封装(猿题库等运用)

    地址:https://github.com/yuantiku/YTKNetwork

    56:CBStoreHouseRefreshControl:一个效果很酷炫的下拉刷新控件

    地址:https://github.com/coolbeet/CBStoreHouseRefreshControl

    57:AFNetworking-RACExtensions:针对ReactiveCocoa的AF封装

    地址:https://github.com/CodaFi/AFNetworking-RACExtensions

    58:模糊效果(毛玻璃)

    地址:https://github.com/nicklockwood/FXBlurView

    59:UITableView展开效果的插件

    地址:https://github.com/sakkaras/SKSTableView

    60:ZIP压缩及解压插件ZipArchive

    地址:https://github.com/ZipArchive/ZipArchive

    61:自定义UIAlertView

    地址:https://github.com/lmcd/LMAlertView

    62:Facebook开源的动画库Pop

    地址:https://github.com/facebook/pop

    63:关于使用facebook动画库的实例集合

    地址:https://github.com/schneiderandre/popping

    64:iOS应用视图上添加简单闪烁效果Shimmer

    地址:https://github.com/facebook/Shimmer

    65:ios数据持久化插件,使得Core Data使用起来更加的便捷容易

    地址:https://github.com/magicalpanda/MagicalRecord

    66:创建缩合的iOS应用程序标题栏

    地址:https://github.com/bryankeller/BLKFlexibleHeightBar

    67:PDF阅读器核心库

    地址:https://github.com/vfr/Reader

    68:STPopup使弹出框也有UINavigationController的效果

    地址:https://github.com/kevin0571/STPopup

    69:基于核心音频,有助于进行实时,低延迟音频处理和可视化的iOS和OSX音频可视化框架

    地址:https://github.com/syedhali/EZAudio

    70:一个不错的弹出Sheet,可以前进跟后退,适合多个页面

    地址:https://github.com/m1entus/MZFormSheetController

    71:Aspect库是对面向切面编程的实现,里面封装了Runtime的方法

    地址:https://github.com/steipete/Aspects

    72:一个不错在无输入源的输入框,如UITableViewCell等

    地址:https://github.com/slackhq/SlackTextViewController

    73:小红点插件,用于提示未读效果

    地址:https://github.com/weng1250/WZLBadge

    74:不错的照片选择器,视频选择器,支持单多选

    地址:https://github.com/mwaterfall/MWPhotoBrowser

    75:含10多种的转场动画效果

    地址:https://github.com/ColinEberhardt/VCTransitionsLibrary

    76:左右菜单显示(类似QQ导航)

    地址:https://github.com/romaonthego/RESideMenu

    77:很赞的等待指示动画(比系统自带的帅)

    地址:https://github.com/ninjaprox/DGActivityIndicatorView

    78:KVOController一个简单安全的KVO(Key-value Observing,键-值观察)工具,提供简单方便、线程安全的API, Facebook的开源项目之一

    地址:https://github.com/facebook/KVOController

    79:FormatterKit收集了很多构思优秀的NSFormatter子类

    地址:https://github.com/mattt/FormatterKit

    80:自定义的UIPageControl(可以设置每个的样式)

    地址:https://github.com/Spaceman-Labs/SMPageControl

    81:使用NJKWebViewProgress做webview进度条(解决先前无法获得进度的问题)

    地址:https://github.com/ninjinkun/NJKWebViewProgress

    82:修改NavigationBar的显示效果

    地址:https://github.com/ltebean/LTNavigationBar/

    83:FCUUID获得设备号的替代方式

    地址:https://github.com/fabiocaccamo/FCUUID

    84:多主题色或者白天黑夜模式的运用

    地址:https://github.com/Draveness/DKNightVersion

    85:GPUImage是一个基于GPU图像和视频处理的开源框架,提供各种各样的图像处理滤镜

    地址:https://github.com/BradLarson/GPUImage

    86:YY图片加载插件,可以支持动态,网络本地,渐进式图片加载等

    地址:https://github.com/ibireme/YYWebImage

    87:封装后的蓝牙帮助库

    地址:https://github.com/coolnameismy/BabyBluetooth

    88:一个很通用的需求就是引导教程

    地址:https://github.com/bubudrc/MPCoachMarks

    89:基于MPMoviePlayerController播放器KRVideoPlayer

    地址:https://github.com/36Kr-Mobile/KRVideoPlayer

    90:UICollection左对齐跟右对齐

    地址:https://github.com/mokagio/UICollectionViewLeftAlignedLayout

    地址:https://github.com/mokagio/UICollectionViewRightAlignedLayout

    91:自定义弹出对话窗,类似系统又可以自定义视图DQAlertView或MMPopupView

    地址:https://github.com/dinhquan/DQAlertView

    地址:https://github.com/adad184/MMPopupView

    92:输入框在焦点获得时会有一个小标题JVFloatLabeledTextField

    地址:https://github.com/jverdi/JVFloatLabeledTextField

    93:针对一些UI进行显示优化,可以设置一些不同的背景色等

    地址:https://github.com/Grouper/FlatUIKit

    94:色彩插件,如果没有设计师又想一些漂亮的色彩就可以运用Chameleon

    地址:https://github.com/ViccAlexander/Chameleon

    95:两个不错的侧边栏显示插件ECSlidingViewController,SWRevealViewController

    地址:https://github.com/ECSlidingViewController/

    ECSlidingViewController

    地址:https://github.com/John-Lluch/SWRevealViewController

    96:各式各样的进度条,可以放在不同地方NAV或者图片或者扇形M13ProgressSuite

    地址:https://github.com/Marxon13/M13ProgressSuite

    97:拉动UITableView时CELL有一摇动的效果AMWaveTransition

    地址:https://github.com/andreamazz/AMWaveTransition

     

    展开全文
  • iOS不同版本升级的新特性:iOS3.0开发特性一、点对点蓝牙连接二、远程浏览内容三、连接周边产品(硬件)四、其它应用可以使用maps五、定位软件六、推送功能七、网络电话(voip)八、录音九、播放音乐十、增强了 app ...
  • iOS系统发布时间

    2017-09-19 09:25:16
    发布日期 版本编号 更改 ...2016年11月9日 iOS10.2 Beta2 发布iOS10.2测试版版 2016年11月1日 iOS10.2 Beta1 发布iOS10.2测试版版 2016年10月25日 iOS10.1 发布iOS10.1正式版 2016年9月22日 iOS10.1 Bet
  • 由于iOS玩机应用的极度匮乏其下载工具类应用更是稀有,先前也为大家推荐过黑科下载器和迅雷安装途径,但是体验上都不完美,很多功能还得付费才能使用,普通用户限速限制次数已经见怪不怪了,稍微敏感点的资源还直接...
  • hello小伙伴们大家好,懒癌患者菌菌又来了,好久没有给大家推荐ios应用了 , 菌菌在网上各种扒帖子的时候, 发现了一款iOS第三方的应用商城,我们可能都知道,在iOS的App store里有很大的限制导致很多安卓有的应用...
  • 本地播放器作为日常生活中不可或缺的一款工具类APP,Windows、Android等平台不乏一些功能与体验兼优的产品,但 iOS 平台的用户就没有那么幸运了,优秀的产品凤毛麟角,且多数收费。 这源于 iOS 平台的特殊性,完美...
  • 转载于:https://blog.51cto.com/14259888/2369621
  • LCMC语料库是一个100万词次(按每1.6个汉字对应一个英文单词折算)的现代汉语书面语通用型平衡语料库。起先建立时,它是作为英国经社研究委员会资助项目Contrasting Tense and Aspect in English and Chinese的部分...
  • iPhone总是弹出一个提示窗口,如下图“iOS 9.3.2可用于您的iPhone且已经可以安装”,而窗口中根本就没有一个不想升级安装的选项。而当我们点击稍后,就会变成如下图所示的界面“输入密码以在今晚更新,如接入电源,...
  • 越狱大神Pwn20wnd发布了最新的苹果12.4系统越狱工具,iOS12.4 目前验证打开着,大家都能刷机越狱了! 长话不多说,今天我们直接进入目前最简单的越狱教程,希望大家能喜欢~~ ▍支持手机型号 重点说明一下目前不支持...
  • 收集整理一波iOS12的捷径库(使用方法见文末),大家使用过程中如果发现有啥问题或者想实现什么捷径,可以关注微信公众号“云峰小罗”,找到我。 1.抖音视频无水印下载 2. 清除照片位置信息 3. 获取热门新闻 4.照片...
  • 首先说一下iOS 11,在WWDC发布之后我对iOS11上面带来的诸多新特性感觉很好想体验一下,并在第一时间更新了iOS11开发者预览版! 更新后体验一天后我的感想是卡卡卡卡,几乎任何一个反应,都有延迟,都要等,等得我好...
  • 1.在iosAPP下载安装时,如果出现此时无法下载安装APP的字样时,可能是苹果系统进行了支持更新,并需要我们确认条约。至于如何判断是否是苹果系统进行了更改,只需要我们进入开发者账号,进入我的账户(Account)如...
1 2 3 4 5 ... 20
收藏数 977,744
精华内容 391,097
关键字:

ios