<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[杨叫兽的技术博客]]></title>
  <link href="http://nijino.cn/atom.xml" rel="self"/>
  <link href="http://nijino.cn/"/>
  <updated>2014-08-15T23:51:22+08:00</updated>
  <id>http://nijino.cn/</id>
  <author>
    <name><![CDATA[杨叫兽]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Objective-C中3种枚举方法耗时比较]]></title>
    <link href="http://nijino.cn/blog/2014/03/11/comparison-for-3-enumeration-methods-in-objective-c/"/>
    <updated>2014-03-11T14:29:00+08:00</updated>
    <id>http://nijino.cn/blog/2014/03/11/comparison-for-3-enumeration-methods-in-objective-c</id>
    <content type="html"><![CDATA[<p>集合类对象（NSArray、NSDictionary、NSSet及其子类）在Objective－C中十分常见。经常会有遍历集合中所有对象的需求，Objective－C中遍历集合中对象的方法有三种：</p>

<ol>
<li>C语言的for循环遍历;</li>
<li>Objective-C的快速枚举;</li>
<li>集合对象的枚举块语法。</li>
</ol>


<!-- more -->


<p>为了测试以上三种枚举方法消耗的时间，我写了一个小程序，对含有1万个元素的数组进行打印操作，看看分别都消耗了多长时间。核心代码如下：</p>

<figure class='code'><figcaption><span>Large Enumeration Test </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="n">NSUInteger</span> <span class="n">totalCount</span> <span class="o">=</span> <span class="mi">10000</span><span class="p">;</span>
</span><span class='line'><span class="n">NSMutableArray</span> <span class="o">*</span><span class="n">array</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSMutableArray</span> <span class="nl">arrayWithCapacity:</span><span class="n">totalCount</span><span class="p">];</span>
</span><span class='line'>        <span class="c1">//create an array including 10000 elements</span>
</span><span class='line'>    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span><span class="n">totalCount</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">array</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="err">@</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="n">stringValue</span><span class="p">];</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>        <span class="c1">//C Language For Loop Enumeration</span>
</span><span class='line'>    <span class="n">CFTimeInterval</span> <span class="n">start1</span> <span class="o">=</span> <span class="n">CACurrentMediaTime</span><span class="p">();</span>
</span><span class='line'>    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span><span class="o">&lt;</span> <span class="n">totalCount</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">NSLog</span><span class="p">(</span><span class="s">@&quot;%@&quot;</span><span class="p">,</span><span class="n">array</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="n">CFTimeInterval</span> <span class="n">end1</span> <span class="o">=</span> <span class="n">CACurrentMediaTime</span><span class="p">();</span>
</span><span class='line'>    <span class="n">NSLog</span><span class="p">(</span><span class="s">@&quot;C Language For Loop method %f&quot;</span><span class="p">,</span><span class="n">end1</span> <span class="o">-</span> <span class="n">start1</span><span class="p">);</span>
</span><span class='line'>        <span class="c1">//Objective-C Fast Enumeration</span>
</span><span class='line'>    <span class="n">CFTimeInterval</span> <span class="n">start2</span> <span class="o">=</span> <span class="n">CACurrentMediaTime</span><span class="p">();</span>
</span><span class='line'>    <span class="k">for</span> <span class="p">(</span><span class="n">NSString</span> <span class="o">*</span><span class="n">string</span> <span class="k">in</span> <span class="n">array</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">NSLog</span><span class="p">(</span><span class="s">@&quot;%@&quot;</span><span class="p">,</span><span class="n">string</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="n">CFTimeInterval</span> <span class="n">end2</span> <span class="o">=</span> <span class="n">CACurrentMediaTime</span><span class="p">();</span>
</span><span class='line'>    <span class="n">NSLog</span><span class="p">(</span><span class="s">@&quot;Objective-C Fast Enumeration method %f&quot;</span><span class="p">,</span><span class="n">end2</span> <span class="o">-</span> <span class="n">start2</span><span class="p">);</span>
</span><span class='line'>        <span class="c1">//Objective-C Block Enumeration</span>
</span><span class='line'>    <span class="n">CFTimeInterval</span> <span class="n">start3</span> <span class="o">=</span> <span class="n">CACurrentMediaTime</span><span class="p">();</span>
</span><span class='line'>    <span class="p">[</span><span class="n">array</span> <span class="nl">enumerateObjectsWithOptions:</span><span class="n">NSEnumerationConcurrent</span> <span class="nl">usingBlock:</span><span class="o">^</span><span class="p">(</span><span class="n">NSString</span> <span class="o">*</span> <span class="n">obj</span><span class="p">,</span> <span class="n">NSUInteger</span> <span class="n">idx</span><span class="p">,</span> <span class="kt">BOOL</span> <span class="o">*</span><span class="n">stop</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">NSLog</span><span class="p">(</span><span class="s">@&quot;%@&quot;</span><span class="p">,</span><span class="n">obj</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}];</span>
</span><span class='line'>    <span class="n">CFTimeInterval</span> <span class="n">end3</span> <span class="o">=</span> <span class="n">CACurrentMediaTime</span><span class="p">();</span>
</span><span class='line'>    <span class="n">NSLog</span><span class="p">(</span><span class="s">@&quot;Objective-C Block Enumeration method %f&quot;</span><span class="p">,</span><span class="n">end3</span> <span class="o">-</span> <span class="n">start3</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>其中CACurrentMediaTime()是一个返回系统时间的函数(<a href="https://developer.apple.com/library/mac/documentation/cocoa/Reference/CoreAnimation_functions/Reference/reference.html" title="Core Animation Function Reference">苹果参考文档</a>)，可以通过结束时间减去开始时间计算代码所消耗的时间。(附：在Mac终端中输入w可以查询机器已经运行的时间信息，w属于Unix命令。)</p>

<p>部分运行结果：</p>

<figure class='code'><figcaption><span>Consume Time Results </span></figcaption>
<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>2014-03-11 15:04:41.522 testspeed[19780:70b] C Language For Loop method 7.750710
</span><span class='line'>2014-03-11 15:04:47.847 testspeed[19780:70b] Objective-C Fast Enumeration method 6.323673
</span><span class='line'>2014-03-11 15:04:53.715 testspeed[19780:70b] Objective-C Block Enumeration method 5.866547</span></code></pre></td></tr></table></div></figure>


<p>从以上结果可以看出，语法块的枚举耗时最短，快速枚举次之，for循环最慢。语法块枚举快的主要原因是枚举options中采用了NSEnumerationConcurrent，也就是并行处理，充分发挥了多核心的优势。当然这么做会导致输出顺序错乱，如果需求对顺序要求严格，就不能使用这个选项。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[给NSLog增加输出功能]]></title>
    <link href="http://nijino.cn/blog/2014/03/02/add-new-function-to-nslog/"/>
    <updated>2014-03-02T21:34:00+08:00</updated>
    <id>http://nijino.cn/blog/2014/03/02/add-new-function-to-nslog</id>
    <content type="html"><![CDATA[<p>之前在<a href="http://blog.163.com/nijino_saki/blog/static/8009214420134128146215/" title="DLog的使用">网易老博客:DLog的使用</a>里讲到编写一个DLog宏替代NSLog输出更多的打印信息。如果之前工程里NSLog很多就需要把所有的NSLog替换成DLog。这么做是不是感觉有点麻烦？其实还有更简单的办法，就是直接写一个NSLog的宏，替换掉Xcode中已存在的宏，同样可以打印需要的信息。只需将下列代码放入prefix.pch文件中：</p>

<!-- more -->




<figure class='code'><figcaption><span>Add additional Print Funtion For NSLog </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="cp">#define NSLog(format, ...) do {\</span>
</span><span class='line'><span class="cp">fprintf(stderr, &quot;&lt;%s : %d&gt; %s\n&quot;,\</span>
</span><span class='line'><span class="cp">        [[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String],\</span>
</span><span class='line'><span class="cp">        __LINE__, __func__);\</span>
</span><span class='line'><span class="cp">(NSLog)((format), ##__VA_ARGS__);\</span>
</span><span class='line'><span class="cp">fprintf(stderr, &quot;-------\n&quot;);\</span>
</span><span class='line'><span class="cp">} while (0)</span>
</span></code></pre></td></tr></table></div></figure>


<p>如果还想深入了解宏定义的知识，请参考<a href="http://www.cocoachina.com/applenews/devnews/2014/0122/7738.html" title="宏定义的黑魔法 - 宏菜鸟起飞手册">这里</a>。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[NSArray技巧两则]]></title>
    <link href="http://nijino.cn/blog/2014/01/05/nsarray-skills/"/>
    <updated>2014-01-05T12:21:00+08:00</updated>
    <id>http://nijino.cn/blog/2014/01/05/nsarray-skills</id>
    <content type="html"><![CDATA[<p>之前我在网易的技术博客中讲到<a href="http://blog.163.com/nijino_saki/blog/static/800921442013421114117193/" title="去除NSArray中重复元素的方法">去除NSArray中重复元素的方法</a>。最近在看WWDC2013视频，发现苹果工程师对数组去重有更为简便的方法，还有一个对数组逆序的简便方法，赶紧记录下来备用。</p>

<!-- more -->


<ol>
<li>NSArray逆序</li>
</ol>


<figure class='code'><figcaption><span>Reverse sequence of NSArray </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="n">NSArray</span> <span class="o">*</span><span class="n">arr</span> <span class="o">=</span> <span class="err">@</span><span class="p">[</span><span class="s">@&quot;first&quot;</span><span class="p">,</span><span class="s">@&quot;second&quot;</span><span class="p">];</span>
</span><span class='line'><span class="n">arr</span> <span class="o">=</span> <span class="n">arr</span><span class="p">.</span><span class="n">reverseObjectEnumerator</span><span class="p">.</span><span class="n">allObjects</span><span class="p">;</span>
</span><span class='line'><span class="n">NSLog</span><span class="p">(</span><span class="s">@&quot;%@&quot;</span><span class="p">,</span><span class="n">arr</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>输出结果为：</p>

<figure class='code'><figcaption><span>Reverse Result </span></figcaption>
<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>2014-01-05 13:52:09.303 CircleAudio[39584:70b] (
</span><span class='line'>second,
</span><span class='line'>first
</span><span class='line'>)</span></code></pre></td></tr></table></div></figure>


<ol>
<li>NSArray快速去重</li>
</ol>


<figure class='code'><figcaption><span>Make NSArray distinct </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="n">NSArray</span> <span class="o">*</span><span class="n">arr</span> <span class="o">=</span> <span class="err">@</span><span class="p">[</span><span class="s">@&quot;first&quot;</span><span class="p">,</span><span class="s">@&quot;second&quot;</span><span class="p">,</span><span class="s">@&quot;first&quot;</span><span class="p">];</span>
</span><span class='line'><span class="n">arr</span> <span class="o">=</span> <span class="p">[</span><span class="n">arr</span> <span class="nl">valueForKeyPath:</span><span class="s">@&quot;@distinctUnionOfObjects.self&quot;</span><span class="p">];</span>
</span><span class='line'><span class="n">NSLog</span><span class="p">(</span><span class="s">@&quot;%@&quot;</span><span class="p">,</span><span class="n">arr</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>输出结果：</p>

<figure class='code'><figcaption><span>Result </span></figcaption>
<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>2014-01-05 13:54:53.457 CircleAudio[39976:70b] (
</span><span class='line'>first,
</span><span class='line'>second
</span><span class='line'>)</span></code></pre></td></tr></table></div></figure>


<p>以上的技巧都是从WWDC2013 session 228中学到的，其中还有一些技巧比如：联合两个数组并去重，感兴趣的同学可以自行下载视频研究。</p>

<p><em>2014.4.21更新:</em></p>

<p>对于更多有关KVC运算符的介绍，可以参考<a href="http://nshipster.cn/kvc-collection-operators/" title="KVC Collection Operators">NSHipster的博文</a>。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[iOS调用Emoji表情的方法]]></title>
    <link href="http://nijino.cn/blog/2013/10/05/emoji/"/>
    <updated>2013-10-05T22:11:00+08:00</updated>
    <id>http://nijino.cn/blog/2013/10/05/emoji</id>
    <content type="html"><![CDATA[<p>Emoji是iOS自带的表情符号，在短信和一些通讯软件中使用起来非常有意思。而如果在iOS软件中能使用这些表情符号，更会让软件显得生机勃勃，比如下面这个软件的评价视图：</p>

<!-- more -->


<p><img src="http://ww4.sinaimg.cn/large/540e407ajw1ejd9jo7pryj20fs08wgmd.jpg"></p>

<p>那么如何使用这些表情呢？主要的思路是拿到Emoji表情的编码。获得Emoji编码的方法是在Mac OS 10.7（lion）及以上版本中随便打开一个程序，选择编辑菜单中的最后一项：特殊字符。
在特殊字符窗口点击左上角下拉菜单，选择自定列表，在自定列表中如果表情符号没有勾选，请勾选。然后往下找到代码表，展开代码表并勾选Unicode选项，最后点击完成。</p>

<p><img src="http://ww4.sinaimg.cn/large/540e407ajw1ejd9k5qkluj20g40bvmyh.jpg"></p>

<p>随便选择一个Emoji表情，右边的详细信息里就会显示这个表情的Unicode，我们需要的就是这个编码（不是括号中的）。</p>

<p><img src="http://ww4.sinaimg.cn/large/540e407ajw1ejd9kqx91tj207d070mxa.jpg"></p>

<p>现在就可以使用这个表情了，将刚才查到表情的Unicode赋值给某个对象的text属性中。需要注意的是赋值时需要以&#8221;\U&#8221;开头，并写够8位，不够时用0在高位补齐。比如下面这个赋值写法：</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="n">self</span><span class="p">.</span><span class="n">label</span><span class="p">.</span><span class="n">text</span> <span class="o">=</span> <span class="s">@&quot;\U0001F603&quot;</span><span class="p">;</span><span class="err">`</span>
</span></code></pre></td></tr></table></div></figure>


<p>在模拟器中的效果:</p>

<p><img src="http://ww1.sinaimg.cn/large/540e407ajw1ejd9lac5dcj20gi0rgt9c.jpg"></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[在iOS应用中使用自定义字体]]></title>
    <link href="http://nijino.cn/blog/2013/09/05/using-custom-font/"/>
    <updated>2013-09-05T21:31:00+08:00</updated>
    <id>http://nijino.cn/blog/2013/09/05/using-custom-font</id>
    <content type="html"><![CDATA[<p>开发过iOS应用的朋友都知道，iOS平台里的字体样式很多，其中的大多数都很美观。但是在这些字体中并没有中文字体，如果想用一些好看的中文字体（比如楷体、隶书等）该怎么做呢？</p>

<!-- more -->


<p>
其实iOS是支持自定义字体的。首先我们可以通过以下代码查看iOS都内置了哪些字体。</p>

<figure class='code'><figcaption><span>Find All Fonts in iOS </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="n">NSArray</span> <span class="o">*</span><span class="n">familyNames</span> <span class="o">=</span> <span class="p">[</span><span class="n">UIFont</span> <span class="n">familyNames</span><span class="p">];</span>
</span><span class='line'><span class="k">for</span> <span class="p">(</span><span class="n">NSString</span> <span class="o">*</span><span class="n">familyName</span> <span class="k">in</span> <span class="n">familyNames</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="n">printf</span><span class="p">(</span><span class="s">&quot;Family: %s </span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,[</span><span class="n">familyName</span> <span class="n">UTF8String</span><span class="p">]);</span>
</span><span class='line'>  <span class="n">NSArray</span> <span class="o">*</span><span class="n">fontNames</span> <span class="o">=</span> <span class="p">[</span><span class="n">UIFont</span> <span class="nl">fontNamesForFamilyName:</span><span class="n">familyName</span><span class="p">];</span>
</span><span class='line'>  <span class="k">for</span> <span class="p">(</span><span class="n">NSString</span> <span class="o">*</span> <span class="n">fontName</span> <span class="k">in</span> <span class="n">fontNames</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="n">printf</span><span class="p">(</span><span class="s">&quot;</span><span class="se">\t</span><span class="s">Font: %s </span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,[</span><span class="n">fontName</span> <span class="n">UTF8String</span><span class="p">]);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>从网上下载到自己想要的字体文件，比如：楷体_GB2312.ttf（.ttf和.odf均可）。将字体文件添加到项目中，并确保字体文件已加入工程的Copy Bundle Resources中：</p>

<p><img src="http://ww1.sinaimg.cn/large/540e407ajw1ejd9h73tz4j20jg05zmxo.jpg"></p>

<p>同时要在工程的info.plist文件中添加一个名为&#8221;Fonts provided by application&#8221;的键，这个键的值是一个数组，将自定义字体文件的全名添加进去。</p>

<p><img src="http://ww1.sinaimg.cn/large/540e407ajw1ejd9i15dmkj20cw026glr.jpg"></p>

<p>以上两步做完之后，还需要再执行一下之前提到的列举所有字体的代码，从打印的字体名称中找到自定义字体的名称。例如楷体_GB2312的字体名称为：KaiTi_GB2312。</p>

<p>现在就可以在项目中使用这个自定义字体了，例如将一个UILabel对象的字体设置为楷体_GB2312，代码如下：</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="n">self</span><span class="p">.</span><span class="n">KaitiLabel</span><span class="p">.</span><span class="n">font</span> <span class="o">=</span> <span class="p">[</span><span class="n">UIFont</span> <span class="nl">fontWithName:</span><span class="s">@&quot;STKaiti&quot;</span> <span class="nl">size:</span><span class="mi">25</span><span class="p">];</span>
</span></code></pre></td></tr></table></div></figure>


<p>最后，送给大家一个使用了娃娃体Label的效果图:</p>

<p><img src="http://ww1.sinaimg.cn/large/540e407ajw1ejd9j2lqlyj20e501pdfv.jpg" title="娃娃体" ></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Settings Bundle的应用]]></title>
    <link href="http://nijino.cn/blog/2013/08/31/settings-bundle/"/>
    <updated>2013-08-31T16:08:00+08:00</updated>
    <id>http://nijino.cn/blog/2013/08/31/settings-bundle</id>
    <content type="html"><![CDATA[<p>Settings Bundle是iOS开发中独有的一个特性，它可以存放app的一些设置，使用起来非常方便。最近公司有一个项目用到了这个技术，于是我认真的研究了一下，发现了一些需要注意的地方，想跟大家分享一下。</p>

<!-- more -->


<p>任何一个项目都可以设置它的Settings Bundle，Settings Bundle字面意思就是设置的大集合，里面可以存放系统的默认设置和用户选择的值。我们可以通过点击左下角的“+”然后选择添加新文件（new file&hellip;）来生成：    <br/>
<img src="http://ww1.sinaimg.cn/large/540e407ajw1ejd9ewg2vhj20kr0e840f.jpg" title="Settings Bundle Creation" ></p>

<p>完成后会发现项目中多了一个Settings.bundle文件，展开后一般会有一个本地化的语言包（en.lproj）和Root.plist文件。本地化语言包是做国际化时用到的，而Root.plist就是用来控制这个app在系统设置中显示设置内容的文件。通过查看这个Root.plist文件你就会发现这个文件像一个大字典，并且它跟info.plist很接近，都是通过XML语法来实现的，你可以在“Preference Items”这个数组中添加一些设置项目，项目种类包括：Group、Multi Value、Slider、Text Field、Title和Toggle Switch。每一个项目都是一个字典，里面都包含有一些键值对。</p>

<p>如果是顺序添加的话直接选中“Preference Items”后点击它旁边的“+”；如果不小心选错需要变更一下项目间的顺序怎么办呢？这里面有一个小技巧。因为Root.plist本质上是一个XML文件，所以我们可以通过查看它的源代码来调整顺序。在Root.plist文件单击右键，选择Open As→Source Code，将会显示XML格式的源码。把要更改顺序项目的 <code>&lt;dict&gt;</code> 和 <code>&lt;/dict&gt;</code> 标签之间的内容（包括 <code>&lt;dict&gt;</code> 和 <code>&lt;/dict&gt;</code> 标签）移到你想要的位置即可。</p>

<p><img src="http://ww1.sinaimg.cn/large/540e407ajw1ejd9fhl24yj20f40biabr.jpg"></p>

<p>既然settings.bundle是app的设置总管，是不是程序一启动就会自动加载它里面的设置呢？我一开始也是这么认为的，可是在亲自尝试后发现不是那么回事。通过查阅相关文档我发现需要在程序启动成功后将settings.bundle中的设置注册到NSUserDefaults中去，这样才能取到设置的内容。</p>

<p>这里我推荐一个网站：<a href="https://developer.apple.com/library/ios/navigation/" title="iOS Developer Library">iOS Developer Library</a>。这个网站是苹果官方的开发者库，里面有大量的官方文档、技术问答以及示例代码。尤其要提一下示例代码，苹果的示例代码是会更新的，有时候从Xcode中的Organizer查到的不一定都是最新的示例代码。</p>

<p>在苹果的Developer Library中我查到了最新的<a href="https://developer.apple.com/library/ios/samplecode/AppPrefs/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007799" title="AppPrefs">AppPrefs</a>示例代码，里面展示了如何在程序启动时拿到settings.bundle中的设置内容，以及如何立即更新更改的设置的方法（利用NSUserDefaultsDidChangeNotification）。我们可以直接把AppPrefs中的代码复制到自己的项目中使用。</p>

<p>最后说一下，一般示例代码中的内容就是为了展示思路和方法，最好不要照本宣科的完全复制。比如这个AppPrefs，它把读取settings.bundle内容的代码放在了AppDelegate中，我个人感觉这样做会让AppDelegte类显得十分臃肿，应该把读取的代码单独放在另外一个类中，我会选择做一个NSUserDefaults的类别（category）来存放。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Interface Builder中的技巧]]></title>
    <link href="http://nijino.cn/blog/2013/08/28/interface-builder-skills/"/>
    <updated>2013-08-28T14:28:00+08:00</updated>
    <id>http://nijino.cn/blog/2013/08/28/interface-builder-skills</id>
    <content type="html"><![CDATA[<p>在我工作中经常会遇到有人吐槽Xcode中的Interface Builder（以下简称IB）不好用的开发者。在我看来，IB是一个非常棒的可视化开发工具，可以非常快捷的设置UI控件的大部分常用属性。下面就说两个IB中的技巧。</p>

<!-- more -->


<ul>
<li>快速显示元素相对位置</li>
</ul>


<p><img src="http://ww4.sinaimg.cn/large/540e407ajw1ejd9ban3mvj20av07z3yq.jpg" title="relative position relationships" ></p>

<p>这个技巧由<a href="http://weibo.com/ysy441088327" title="余书懿">余书懿</a>在新浪微博分享。
在IB中，选中一个control A,然后按住alt键，鼠标指向B，就显示A和B的相对位置关系，指向父view也行。</p>

<ul>
<li>给页面添加水平、垂直辅助线</li>
</ul>


<p>这个技巧是由我一个好朋友，同时也是陌陌的产品经理<a href="http://weibo.com/memtimen" title="Memtimen">Memtimen</a>发现的。IB中是可以添加水平和垂直的辅助线的。并且辅助线是可以拖动、重复添加和删除的。</p>

<h4>水平辅助线的快捷键是：Command ＋ Shift ＋ －</h4>

<h4>垂直辅助线的快捷键是：Command ＋ Shift ＋ ｜</h4>

<p>当然，也可以通过菜单命令来生成，位置在Editor菜单下,如下图：  <br/>
<img src="http://ww4.sinaimg.cn/large/540e407ajw1ejd9cmb5j6j20bu0alab6.jpg" title="Horizontal & Vertical Guide" ></p>

<p>辅助线的生成位置是由当前选定的view的中心点决定的，也就是说，如果当前选定了根view，那么将生成根view的辅助线；如果选中的是某一个UI控件，那就以这个控件的中心点生成。（注意下图的UILabel &amp; UIButton）</p>

<p><img src="http://ww3.sinaimg.cn/large/540e407ajw1ejd9dbkdsgj20a50gt74h.jpg"></p>

<p>有了辅助线就可以轻松根据辅助线对齐控件（辅助线可以吸附），拖动辅助线可以查看辅助线把视图分割的两部分大小。</p>

<p><img src="http://ww1.sinaimg.cn/large/540e407ajw1ejd9dyqrrwj20ac070dfs.jpg"></p>

<p>至于删除辅助线嘛，就是把辅助线在其方向上移出视图边界，你会听到嗖地一声同时会看到一个丢纸团的动画，那就表明删除辅助线成功了。</p>

<h3><em>小结：</em></h3>

<p>从我自身来讲，一开始做iOS开发也不是很爱用IB这个东西，感觉调整起来非常别扭。但是随着我做开发时间的变长，我越来越觉得IB非常好使，非常直观与节省时间。之前在《程序员》上看过一位计算机博士写的连载文章：<a href="http://www.douban.com/group/topic/23658084/" title="Mac OS X 背后的故事">《Mac OS X 背后的故事》</a>，其中有一个章节是讲<a href="http://www.programmer.com.cn/9234/" title="Jean-Marie Hullot的Interface Builder神话">Interface Builder</a>的，了解了IB的来龙去脉，才知道IB是乔帮主极力推崇的好东西。在我看来，IB才是Xcode这个IDE与众不同和精华所在，不会使用IB的iOS开发者不能算是真正iOS开发者，因为他从没有真正走进乔帮主的内心世界！</p>

<p>以上只是本人一家之言，各位看看了解一下就可以了，习惯这个东西不是那么容易改的。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[iOS6中的cellForRowAtIndexPath方法]]></title>
    <link href="http://nijino.cn/blog/2013/08/12/new-cell-for-row/"/>
    <updated>2013-08-12T14:57:00+08:00</updated>
    <id>http://nijino.cn/blog/2013/08/12/new-cell-for-row</id>
    <content type="html"><![CDATA[<p>UITableView是绝大部分iOS开发中必不可少的类。它的优势在于自身会维持一个可复用的队列，对于提高系统运行的流畅性有着不可磨灭的作用。</p>

<!-- more -->


<p>可复用的队列一般要写在UITableView的cellForRowAtIndexPath方法中，之前的写法一般是这样：</p>

<figure class='code'><figcaption><span>Standard cell for row method </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="k">static</span> <span class="n">NSString</span> <span class="o">*</span><span class="n">CellIdentifier</span> <span class="o">=</span> <span class="s">@&quot;Cell&quot;</span><span class="p">;</span>
</span><span class='line'><span class="n">UITableViewCell</span> <span class="o">*</span><span class="n">cell</span> <span class="o">=</span> <span class="p">[</span><span class="n">tableView</span> <span class="nl">dequeueReusableCellWithIdentifier:</span><span class="n">CellIdentifier</span><span class="p">];</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">cell</span> <span class="o">==</span> <span class="nb">nil</span><span class="p">){</span>
</span><span class='line'>      <span class="n">cell</span> <span class="o">=</span> <span class="p">[[</span><span class="n">UITableViewCell</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithStyle:</span><span class="n">UITableViewCellStyleSubtitle</span> <span class="nl">reuseIdentifier:</span><span class="n">CellIdentifier</span><span class="p">];</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="c1">// Configure the cell    </span>
</span><span class='line'><span class="k">return</span> <span class="n">cell</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>


<p>上面这段代码的原理是首先会定义一个静态单元格标识，之后看看可复用队列中是否存在带有这个标识的单元格，如果没有就要重新生成。</p>

<p>对于一些拥有一段iOS开发经验的开发者来说这段代码应该是再熟悉不过了，因为好多应用都会用到UITableView。但是我在Xcode5 DP版本上发现这段代码有了变化，在Xcode5 DP中新生成的UITableViewController类中的cellForRowAtIndexPath方法变成了以下这样：</p>

<figure class='code'><figcaption><span>New cell for row method in iOS6 </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="k">static</span> <span class="n">NSString</span> <span class="o">*</span><span class="n">CellIdentifier</span> <span class="o">=</span> <span class="s">@&quot;Cell&quot;</span><span class="p">;</span>
</span><span class='line'><span class="n">UITableViewCell</span> <span class="o">*</span><span class="n">cell</span> <span class="o">=</span> <span class="p">[</span><span class="n">tableView</span> <span class="nl">dequeueReusableCellWithIdentifier:</span><span class="n">CellIdentifier</span> <span class="nl">forIndexPath:</span><span class="n">indexPath</span><span class="p">];</span>
</span><span class='line'><span class="c1">// Configure the cell... </span>
</span><span class='line'><span class="k">return</span> <span class="n">cell</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>


<p>表面上看UITableView好像支持了一个新方法：dequeueReusableCellWithIdentifier:forIndexPath:,这个方法是怎么回事呢？赶紧来看看这个方法的说明：
<img src="http://ww1.sinaimg.cn/large/540e407ajw1ejd99z3d97j20k20dxwi4.jpg" title="UITableView reference" ></p>

<p>说明文档中说这个方法也可以从复用队列中提取cell。如果cell没有在复用队列中，那就会调用cell的initWithStyle:reuseIdentifier:方法生成新的cell。至于之前在代码中指定cell的风格，现在已经可以在storyboard中指定了。</p>

<p>上面这个例子充分说明了苹果在简化代码方面作出的巨大努力。Objective-C本身语法就有些长(verbose)，如果不深入研究一些简化代码的写法，那么一个项目的代码就会变的非常冗余。这也是程序员经常说的把代码写多容易，而把代码量减少并且不丧失功能才是有难度的。</p>

<p>另外我注意到这个方法是从iOS6.0版本开始支持的，可是在Xcode4.6.3中生成新的UITableViewController并不会默认生成新方法，只有Xcode5中才会生成，不知道这个方法在Xcode4.6.3中是否可以使用，需要通过实践来检验。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[KVC技巧二则]]></title>
    <link href="http://nijino.cn/blog/2013/07/02/using-kvc/"/>
    <updated>2013-07-02T14:31:00+08:00</updated>
    <id>http://nijino.cn/blog/2013/07/02/using-kvc</id>
    <content type="html"><![CDATA[<p>说两个与KVC相关的技巧。</p>

<!-- more -->


<ul>
<li>KVC与字典</li>
</ul>


<p>有时候我们需要取出嵌套字典中的某个键的值。例如某个嵌套字典：</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="n">NSDictionary</span> <span class="o">*</span><span class="n">dict</span> <span class="o">=</span> <span class="err">@</span><span class="p">{</span><span class="s">@&quot;subDict&quot;</span><span class="o">:</span><span class="err">@</span><span class="p">{</span><span class="s">@&quot;subKey&quot;</span><span class="o">:</span><span class="s">@&quot;aStr&quot;</span><span class="p">}};</span>
</span></code></pre></td></tr></table></div></figure>


<p>需要取出 <code>subKey</code> 这个键的值。以前总是用 <code>valueForKey</code> 嵌套的语法来做，其实根本不用那么麻烦，直接利用 <code>valueForKeyPath</code> 方法就可以实现。代码如下：</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="n">NSString</span> <span class="o">*</span><span class="n">str</span> <span class="o">=</span> <span class="p">[</span><span class="n">dict</span> <span class="nl">valueForKeyPath:</span><span class="s">@&quot;subDict.subKey&quot;</span><span class="p">];</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>KVC实现高阶消息传递</li>
</ul>


<p>有时候需要对数组中每个对象调用某一个方法后生成新的数组，我们可以利用KVC的高阶消息传递功能来实现。例如有下面这样一个数组：</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="n">NSArray</span> <span class="o">*</span><span class="n">originArr</span> <span class="o">=</span> <span class="err">@</span><span class="p">[</span><span class="s">@&quot;octopress&quot;</span><span class="p">,</span><span class="s">@&quot;nijino&quot;</span><span class="p">,</span><span class="s">@&quot;saki&quot;</span><span class="p">];</span>
</span></code></pre></td></tr></table></div></figure>


<p>我想将这个数组中的每一个元素首字母大写，然后生成新的数组，如果按照常规做法需要利用快速枚举对数组每一个元素进行操作，并且还要分配一个空数组来存储处理过的元素。</p>

<p>而利用KVC的高阶消息传递，只需一句话就可以达到目的：</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="n">NSArray</span> <span class="o">*</span><span class="n">resultArr</span> <span class="o">=</span> <span class="p">[</span><span class="n">originArr</span> <span class="nl">valueForKey:</span><span class="s">@&quot;capitalizedString&quot;</span><span class="p">];</span>
</span></code></pre></td></tr></table></div></figure>


<p>这样一步就实现了需求。</p>

<h3><em>小结：</em></h3>

<p>KVC是Objective－C特有的语法现象，可以加以利用实现代码的简洁性和可维护性。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[ARC在IBOutlet属性中的使用]]></title>
    <link href="http://nijino.cn/blog/2013/06/24/iboutlet-arc/"/>
    <updated>2013-06-24T22:12:00+08:00</updated>
    <id>http://nijino.cn/blog/2013/06/24/iboutlet-arc</id>
    <content type="html"><![CDATA[<p>ARC提供四种所有权修饰符:</p>

<ul>
<li>strong</li>
<li>weak</li>
<li>unsafe_unretained</li>
<li>autoreleasing</li>
</ul>


<p>其中前三个可以用于属性中声明所有权。对于这三个用于属性声明的修饰符，下面分别讲讲他们对应的使用场景。</p>

<!-- more -->


<ol>
<li><p><em>strong</em>：与之前的retain差不多，可以增加属性引用计数的值。在不需要的时候，需要手动设置属性为nil。</p></li>
<li><p><em>weak</em>：是iOS5及以上才支持的修饰符。它被称为“归零弱引用”。可以只是持有指针而不增加引用计数来避免循环保留。当指针指向的内存被销毁后，声明weak的属性指针会自动置为nil，这也是它被称为归零弱引用的原因。</p></li>
<li><p><em>unsafe_unretained</em>：对于iOS5以下版本，并不支持ARC中的weak声明，可以用unsafe_unretained声明来代替weak。unsafe_unretained同样也是不增加引用计数的值，但它没有“归零”的动作，需要手动操作，一般作为支持iOS5以下weak的替代方案。</p></li>
</ol>


<p>解释了3种属性的意义，下面说说对于属性声明为IBOutlet时3种所有权修饰符的取舍以及使用技巧。<br/>
由于我自己很熟悉Interface Bulider中的操作，所以非常喜欢那种拉控件然后连线并直接声称属性代码的操作。对于直接从xib或者storyboard拉出来生成的IBOutlet属性，一般是选择strong还是weak呢？</p>

<p><img class="right" src="http://ww2.sinaimg.cn/large/540e407ajw1ejd95zm5ymj206y0473yj.jpg" title="IBOutlet strong property instance" ></p>

<h4>这里有个原则：</h4>

<p>如果该控件位于控件树的顶部，比如
UIViewController下的view，那就应该选择strong，因为viewcontroller直接拥有该view。例如右图中的View。</p>

<p><img class="left" src="http://ww1.sinaimg.cn/large/540e407ajw1ejd96tvl2lj206h03b0sq.jpg" title="IBOutlet weak property instance" >
而如果控件是viewcontroller中view的子视图，对于这个子视图，它的所有者是它的父视图，代码中只是想引用一下这个子视图的指针而已，那么就应该选择weak（iOS5以下选择unsafe_unretained）。例如左图中的UILabel。</p>

<p>对于以上的概念，我用一张图表来说明：
<img src="http://ww3.sinaimg.cn/large/540e407ajw1ejd97ytsjhj20e209874j.jpg" title="property choosing diagram" ></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[利用NSString的Hash方法比较字符串]]></title>
    <link href="http://nijino.cn/blog/2013/06/19/nsstring-hash/"/>
    <updated>2013-06-19T14:10:00+08:00</updated>
    <id>http://nijino.cn/blog/2013/06/19/nsstring-hash</id>
    <content type="html"><![CDATA[<p>实际编程总会涉及到比较两个字符串的内容，一般会用</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="p">[</span><span class="n">string1</span> <span class="nl">isEqualsToString:</span><span class="n">string2</span><span class="p">];</span>
</span></code></pre></td></tr></table></div></figure>


<p>来比较两个字符串是否一致。对于字符串的isEqualsToString方法，需要逐个比较字符串的内容，是比较耗时的操作。</p>

<!-- more -->


<p>偶然间我发现NSString类里有个hash方法，作用是返回NSString实例的散列值。众所周知，内容相同的字符串拥有相同的散列值，内容不同的字符串拥有不同的散列值。所以完全可以根据字符串散列值来判断两个字符串是否一致。
于是上面比较字符串的写法可以这么写(一般比较字符串是if语句的判断条件):</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="k">if</span> <span class="p">([</span><span class="n">string1</span> <span class="n">hash</span><span class="p">]</span> <span class="o">==</span> <span class="p">[</span><span class="n">string2</span> <span class="n">hash</span><span class="p">])</span>
</span></code></pre></td></tr></table></div></figure>


<p>实践中发现了一个问题：有时候字符串返回的散列值为负数，而苹果文档说hash方法一定返回无符号数，不知是不是位数问题造成的。
<img src="http://ww4.sinaimg.cn/large/540e407ajw1ejd94lrb94j20e107mq47.jpg" title="NSString hash method reference" ></p>

<p>例如:</p>

<figure class='code'><figcaption><span>NSString Hash Method Example </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="n">NSString</span> <span class="o">*</span><span class="n">string1</span> <span class="o">=</span> <span class="s">@&quot;yyb&quot;</span><span class="p">;</span>
</span><span class='line'><span class="n">NSString</span> <span class="o">*</span><span class="n">string2</span> <span class="o">=</span> <span class="s">@&quot;nijino_saki&quot;</span><span class="p">;</span>
</span><span class='line'><span class="n">NSLog</span><span class="p">(</span><span class="s">@&quot;string1 hash %d&quot;</span><span class="p">,[</span><span class="n">string1</span> <span class="n">hash</span><span class="p">]);</span>
</span><span class='line'><span class="n">NSLog</span><span class="p">(</span><span class="s">@&quot;string2 hash %d&quot;</span><span class="p">,[</span><span class="n">string2</span> <span class="n">hash</span><span class="p">]);</span>
</span></code></pre></td></tr></table></div></figure>


<p>输出结果为:</p>

<figure class='code'><figcaption><span>Hash Result </span></figcaption>
<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>2013-06-19 18:47:11.612 test[26719:c07] string1 hash 530522127
</span><span class='line'>2013-06-19 18:47:11.613 test[26719:c07] string2 hash -975949159</span></code></pre></td></tr></table></div></figure>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[我的第一篇Octopress博客]]></title>
    <link href="http://nijino.cn/blog/2013/06/01/my-first-blog/"/>
    <updated>2013-06-01T06:00:00+08:00</updated>
    <id>http://nijino.cn/blog/2013/06/01/my-first-blog</id>
    <content type="html"><![CDATA[<h2>Hello Octopress!</h2>

<p>欢迎来到我的技术博客，这个博客是由Octopress构建的。
同时也欢迎访问我在<a href="http://blog.163.com/nijino_saki/" title="杨叫兽的技术博客(网易)">网易的博客</a>。</p>
]]></content>
  </entry>
  
</feed>
