OC 设计模式

来源:互联网 发布:网络不稳定英文 编辑:程序博客网 时间:2024/06/10 17:02

单例模式

单例简介

  • 单例是生命周期与程序生命周期相同,仅能生成一次、且不能被销毁的唯一实例;

  • 需要确保应用中的一个特定类有且仅有一个实例(对象);

  • 单例可在程序任何位置被访问,且一直存在;

  • 单例实例获取方法命名规则:一般以standard…、shared…、default….开头;

  • 单例必须至少满足以下条件:

    • 只初始化一次;

    • 全局存在;

    • 唯一,对象不可改;

    • 方便获取,任何位置可访问

系统单例

  • UIApplication:应用程序单例

  • NSNotificationCenter:通知中心单例

  • NSUserDefaults:用户默认单例

  • NSFileManager:文件管理单例

单例优点

  • 共享信息;

  • 实例控制:Singleton会阻止其他对象实例化其自己的Singleton对象的副本,从而确保所有对象都访问唯一实例;

  • 灵活性:因为类控制了实例化过程,所以类可以更加灵活地修改实例化过程;

自定义单例创建常用方法

首先创建一个继承于NSObject的类Singleton,其次在Singleton.m文件中实现如下代码;

  • 方法1:一般创建
<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#import <span class="hljs-title" style="box-sizing: border-box;">"Singleton.h"</span></span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 静态变量保证单例对象始终存在</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> Singleton *singleton = <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>;<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@implementation</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Singleton</span></span>+ (instancetype)defaultSingleton {    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 仅在单例对象为空时初始化一次,之后直接返回唯一的单例对象</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (singleton == <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>) {        singleton = [[Singleton alloc] init];    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> singleton;}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@end</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul>
  • 方法2:GCD创建(推荐使用)
<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#import <span class="hljs-title" style="box-sizing: border-box;">"Singleton.h"</span></span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> Singleton *singleton = <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>;<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@implementation</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Singleton</span></span>+ (instancetype)defaultSingleton {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">dispatch_once_t</span> onceToken;    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">dispatch_once</span>(&onceToken, ^{        singleton = [[Singleton alloc] init];    });    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> singleton;}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@end</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li></ul>

自定义单例创建完整方法

  • 一般创建单例方法可能会出现一些问题,我们通过不同的途径得到不同的对象,显然是不行的。我们必须要确保对象的唯一性,所以我们就需要封锁用户通过alloc/init/copy以及release/retain等方法来构造或操作对象这条道路。

  • 我们知道,创建对象的步骤分为申请内存(alloc)、初始化(init)这两个步骤,我们要确保对象的唯一性,因此在第一步这个阶段我们就要拦截它。当我们调用alloc方法时,oc内部会调用allocWithZone这个方法来申请内存,我们覆写这个方法,然后在这个方法中调用defaultSingleton方法返回单例对象,这样就可以达到我们的目的。拷贝对象也是同样的原理,覆写copyWithZone方法,注意需遵守<NSCopying>协议,然后在这个方法中调用defaultSingleton方法返回单例对象,其他示例直接参考如下代码:

<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> Singleton *singleton = <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>;+ (instancetype)defaultSingleton {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!singleton) {        singleton = [[Singleton alloc] init];    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> singleton;}<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// alloc</span>+ (instancetype)allocWithZone:(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> _NSZone *)zone {    @synchronized(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!singleton) {            singleton = [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span> allocWithZone:zone];            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> singleton;        }        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>;    }}<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// copy</span>- (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">id</span>)copyWithZone:(NSZone *)zone {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>;}<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// retain</span>- (instancetype)retain {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>;}<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// release</span>- (oneway <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)release {}<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// autorelease</span>- (instancetype)autorelease {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>;}<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// retainCount</span>- (NSUInteger)retainCount {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> NSUIntegerMax;}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li></ul>

单例使用

首先在main.m文件中,引入“Singleton.h”,其次创建两个单例实例,并且打印对象信息;

这里写图片描述

我们可以看到,两个实例对象的地址是一致的,由此可见,单例的唯一性。

可利用单例的唯一性进行传值,但必须满足一个前提条件就是,在传值时,必须保证单例存在并且单例属性确实有值。

现在在Singleton.h文件中声明属性name,其次创建一个Person类,为其设置属性name,并且重写init方法,通过单例对name直接复制,如下所示:

<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#import <span class="hljs-title" style="box-sizing: border-box;">"Person.h"</span></span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#import <span class="hljs-title" style="box-sizing: border-box;">"Singleton.h"</span></span><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@implementation</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Person</span></span>- (instancetype)init {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> = [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span> init];    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 获取单例属性值赋给name</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.name</span> = [Singleton defaultSingleton]<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.name</span>;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>;}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@end</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul>

切换到main.m文件中,创建单例实例,并且给name属性复制,其次实例化Person对象,并打印person.name,如下所示:

<code class="hljs vala has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#import <Foundation/Foundation.h></span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#import "Singleton.h"</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#import "Person.h"</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> argc, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> * argv[]) {    @autoreleasepool {<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#pragma mark - 单例模式</span>        Singleton *singleton = [Singleton defaultSingleton];        singleton.name = @<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Admin"</span>;        Person *person = [[Person alloc] init];        NSLog(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Person's name is '%@'."</span>, person.name); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//  Person's name is 'Admin'.</span>    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li></ul>

从上述代码中可以看出,可通过单例进行传值操作。

KVC 键值编码

概述

  • KVC是KeyValueCoding的简称,它是一种可以直接通过字符串的名字(key)来访问类属性(实例变量)的机制。而不是通过调用Setter、Getter方法访问。通常我们使用valueForKey来替代getter() 方法,setValue:forKey来代替setter()方法。

  • 当使用KVO、Core Data、CocoaBindings、AppleScript(Mac支持)时,KVC是关键技术。

常用方法

  • 取值方法
<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1、</span>valueForKey:,传入<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span>属性的名字。<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 2、</span>valueForKeyPath:,传入<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span>属性的路径,xx<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.xx</span>形式。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
  • 设值方法
<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1、</span>- (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)setValue:(nullable <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">id</span>)value forKey:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *)key;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 2、</span>- (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)setValue:(nullable <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">id</span>)value forKeyPath:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *)keyPath;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 3、- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues;</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 4、</span>- (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)setValue:(nullable <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">id</span>)value forUndefinedKey:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *)key;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

KVC 读取方式

KVC使用起来比较简单,但是它如何查找一个属性进行读取呢?具体查找规则(假设现在要利用KVC对name进行读取):

  • 如果是动态设置属性,则优先考虑调用setName方法,如果没有该方法则优先考虑搜索成员变量_name,如果仍然不存在则搜索成员变量name,如果最后仍然没搜索到则会调用这个类的setValue:forUndefinedKey:方法(注意搜索过程中不管这些方法、成员变量是私有的还是公共的都能正确设置);

  • 如果是动态读取属性,则优先考虑调用name方法(属性name的getter方法),如果没有搜索到则会优先搜索成员变量_name,如果仍然不存在则搜索成员变量name,如果最后仍然没搜索到则会调用这个类的valueforUndefinedKey:方法(注意搜索过程中不管这些方法、成员变量是私有的还是公共的都能正确读取);

案例

1、声明 KVCClass 类,并在其.h文件中声明几个全局变量,无需定义成属性及生成存(setter)取(getter)方法,代码如下:

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">#<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> <Foundation/Foundation.h><span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@interface</span> KVCClass : NSObject {    NSString *_name;        <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**< 姓名 */</span>    NSString *_nationality; <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**< 国籍 */</span>    NSInteger _age;         <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**< 年龄 */</span>}<span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@end</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

2、在 “KVCClass.m”文件中,重写description方法与dealloc方法,代码如下:

<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#import <span class="hljs-title" style="box-sizing: border-box;">"KVCClass.h"</span></span><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@implementation</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">KVCClass</span></span>- (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)dealloc {    [_name release]; _name = <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>;    [_nationality release]; _nationality = <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>;    [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span> dealloc];}- (<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *)description {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> stringWithFormat:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<%p name:%@, age:%ld, address:%@>"</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>, _name, _age, _nationality];}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@end</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>

3、在main.m文件中,导入KVCClass.h,实例化对象,并通过KVC为其设值,代码如下:

<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#import <span class="hljs-title" style="box-sizing: border-box;"><Foundation/Foundation.h></span></span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#import <span class="hljs-title" style="box-sizing: border-box;">"KVCClass.h"</span></span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> argc, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> * argv[]) {    @autoreleasepool {<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#pragma mark - KVC </span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1、逐一赋值</span>        KVCClass *kvcObject1 = [[KVCClass alloc] init];        [kvcObject1 setValue:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Charles"</span> forKey:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"name"</span>];        [kvcObject1 setValue:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"China"</span> forKey:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"nationality"</span>];        [kvcObject1 setValue:@<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">22</span> forKey:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"age"</span>];        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%@"</span>, kvcObject1);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 取值</span>        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Name is '%@'."</span>, [kvcObject1 valueForKey:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"name"</span>]);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 2、统一赋值</span>        KVCClass *kvcObject2 = [[KVCClass alloc] init];        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSDictionary</span> *dic = @{@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"name"</span>:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"William"</span>, @<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"nationality"</span>:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"USA"</span>, @<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"age"</span>:@<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>};        [kvcObject2 setValuesForKeysWithDictionary:dic];        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%@"</span>, kvcObject2);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 取值</span>        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Name is '%@'."</span>, [kvcObject2 valueForKey:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"name"</span>]);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li></ul>

控制台输出情况如下:

这里写图片描述

Tips

1、key的值必须正确,如果拼写错误,会出现异常;

2、当key的值是没有定义的,valueForUndefinedKey:这个方法会被调用,如果你自己写了这个方法,key的值出错就会调用到这里来;

3、因为类key反复嵌套,所以有个keyPath的概念,keyPath就是用.号来把一个一个key链接起来,这样就可以根据这个路径访问下去;

4、NSArray/NSSet等都支持KVC;

KVO 键值监听

概述

  • KVO,即:Key-Value Observing,它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知。简单的说就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应的观察者了。在ObjC中要实现KVO则必须实现NSKeyValueObServing协议,不过幸运的是NSObject已经实现了该协议,因此几乎所有的ObjC对象都可以使用KVO。

  • 在面对对象编程时,我们很多情况下直接处理某些事件会很麻烦。如常见的程序运行中电话呼入、用户突然点击home键等等,一般我们使用观察者(代理)来处理类似事件。

  • 在使用这些模式的时候,我们需要告诉这些角色,谁来响应这些事件,这就需要使用类的引用。

  • 类的引用本质上就是如何让另外一个角色,“知道”另外一个角色,对应到代码中,就是如何让某一个类的对象,顺利的把信息传递给另外一个对象。

  • 处理类的引用的时候,应注意以下几点:

    • 每个类是否能正常接收到信息(响应动作)

    • 信息传递时接收者是否存在

    • 每个类是否能正常释放(不会引起循环引用)

键值观察

  • 键值观察是基于键值编码的一种技术;

  • 利用键值观察可以注册成为一个对象的观察者,在该对象的某个属性变化时收到通知;

  • 被观察对象需要编写复合KVC标准的存取方法;

常用方法

系统框架已经支持KVO,所以程序员在使用的时候非常简单。

1、注册指定Key路径的监听器:addObserver: forKeyPath: options: context:

2、实现回调方法: observeValueForKeyPath: ofObject: change: context:

3、删除指定Key路径的监听器:removeObserver: forKeyPath、removeObserver: forKeyPath: context:

案例

此案例将KVC与KVO结合使用

1、声明 KVOClass 类,并在其.h文件中声明全局变量_weather

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">#<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> <Foundation/Foundation.h><span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@interface</span> KVOClass : NSObject {    NSString *_weather; <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**< 天气 */</span>}<span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@end</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

2、在“person.m”文件中实现如下代码:

<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#import <span class="hljs-title" style="box-sizing: border-box;">"KVOClass.h"</span></span><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@implementation</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">KVOClass</span></span>- (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)dealloc {    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 移除监听</span>    [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> removeObserver:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> forKeyPath:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"weather"</span>];    [_weather release]; _weather = <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>;    [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span> dealloc];}- (instancetype)init {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> = [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span> init];    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 注册监听</span>        [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> addObserver:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> forKeyPath:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"weather"</span> options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>];    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>;}<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 实现监听回调方法</span>- (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)observeValueForKeyPath:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *)keyPath ofObject:(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">id</span>)object change:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSDictionary</span><<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">id</span>> *)change context:(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> *)context {    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"天气发生变化,此时天气情况:%@"</span>, change[@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"new"</span>]);}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@end</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li></ul>

3、在“main.m”文件中导入KVOClass.h文件,实现如下代码,观察控制台:

<code class="hljs vala has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#import <Foundation/Foundation.h></span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#import "KVOClass.h"</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> argc, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> * argv[]) {    @autoreleasepool {<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#pragma mark - KVO</span>        KVOClass *kvoObject = [[KVOClass alloc] init];        [kvoObject setValue:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"晴"</span> forKey:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"weather"</span>];        [kvoObject release];    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li></ul>

控制台输出:

<code class="hljs css has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">2015<span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">-11-17</span> 23<span class="hljs-pseudo" style="color: rgb(0, 0, 0); box-sizing: border-box;">:02</span><span class="hljs-pseudo" style="color: rgb(0, 0, 0); box-sizing: border-box;">:00</span><span class="hljs-class" style="box-sizing: border-box; color: rgb(155, 112, 63);">.860</span> <span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">DesignPatterns</span><span class="hljs-attr_selector" style="color: rgb(0, 136, 0); box-sizing: border-box;">[1392:132353]</span> 天气发生变化,此时天气情况:晴</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

Tips

使用KVC可以大大地减少我们的代码量,当遇到property的时候,可以多想想是否可以KVC来帮助我,是否可以用KVC来重构代码, 当需要加入observer模式时,可以考虑下KVO, 在高性能的observer里面,KVO会给我们很好的帮助。

数据持久化

  • iOS应用程序使用沙盒机制作为文件存储方式;

  • 应用程序有一个独立的沙盒文件夹,程序仅能访问自己沙盒路径下的文件,任何情况下都无法访问其它程序的沙盒;

  • 那我们可以通过什么方法将数据存入沙盒,同时也可以取出?可同 NSUserdefaults 或 属性列表实现。

  • 数据持久化的方法还有很多,如本地数据库(CoreData、sqlite、归档)、网络数据库(服务器)等等,会在后面的博客中介绍。

NSUserdefaults

常用方法

1、存值

<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1、获取系统单例</span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSUserDefaults</span> *defaults = [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSUserDefaults</span> standardUserDefaults];<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 2、设值</span>[defaults setObject:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"William"</span> forKey:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"name"</span>];<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 3、同步数据</span>[defaults synchronize];</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

2、取值

<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1、获取系统单例</span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSUserDefaults</span> *defaults = [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSUserDefaults</span> standardUserDefaults];<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 2、取值</span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *name = [defaults objectForKey:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"name"</span>];<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 3、打印信息</span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Name is '%@'."</span>, name);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

3、移除值

<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1、获取系统单例</span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSUserDefaults</span> *defaults = [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSUserDefaults</span> standardUserDefaults];<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 2、删除值</span>[defaults removeObjectForKey:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"name"</span>];<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 3、同步数据</span>[defaults synchronize];</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

Tips

1、从上述示例中可以看出,无论是什么操作,都需获取userdefaults单例,如果是存值或删除值,一定记得调用synchronize方法,同步数据。

2、通过userdefaults同样可以进行值的传递,因为userdefaults本质也是单例。

读写文件

我们可以自己通过代码,根据一条路径自动在桌面上创建一个文件,来存取我们的数据,注意:这个数据并非存在沙河中。

获取桌面文件路径方式:直接将桌面文件拖入Xcode工程即可,Xcode会自动获取文件路径。

<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSDictionary</span> *dict = @{@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"account"</span>:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Admin"</span>, @<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"password"</span>:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"123456"</span>};<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1、写入文件</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 将 dict 存入文件,/infomation.text 为自己给存储对象文件的命名</span>[dict writeToFile:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/Users/LiHongyao/Desktop/Datas/infomation.text"</span> atomically:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">YES</span>];<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 2、读取文件</span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSDictionary</span> *infomation = [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSDictionary</span> dictionaryWithContentsOfFile:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/Users/LiHongyao/Desktop/Datas/infomation.text"</span>];<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%@"</span>, infomation);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

输出情况:

<code class="hljs delphi has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2015</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">11</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">17</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">23</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">49</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">39.302</span> DesignPatterns[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1562</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">170884</span>] <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">{    account = Admin;    password = 123456;}</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Program</span> ended <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">with</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">exit</span> code: <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span></code>
0 0
原创粉丝点击