<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Uiresponder on Chen</title><link>https://hechen.github.io/zh-cn/tags/uiresponder/</link><description>Recent content in Uiresponder on Chen</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Fri, 21 Dec 2018 14:30:50 +0000</lastBuildDate><atom:link href="https://hechen.github.io/zh-cn/tags/uiresponder/index.xml" rel="self" type="application/rss+xml"/><item><title>UserDefaults and Keychain</title><link>https://hechen.github.io/zh-cn/post/userdefaults-and-keychain/</link><pubDate>Fri, 21 Dec 2018 14:30:50 +0000</pubDate><guid>https://hechen.github.io/zh-cn/post/userdefaults-and-keychain/</guid><description>&lt;p&gt;Apple 提供了几种持久化方案，其中 UserDefaults 和 Keychain 是 App 开发过程中使用频率最高的方案，而且从以往和同事的探讨过程中发现对这两个概念中有一些细节还是理解不太透彻，因此本文会针对这二者展开讲一讲。&lt;/p&gt;
&lt;h2 id="userdefaults"&gt;UserDefaults&lt;/h2&gt;
&lt;p&gt;首先，阅读完 Apple 关于 UserDefaults 一节的文档描述之后，我觉得有两个需要注意的点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;UserDefaults 的构成&lt;/li&gt;
&lt;li&gt;UserDefaults 的目的&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="userdefaults-构成"&gt;UserDefaults 构成&lt;/h3&gt;
&lt;p&gt;我们可以看看具体 UserDefaults 存储的地方，如下图，我们在应用中写入 Demo 数据：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Write Key-Value to UserDefaults" loading="lazy" src="https://i.imgur.com/wq9onOa.png"&gt;&lt;/p&gt;
&lt;p&gt;打印 Library 路径，在 Finder 中打开路径:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Library" loading="lazy" src="https://i.imgur.com/65ybYX6.png"&gt;&lt;/p&gt;
&lt;p&gt;如下展示内容，可以看到在 Preferences 目录中存在某个文件，例如该 App Library 目录下存放的文件为 &lt;code&gt;app.chen.ios.PersistenceDemo.plist&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Cache" loading="lazy" src="https://i.imgur.com/ChqnDJa.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Preferences" loading="lazy" src="https://i.imgur.com/cPvlFdR.png"&gt;&lt;/p&gt;
&lt;p&gt;该 plist 内容如图所示，即为我们之前在 App 中写入的 Key-Value。&lt;/p&gt;
&lt;p&gt;&lt;img alt="plist" loading="lazy" src="https://i.imgur.com/shdXoZN.png"&gt;&lt;/p&gt;
&lt;p&gt;所以这也证明了，我们针对 UserDefaults 的读写实质上是针对 plist 文件的读写。&lt;/p&gt;
&lt;p&gt;iOS 系统会自动帮你做 &lt;code&gt;plist&lt;/code&gt; 文件的读入以及 Cache，根据情况会把你在内存中所做的操作同步到 &lt;code&gt;plist&lt;/code&gt; 文件（UserDefaults 同步到内存是同步的，同步到 Database 是异步的， iOS 8 开始，会有一个常驻进程 &lt;code&gt;cfprefsd&lt;/code&gt; 来负责同步）。&lt;/p&gt;</description></item><item><title>理解响应者和响应链</title><link>https://hechen.github.io/zh-cn/post/understanding-responders-and-the-responder-chain/</link><pubDate>Mon, 13 Nov 2017 21:22:44 +0000</pubDate><guid>https://hechen.github.io/zh-cn/post/understanding-responders-and-the-responder-chain/</guid><description>&lt;p&gt;Apps 是通过响应者（responder）对象来接收和处理事件的。一个响应者对象是 UIResponder 类的一个实例，我们常见的 UIView，UIViewController 以及 UIApplication 都是 UIResponder 的子类。 UIKit 自动帮你管理着这些 responder 相关的行为，包括事件是如何从一个 responder 传递给另一个 responder 的等等。当然，你也可以修改你的 app 中事件传递的默认行为。&lt;/p&gt;
&lt;p&gt;UIKit 会把大部分的事件都传递给最适合的 responder 对象来处理。如果该 responder 无法处理该事件，UIKit 就会继续把该事件沿着当前的响应者链传递到下一个 responder。响应者链就是你的 App 中所有响应者的动态配置，也因为其是动态的，你的 App 中不可能只存在单一的响应者链。由于事件总是从特定的响应者那里流转到更通用的响应者那里，因此很容易确定某响应者链中下一个响应者是谁。举个例子，一个 view 的下一个响应者是其 superview 或者负责管理它的 view controller。事件就是这样在响应者链中传递直到其被处理掉。&lt;/p&gt;
&lt;p&gt;下图展示了一个界面中包含了 一个 Label，一个 TextField，一个 Button 以及两个容器 view 的 App 中响应链是什么样子的。如果 TextField 不处理某个事件，UIKit 就会把该事件发送给 TextField 的父级 UIView 对象，同样的，如果该对象依然处理不了，就会传递给该 view 对象的 window。如果 window 对象也依然无法处理该事件，UIKit 最终会把该事件传递给 UIApplication 对象，一般上该 UIApplication 对象是 App 的 delegate 对象并且是 UIResponder 实例，当然这个时候已经脱离了响应者链了。&lt;/p&gt;</description></item></channel></rss>