<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title><![CDATA[Tassel's Blog]]></title>
  
  <link href="/atom.xml" rel="self"/>
  <link href="http://tasselx.github.io/"/>
  <updated>2016-10-09T16:09:27.000Z</updated>
  <id>http://tasselx.github.io/</id>
  
  <author>
    <name><![CDATA[Tassel]]></name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title><![CDATA[Xcode8兼容iOS7真机调试]]></title>
    <link href="http://tasselx.github.io/2016/09/27/Xcode8withiOS7-debug/"/>
    <id>http://tasselx.github.io/2016/09/27/Xcode8withiOS7-debug/</id>
    <published>2016-09-27T15:04:58.000Z</published>
    <updated>2016-10-09T16:09:27.000Z</updated>
    <content type="html"><![CDATA[<p>Xcode8 正式版已经发布，去除了对iOS7支持，使用iOS7真机调试的时候会出现下面所示的情况。</p>
<p><img src="http://ww1.sinaimg.cn/large/7c00f1e1gw1f8mgtapz2ej20n607caaf.jpg" alt="Xcode8默认不支持iOS7调试"></p>
<p>Xcode8默认支持iOS 8.0-iOS10+，但是因为一些老项目还是需要支持iOS7调试的，那么怎么办呢？当然是有解决办法的下面说下如何解决<br><code>注:如遇密码输入框，请输入电脑管理员密码</code></p>
<a id="more"></a>
<ol>
<li><p>加入DeviceSupport支持文件，可以从Xcode7里面提取到，路径是<br><code>/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport</code>放在Xcode8同样目录下面，如果找不到的话，我这里提供了网盘下载地址<a href="https://yunpan.cn/ck9b6EKcXCbML" target="_blank" rel="external">https://yunpan.cn/ck9b6EKcXCbML</a> （提取码：72da）<br><img src="http://ww4.sinaimg.cn/large/7c00f1e1gw1f8mgtzztooj20tk064q2u.jpg" alt="DeviceSupport"></p>
</li>
<li><p>修改SDKSettings设置，加入支持，路径在<br><code>/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/SDKSettings.plist</code><br>使用文本编辑器打开<br><img src="http://ww2.sinaimg.cn/large/7c00f1e1gw1f8mgue0dpaj20yg0o4dhw.jpg" alt="SDKSettings.plist"><br>加入支持后<img src="http://ww3.sinaimg.cn/large/7c00f1e1gw1f8mguw16haj21k801iwen.jpg" alt=""></p>
</li>
</ol>
<blockquote>
<p>两步完成以后，重启Xcode，就可以调试iOS7真机了</p>
</blockquote>
]]></content>
    <summary type="html">
    <![CDATA[<p>Xcode8 正式版已经发布，去除了对iOS7支持，使用iOS7真机调试的时候会出现下面所示的情况。</p>
<p><img src="http://ww1.sinaimg.cn/large/7c00f1e1gw1f8mgtapz2ej20n607caaf.jpg" alt="Xcode8默认不支持iOS7调试"></p>
<p>Xcode8默认支持iOS 8.0-iOS10+，但是因为一些老项目还是需要支持iOS7调试的，那么怎么办呢？当然是有解决办法的下面说下如何解决<br><code>注:如遇密码输入框，请输入电脑管理员密码</code></p>]]>
    
    </summary>
    
      <category term="Xcode8" scheme="http://tasselx.github.io/tags/Xcode8/"/>
    
      <category term="iOS" scheme="http://tasselx.github.io/categories/iOS/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[iOS pfx SHA1WithRSA 加签,验签]]></title>
    <link href="http://tasselx.github.io/2016/08/06/ios-pfx-sha1withrsa-sign-Verify/"/>
    <id>http://tasselx.github.io/2016/08/06/ios-pfx-sha1withrsa-sign-Verify/</id>
    <published>2016-08-06T02:37:02.000Z</published>
    <updated>2016-08-06T02:56:16.000Z</updated>
    <content type="html"><![CDATA[<blockquote>
<p>最近搞的一个加签验签，证书文件给的pfx，以前没搞过pfx，大致查了下pfx加密标准是PKCS#12里面包含公钥，以及私钥。这里我们要用到私钥加签，公钥验签,由于iOS这方面资料可能不太多，记录一下，贴下代码</p>
</blockquote>
<a id="more"></a>
<h2 id="提取私钥，然后进行加签">提取私钥，然后进行加签</h2><figure class="highlight objectivec"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br></pre></td><td class="code"><pre><span class="line">-(<span class="built_in">NSString</span> *)signTheDataSHA1WithRSA:(<span class="built_in">NSString</span> *)plainText</span><br><span class="line">&#123;</span><br><span class="line">    uint8_t* signedBytes = <span class="literal">NULL</span>;</span><br><span class="line">    size_t signedBytesSize = <span class="number">0</span>;</span><br><span class="line">    OSStatus sanityCheck = noErr;</span><br><span class="line">    <span class="built_in">NSData</span>* signedHash = <span class="literal">nil</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="built_in">NSString</span> * path = [[<span class="built_in">NSBundle</span> mainBundle]pathForResource:<span class="string">@"Xpay"</span> ofType:<span class="string">@"pfx"</span>];</span><br><span class="line">    <span class="built_in">NSData</span> * data = [<span class="built_in">NSData</span> dataWithContentsOfFile:path];</span><br><span class="line">    <span class="comment">//因为pfx之前设置的有密码所以这里要设置一下</span></span><br><span class="line">    <span class="built_in">NSMutableDictionary</span> * options = [[<span class="built_in">NSMutableDictionary</span> alloc] init]; <span class="comment">// Set the private key query dictionary.</span></span><br><span class="line">    [options setObject:<span class="string">@"xxxx"</span> forKey:(<span class="keyword">id</span>)kSecImportExportPassphrase];</span><br><span class="line">    <span class="built_in">CFArrayRef</span> items = <span class="built_in">CFArrayCreate</span>(<span class="literal">NULL</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="literal">NULL</span>);</span><br><span class="line">    OSStatus securityError = SecPKCS12Import((<span class="built_in">CFDataRef</span>) data, (<span class="built_in">CFDictionaryRef</span>)options, &amp;items);</span><br><span class="line">    <span class="keyword">if</span> (securityError!=noErr) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span> ;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">CFDictionaryRef</span> identityDict = <span class="built_in">CFArrayGetValueAtIndex</span>(items, <span class="number">0</span>);</span><br><span class="line">    SecIdentityRef identityApp =(SecIdentityRef)<span class="built_in">CFDictionaryGetValue</span>(identityDict,kSecImportItemIdentity);</span><br><span class="line">    SecKeyRef privateKeyRef=<span class="literal">nil</span>;</span><br><span class="line">    SecIdentityCopyPrivateKey(identityApp, &amp;privateKeyRef);</span><br><span class="line">    signedBytesSize = SecKeyGetBlockSize(privateKeyRef);</span><br><span class="line">    </span><br><span class="line">    <span class="built_in">NSData</span> *plainTextBytes = [plainText dataUsingEncoding:<span class="built_in">NSUTF8StringEncoding</span>];</span><br><span class="line">    </span><br><span class="line">    signedBytes = malloc( signedBytesSize * <span class="keyword">sizeof</span>(uint8_t) ); <span class="comment">// Malloc a buffer to hold signature.</span></span><br><span class="line">    memset((<span class="keyword">void</span> *)signedBytes, <span class="number">0x0</span>, signedBytesSize);</span><br><span class="line">    </span><br><span class="line">    sanityCheck = SecKeyRawSign(privateKeyRef,</span><br><span class="line">                                kSecPaddingPKCS1SHA1,</span><br><span class="line">                                (<span class="keyword">const</span> uint8_t *)[[<span class="keyword">self</span> getHashBytes:plainTextBytes] bytes],</span><br><span class="line">                                CC_SHA1_DIGEST_LENGTH,</span><br><span class="line">                                (uint8_t *)signedBytes,</span><br><span class="line">                                &amp;signedBytesSize);</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span> (sanityCheck == noErr)</span><br><span class="line">    &#123;</span><br><span class="line">        signedHash = [<span class="built_in">NSData</span> dataWithBytes:(<span class="keyword">const</span> <span class="keyword">void</span> *)signedBytes length:(<span class="built_in">NSUInteger</span>)signedBytesSize];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span> (signedBytes)</span><br><span class="line">    &#123;</span><br><span class="line">        free(signedBytes);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">NSString</span> *signatureResult=[<span class="built_in">NSString</span> stringWithFormat:<span class="string">@"%@"</span>,[signedHash base64EncodedString]];</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> signatureResult;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">- (<span class="built_in">NSData</span> *)getHashBytes:(<span class="built_in">NSData</span> *)plainText &#123;</span><br><span class="line">    CC_SHA1_CTX ctx;</span><br><span class="line">    uint8_t * hashBytes = <span class="literal">NULL</span>;</span><br><span class="line">    <span class="built_in">NSData</span> * hash = <span class="literal">nil</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// Malloc a buffer to hold hash.</span></span><br><span class="line">    hashBytes = malloc( CC_SHA1_DIGEST_LENGTH * <span class="keyword">sizeof</span>(uint8_t) );</span><br><span class="line">    memset((<span class="keyword">void</span> *)hashBytes, <span class="number">0x0</span>, kChosenDigestLength);</span><br><span class="line">    <span class="comment">// Initialize the context.</span></span><br><span class="line">    CC_SHA1_Init(&amp;ctx);</span><br><span class="line">    <span class="comment">// Perform the hash.</span></span><br><span class="line">    CC_SHA1_Update(&amp;ctx, (<span class="keyword">void</span> *)[plainText bytes], [plainText length]);</span><br><span class="line">    <span class="comment">// Finalize the output.</span></span><br><span class="line">    CC_SHA1_Final(hashBytes, &amp;ctx);</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// Build up the SHA1 blob.</span></span><br><span class="line">    hash = [<span class="built_in">NSData</span> dataWithBytes:(<span class="keyword">const</span> <span class="keyword">void</span> *)hashBytes length:(<span class="built_in">NSUInteger</span>)kChosenDigestLength];</span><br><span class="line">    <span class="keyword">if</span> (hashBytes) free(hashBytes);</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> hash;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="提取公钥，验证签名">提取公钥，验证签名</h2><figure class="highlight objectivec"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">BOOL</span> PKCSVerifyBytesSHA1withRSA(<span class="built_in">NSData</span>* plainData, <span class="built_in">NSData</span>* signature, SecKeyRef publicKey)</span><br><span class="line">&#123;</span><br><span class="line">    size_t signedHashBytesSize = SecKeyGetBlockSize(publicKey);</span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">void</span>* signedHashBytes = [signature bytes];</span><br><span class="line">    </span><br><span class="line">    size_t hashBytesSize = CC_SHA1_DIGEST_LENGTH;</span><br><span class="line">    uint8_t* hashBytes = malloc(hashBytesSize);</span><br><span class="line">    <span class="keyword">if</span> (!CC_SHA1([plainData bytes], (CC_LONG)[plainData length], hashBytes)) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">NO</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    OSStatus status = SecKeyRawVerify(publicKey,</span><br><span class="line">                                      kSecPaddingPKCS1SHA1,</span><br><span class="line">                                      hashBytes,</span><br><span class="line">                                      hashBytesSize,</span><br><span class="line">                                      signedHashBytes,</span><br><span class="line">                                      signedHashBytesSize);</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> status == errSecSuccess;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">- (SecKeyRef)getPublicKey &#123;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">NSString</span> * path = [[<span class="built_in">NSBundle</span> mainBundle]pathForResource:<span class="string">@"Xpay"</span> ofType:<span class="string">@"pfx"</span>];</span><br><span class="line">    <span class="built_in">NSData</span> * data = [<span class="built_in">NSData</span> dataWithContentsOfFile:path];</span><br><span class="line"></span><br><span class="line">    SecIdentityRef myIdentity;</span><br><span class="line">    SecTrustRef myTrust;</span><br><span class="line">    extractIdentityAndTrust((__bridge <span class="built_in">CFDataRef</span>)data, &amp;myIdentity, &amp;myTrust);</span><br><span class="line">    </span><br><span class="line">    SecKeyRef publicKey;</span><br><span class="line">    publicKey = SecTrustCopyPublicKey(myTrust);</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> publicKey;</span><br><span class="line">&#125;</span><br><span class="line">OSStatus extractIdentityAndTrust(<span class="built_in">CFDataRef</span> inP12data, SecIdentityRef *identity, SecTrustRef *trust)</span><br><span class="line">&#123;</span><br><span class="line">    OSStatus securityError = errSecSuccess;</span><br><span class="line">    </span><br><span class="line">    <span class="built_in">CFStringRef</span> password = <span class="built_in">CFSTR</span>(<span class="string">"xxxx"</span>);</span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">void</span> *keys[] = &#123; kSecImportExportPassphrase &#125;;</span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">void</span> *values[] = &#123; password &#125;;</span><br><span class="line">    </span><br><span class="line">    <span class="built_in">CFDictionaryRef</span> options = <span class="built_in">CFDictionaryCreate</span>(<span class="literal">NULL</span>, keys, values, <span class="number">1</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line">    </span><br><span class="line">    <span class="built_in">CFArrayRef</span> items = <span class="built_in">CFArrayCreate</span>(<span class="literal">NULL</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="literal">NULL</span>);</span><br><span class="line">    securityError = SecPKCS12Import(inP12data, options, &amp;items);</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span> (securityError == <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="built_in">CFDictionaryRef</span> myIdentityAndTrust = <span class="built_in">CFArrayGetValueAtIndex</span>(items, <span class="number">0</span>);</span><br><span class="line">        <span class="keyword">const</span> <span class="keyword">void</span> *tempIdentity = <span class="literal">NULL</span>;</span><br><span class="line">        tempIdentity = <span class="built_in">CFDictionaryGetValue</span>(myIdentityAndTrust, kSecImportItemIdentity);</span><br><span class="line">        *identity = (SecIdentityRef)tempIdentity;</span><br><span class="line">        <span class="keyword">const</span> <span class="keyword">void</span> *tempTrust = <span class="literal">NULL</span>;</span><br><span class="line">        tempTrust = <span class="built_in">CFDictionaryGetValue</span>(myIdentityAndTrust, kSecImportItemTrust);</span><br><span class="line">        *trust = (SecTrustRef)tempTrust;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span> (options) &#123;</span><br><span class="line">        <span class="built_in">CFRelease</span>(options);</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> securityError;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>参考<br><a href="http://blog.csdn.net/justinjing0612/article/details/7786250" target="_blank" rel="external">http://blog.csdn.net/justinjing0612/article/details/7786250</a><br><a href="https://developer.apple.com/library/mac/documentation/Security/Conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html" target="_blank" rel="external">https://developer.apple.com/library/mac/documentation/Security/Conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html</a><br><a href="https://xiuchundao.me/post/ios-read-cert-with-security-framework" target="_blank" rel="external">https://xiuchundao.me/post/ios-read-cert-with-security-framework</a></p>
</blockquote>
]]></content>
    <summary type="html">
    <![CDATA[<blockquote>
<p>最近搞的一个加签验签，证书文件给的pfx，以前没搞过pfx，大致查了下pfx加密标准是PKCS#12里面包含公钥，以及私钥。这里我们要用到私钥加签，公钥验签,由于iOS这方面资料可能不太多，记录一下，贴下代码</p>
</blockquote>]]>
    
    </summary>
    
      <category term="加密" scheme="http://tasselx.github.io/tags/%E5%8A%A0%E5%AF%86/"/>
    
      <category term="iOS" scheme="http://tasselx.github.io/categories/iOS/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[Podfile语法参考（译）]]></title>
    <link href="http://tasselx.github.io/2015/10/30/Podfile-Syntax-Reference/"/>
    <id>http://tasselx.github.io/2015/10/30/Podfile-Syntax-Reference/</id>
    <published>2015-10-30T11:56:34.000Z</published>
    <updated>2015-10-30T12:15:33.000Z</updated>
    <content type="html"><![CDATA[<p>本文翻译自官方的<a href="https://guides.cocoapods.org/syntax/podfile.html" target="_blank" rel="external">Podfile Syntax Reference</a>,也参考了之前一位博主的<a href="http://www.tomatopeter.com/blog/2014/11/22/podfile-syntax-reference-chinese/" target="_blank" rel="external">翻译</a>，若翻译中有什么异议，欢迎留言指正。<br><a id="more"></a></p>
<h2 id="Podfile">Podfile</h2><p>Podfile文件详细描述了一个或多个工程中targets的依赖关系。Podfile会默认创建一个隐式的目标链接到工程中用户的第一个target，名称为“default”。</p>
<p>一个Podfile可以非常简单:</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">pod</span> <span class="string">'AFNetworking'</span>, <span class="string">'~&gt; 1.0'</span></span><br></pre></td></tr></table></figure>
<p>也可以配置的复杂一点,如下:</p>
<figure class="highlight elixir"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">source <span class="string">'https://github.com/CocoaPods/Specs.git'</span></span><br><span class="line"></span><br><span class="line">platform <span class="symbol">:ios</span>, <span class="string">'6.0'</span></span><br><span class="line">inhibit_all_warnings!</span><br><span class="line"></span><br><span class="line">xcodeproj <span class="string">'MyProject'</span></span><br><span class="line"></span><br><span class="line">pod <span class="string">'ObjectiveSugar'</span>, <span class="string">'~&gt; 0.5'</span></span><br><span class="line"></span><br><span class="line">target <span class="symbol">:test</span> <span class="keyword">do</span></span><br><span class="line">  pod <span class="string">'OCMock'</span>, <span class="string">'~&gt; 2.0.1'</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line">post_install <span class="keyword">do</span> |installer|</span><br><span class="line">  installer.pods_project.targets.each <span class="keyword">do</span> |target|</span><br><span class="line">    puts <span class="comment">#&#123;target.name&#125;</span></span><br><span class="line">  <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure>
<h2 id="Dependencies（依赖项）">Dependencies（依赖项）</h2><p>Podfile描述用于各个用户targe中的依赖项</p>
<ul>
<li><code>pod</code> 是声明指定依赖的方法</li>
<li><code>podspec</code> 提供了一个简单的API用于创建podspecs</li>
<li><code>target</code> 允许你在工程中限定依赖项只在你指定的targets中生效</li>
</ul>
<h3 id="pod">pod</h3><p>指定工程的一个依赖</p>
<p>一个依赖项通过pod名和可选的版本号来声明</p>
<p>当你开始一个项目的时候你可能只需要一个最新版本的依赖，那么你就可以忽略版本号了，这样写：</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">pod</span> <span class="string">'SSZipArchive'</span></span><br></pre></td></tr></table></figure>
<p>以后你可能想指定一个Pod的固定版本的时候，可以写上具体的版本号来指定：</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">pod</span> <span class="string">'Objection'</span>, <span class="string">'0.9'</span></span><br></pre></td></tr></table></figure>
<p>对版本号的操作除了指定与不指定，你还可以做其他操作：</p>
<ul>
<li><code>&gt;0.1</code>  高于0.1的任何版本</li>
<li><code>&gt;=0.1</code> 版本0.1和任何更高版本</li>
<li><code>&lt;0.1</code>  低于0.1的任何版本</li>
<li><code>&lt;=0.1</code> 版本0.1和任何较低的版本</li>
<li><code>〜&gt;0.1.2</code> 版本 0.1.2的版本到0.2 ，不包括0.2。这个基于你指定的版本号的最后一个部分。这个例子等效于&gt;= 0.1.2并且 &lt;0.2.0，并且始终是你指定范围内的最新版本</li>
</ul>
<p>版本控制列表可用做更细的版本管理</p>
<p>想要了解更过关于版本控制策略的信息，可以参阅：</p>
<ul>
<li><p><a href="http://semver.org/" target="_blank" rel="external">Semantic Versioning</a></p>
</li>
<li><p><a href="http://docs.rubygems.org/read/chapter/7" target="_blank" rel="external">RubyGems Versioning Policies</a></p>
</li>
</ul>
<p>最后，你可以使用标示 <code>:head</code>来指定版本. 这就意味着工程会使用指定spec下该pod的最新可以用版本，不过会强制下载’bleeding edge’高风险版本(HEAD).务必小心使用，因为spec可能导致不兼容</p>
<figure class="highlight elixir"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pod <span class="string">'Objection'</span>, <span class="symbol">:head</span></span><br></pre></td></tr></table></figure>
<h4 id="Build_configurations（编译配置）">Build configurations（编译配置）</h4><p>重要提示:</p>
<blockquote>
<p>下面的语法是暂时的，将来很可能会更改，恕不另行通知。因为大家都在要求这个功能，所以我们发布了这个功能。你可以使用它，但你可能需要改变你的Podfile去使用未来版本的CocoaPods。不管怎么样，一个简单清晰的升级路径会提供给你</p>
</blockquote>
<p>默认情况下， 依赖项会被安装在所有target的build configuration中。为了调试或者处于其他原因，依赖项只能在给定的build configuration中被启用 </p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pod <span class="string">'PonyDebugger'</span>, :configurations =&gt; [<span class="string">'Release'</span>, <span class="string">'App Store'</span>]</span><br></pre></td></tr></table></figure>
<p>当然你也可以弄白名单只指定一个build configurations</p>
<figure class="highlight armasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">当然你也可以只指定一个<span class="keyword">build </span>configurations</span><br></pre></td></tr></table></figure>
<h4 id="Subspecs">Subspecs</h4><p>当你用一个名字装Pod的时候，它将安装所有定义在podspec里面的默认subspec</p>
<p>你可以这样指定:</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">pod</span> <span class="string">'QueryKit/Attribute'</span></span><br></pre></td></tr></table></figure>
<p>也可以指定一个集合，像下面这样:</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pod <span class="string">'QueryKit'</span>, :subspecs =&gt; [<span class="string">'Attribute'</span>, <span class="string">'QuerySet'</span>]</span><br></pre></td></tr></table></figure>
<p>当然依赖也可以从其他源来获取</p>
<h4 id="Using_the_files_from_a_local_path_(使用本地文件)">Using the files from a local path (使用本地文件)</h4><p>如果你想用一个自己开发的本地的Pod，你可以用<code>path</code>选项</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pod <span class="string">'AFNetworking'</span>, :path =&gt; <span class="string">'~/Documents/AFNetworking'</span></span><br></pre></td></tr></table></figure>
<p>使用这个选项后，Cocoapods会将给定的文件夹认为是Pod的源，并且在工程中直接引用这些文件。这就意味着你编辑的部分可以保留在CocoaPods安装中</p>
<p>被引用的文件夹可以来自你喜爱的SCM，甚至当前仓库的一个git子模块</p>
<p>注意：Pod的<code>podspec</code>文件也应该被放在这个文件夹当中</p>
<h4 id="From_a_podspec_in_the_root_of_a_library_repository_(引用仓库根目录的podspec)">From a podspec in the root of a library repository (引用仓库根目录的podspec)</h4><p>有的时候你可能想要使用一个最新的开发版本，或者某一个二次开发版本。如果是这样，你可以在pod声明中特别标明</p>
<p>使用仓库中的<code>master</code>分支:</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pod <span class="string">'AFNetworking'</span>, :git =&gt; <span class="string">'https://github.com/gowalla/AFNetworking.git'</span></span><br></pre></td></tr></table></figure>
<p>使用仓库的其他分支:</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pod <span class="string">'AFNetworking'</span>, :git =&gt; <span class="string">'https://github.com/gowalla/AFNetworking.git'</span>, :branch =&gt; <span class="string">'dev'</span></span><br></pre></td></tr></table></figure>
<p>使用仓库的某个tag:</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pod <span class="string">'AFNetworking'</span>, :git =&gt; <span class="string">'https://github.com/gowalla/AFNetworking.git'</span>, :tag =&gt; <span class="string">'0.7.0'</span></span><br></pre></td></tr></table></figure>
<p>或者指定一个提交记录:</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pod <span class="string">'AFNetworking'</span>, :git =&gt; <span class="string">'https://github.com/gowalla/AFNetworking.git'</span>, :commit =&gt; <span class="string">'082f8319af'</span></span><br></pre></td></tr></table></figure>
<p>需要特别注意的是，虽然这样将会满足任何在Pod中的依赖项通过其他Pods<br>但是podspec必须存在于仓库的根目录中，如果根目录中没有存在这个podspec文件，你将不得不使用下面提到的几种方式之一</p>
<h4 id="From_a_podspec_outside_a_spec_repository,_for_a_library_without_podspec（在一个不带podsepec的库里引用外部的spec）">From a podspec outside a spec repository, for a library without podspec（在一个不带podsepec的库里引用外部的spec）</h4><p>如果一个podspec能够从外部的仓库源的获取，设想一下，也通过HTTP来获取podspec:</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pod <span class="string">'JSONKit'</span>, :podspec =&gt; <span class="string">'https://example.com/JSONKit.podspec'</span></span><br></pre></td></tr></table></figure>
<h3 id="podspec">podspec</h3><p>使用一个在给定podspec中声明的Pod的依赖项。如果如果没有参数被传递，那么在Podfile根部的第一个podspec会被使用。它将会被库所在的工程所使用</p>
<p>注意:这个不会包含哪些来自于podspec的资源而仅仅是来自于CocoaPods基础架构</p>
<p>例子:</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">podspec</span><br></pre></td></tr></table></figure>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="rule"><span class="attribute">podspec </span>:<span class="value">name =&gt; <span class="string">'QuickDialog'</span></span></span></span><br></pre></td></tr></table></figure>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="rule"><span class="attribute">podspec </span>:<span class="value">path =&gt; <span class="string">'/Documents/PrettyKit/PrettyKit.podspec'</span></span></span></span><br></pre></td></tr></table></figure>
<h3 id="target">target</h3><p>在target块里面定义依赖项，如果对应的target不想添加依赖可以用<code>:exclusive =&gt; true</code>参数</p>
<p>Podfile文件将会创建一个全局的target名叫<code>:default</code>，default将会生成一个<code>libPod.a</code>文件。这个target将会与用户工程中的第一个target绑定起来如果没有指定特殊的<code>link_with</code>属性的话</p>
<p>例子：</p>
<p>定义一个target:</p>
<figure class="highlight elixir"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">target <span class="symbol">:ZipApp</span> <span class="keyword">do</span></span><br><span class="line">  pod <span class="string">'SSZipArchive'</span></span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure>
<p>定义一个独有的target:</p>
<figure class="highlight elixir"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">target <span class="symbol">:ZipApp</span> <span class="keyword">do</span></span><br><span class="line">  pod <span class="string">'SSZipArchive'</span></span><br><span class="line">  target <span class="symbol">:test</span>, <span class="symbol">:exclusive</span> =&gt; <span class="keyword">true</span> <span class="keyword">do</span></span><br><span class="line">    pod <span class="string">'JSONKit'</span></span><br><span class="line">  <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure>
<h2 id="Target_configuration_(目标项配置)">Target configuration (目标项配置)</h2><p>这些设置用来控制cocoapods生成project</p>
<p>开头<code>platform</code>用来说明项目的工作平台，<code>xcodeproj</code>允许你指定需要链接的工程</p>
<h3 id="platform">platform</h3><p>指定了静态库应该被编译在哪个平台</p>
<p>Cocoapods提供一个默认的部署目标如果你自己没有指定的话。目前的默认设置是<code>iOS4.3</code>、<code>OS X10.6</code>、<code>tvOS 9.0</code>、<code>watchOS 2.0</code></p>
<p>如果部署目标要求iOS版本小于<code>4.3</code>，<code>armv6</code>架构将会被添加到<code>ARCHS</code>中</p>
<p>例子：<br>指定平台</p>
<figure class="highlight crystal"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">platform <span class="symbol">:ios</span>, </span><br><span class="line">platform <span class="symbol">:ios</span></span><br></pre></td></tr></table></figure>
<h3 id="xcodeproj">xcodeproj</h3><p>指定包含引用pod库的target的Xcode工程会被链接到</p>
<p>如果没有显示的project被指定，那么会默认使用target的父target指定的project作为目标。如果如果没有任何一个target指定目标，那么就会使用和Podefile在同一目录下的project。同样也能够指定是否这些设置在release或者debug模式下生效。为了做到这一点，你必须指定一个名字和:release/:debuge关联起来</p>
<p>例子:<br>指定用户工程</p>
<figure class="highlight delphi"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># Look <span class="keyword">for</span> target <span class="keyword">to</span> link <span class="keyword">with</span> <span class="keyword">in</span> an Xcode project called</span><br><span class="line"># `MyProject.xcodeproj`.</span><br><span class="line">xcodeproj <span class="string">'MyProject'</span></span><br><span class="line"></span><br><span class="line">target :test <span class="keyword">do</span></span><br><span class="line">  # This Pods <span class="keyword">library</span> links <span class="keyword">with</span> a target <span class="keyword">in</span> another project.</span><br><span class="line">  xcodeproj <span class="string">'TestProject'</span></span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure>
<p>用自定义的编译配置</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xcodeproj <span class="string">'TestProject'</span>, <span class="string">'Mac App Store'</span> =&gt; :release, <span class="string">'Test'</span> =&gt; :debug</span><br></pre></td></tr></table></figure>
<h3 id="link_with">link_with</h3><p>指定用户project里面中面的target链接到pod库</p>
<p>如果没有显示的指定target，那么就会链接到工程中的第一个target。所以如果你只需要链接第一个target，那么你不需要使用link_with</p>
<p>例子:</p>
<p>链接用户工程里面的一个target</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">link_with</span> <span class="string">'MyApp'</span></span><br></pre></td></tr></table></figure>
<p>链接多个target</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">link_with</span> <span class="string">'MyApp'</span>, <span class="string">'MyOtherApp'</span></span><br></pre></td></tr></table></figure>
<h3 id="inhibit_all_warnings!">inhibit_all_warnings!</h3><p>屏蔽cocoapods库里面的所有警告</p>
<p>这个特性也能在子target里面定义</p>
<p>如果你想屏蔽某pod里面的警告也是可以的:</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pod <span class="string">'SSZipArchive'</span>, :inhibit_warnings =&gt; <span class="keyword">true</span></span><br></pre></td></tr></table></figure>
<h3 id="use_frameworks!">use_frameworks!</h3><p>可以用framework的pod替代静态库的</p>
<p>这个特性可以通过定义子target来继承</p>
<h2 id="Workspace（工作区）">Workspace（工作区）</h2><p>这部分内容列举了配置workspace的选项和设置全局配置</p>
<h3 id="workspace">workspace</h3><p>指定应该包含所有projects的Xcode workspace.</p>
<p>如果没有显示指定workspace并且在Podfile所在目录只有一个project，那么project的名称会被用作于workspace的名称</p>
<p>例子：<br>指定一个workspace</p>
<figure class="highlight mel"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">workspace</span> <span class="string">'MyWorkspace'</span></span><br></pre></td></tr></table></figure>
<h3 id="generate_bridge_support!">generate_bridge_support!</h3><p>指定后从所有已经安装的pod的头文件中会生成一个BridgeSupport元数据文档</p>
<p>一些脚本语言例如<code>MacRuby</code>,<code>Nu</code>,<code>JSCocoa</code>能够利用这些作为桥接类型、函数等等</p>
<h3 id="set_arc_compatibility_flag!">set_arc_compatibility_flag!</h3><p>指定后<code>-fobjc-arc</code> flag会被添加到<code>OTHER_LD_FLAGS</code>中</p>
<p>这个是用来解决编译non-ARC项目出现的一个的bug（详见 #142）。本来这些事情都是有Xcode4.3.2中的libtool自动完成的，不过看来现在flag <code>-fobjc-arc</code> 已经不被支持了。所以必须显示的指定使用这个方法</p>
<p>这个方法在CocoaPods 1.0中也许会被废弃</p>
<h2 id="Sources">Sources</h2><p>Podfile检索了所有sources(repos)中的specs</p>
<p>Sources是<code>全局的</code>，不存储在每个target定义里面</p>
<h3 id="source">source</h3><p>指定specs的位置</p>
<p>使用这个方法指定sources。sources的顺序是有关系的的。CocoaPods将使用pod第一次出现的source中的最高版本（后续的source中哪怕出现了更高的版本，也不予考虑）</p>
<p>cocoapods 官方source是隐式的需要的，一旦你指定了其他source 你就需要也把官方的指定上</p>
<p>例子:</p>
<p>指定Artsy库然后带上官方的</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">CocoaPods Master Repository</span><br><span class="line"></span><br><span class="line"><span class="built_in">source</span> <span class="string">'https://github.com/artsy/Specs.git'</span></span><br><span class="line"><span class="built_in">source</span> <span class="string">'https://github.com/CocoaPods/Specs.git'</span></span><br></pre></td></tr></table></figure>
<h2 id="Hooks（钩子）">Hooks（钩子）</h2><p>Podfile提供了钩子用来在安装时被调用</p>
<p>钩子是<code>全局的</code>，不存储在每个target定义里面</p>
<h3 id="plugin">plugin</h3><p>指定的插件应该使用在安装过程中</p>
<p>使用此方法来指定一个插件，应该在安装过程中使用，同时，应传递给插件调用时的选项</p>
<p>例子:</p>
<p>指定用<code>slather</code> 和 <code>cocoapods-keys</code>插件</p>
<figure class="highlight ocaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">plugin <span class="symbol">'cocoapods</span>-keys', :keyring =&gt; <span class="symbol">'Eidolon'</span></span><br><span class="line">plugin <span class="symbol">'slather'</span></span><br></pre></td></tr></table></figure>
<h3 id="pre_install">pre_install</h3><p>这个钩子允许你在Pods被下载后但是还未安装前对Pods做一些改变</p>
<p>它接受<a href="http://rubydoc.info/gems/cocoapods/Pod/Installer/" target="_blank" rel="external">Pod::Installer</a>作为唯一参数</p>
<p>例子:</p>
<p>定义pre_install钩子</p>
<figure class="highlight cal"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">pre_install <span class="keyword">do</span> |installer|</span><br><span class="line">  # <span class="keyword">Do</span> something fancy!</span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure>
<h3 id="post_install">post_install</h3><p>这个钩子允许你在生成的Xcode project写入硬盘或者其他你想执行的操作前做最后的改动</p>
<p>它接受<a href="http://rubydoc.info/gems/cocoapods/Pod/Installer/" target="_blank" rel="external">Pod::Installer</a>作为唯一参数</p>
<p>例子:</p>
<p>给所有target自定义编译配置</p>
<figure class="highlight livecodeserver"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">post_install <span class="built_in">do</span> |installer|</span><br><span class="line">  installer.pods_project.targets.<span class="keyword">each</span> <span class="built_in">do</span> |target|</span><br><span class="line">    target.build_configurations.<span class="keyword">each</span> <span class="built_in">do</span> |config|</span><br><span class="line">      config.build_settings[<span class="string">'GCC_ENABLE_OBJC_GC'</span>] = <span class="string">'supported'</span></span><br><span class="line">    <span class="function"><span class="keyword">end</span></span><br><span class="line">  <span class="title">end</span></span></span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure>
]]></content>
    <summary type="html">
    <![CDATA[<p>本文翻译自官方的<a href="https://guides.cocoapods.org/syntax/podfile.html">Podfile Syntax Reference</a>,也参考了之前一位博主的<a href="http://www.tomatopeter.com/blog/2014/11/22/podfile-syntax-reference-chinese/">翻译</a>，若翻译中有什么异议，欢迎留言指正。<br>]]>
    
    </summary>
    
      <category term="cocoapods" scheme="http://tasselx.github.io/tags/cocoapods/"/>
    
      <category term="iOS" scheme="http://tasselx.github.io/categories/iOS/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[iOS面试题总结（知乎分享面试题）]]></title>
    <link href="http://tasselx.github.io/2015/07/29/ios-interview/"/>
    <id>http://tasselx.github.io/2015/07/29/ios-interview/</id>
    <published>2015-07-28T17:32:21.000Z</published>
    <updated>2015-08-16T17:39:03.000Z</updated>
    <content type="html"><![CDATA[<p><img src="http://ww4.sinaimg.cn/large/7c00f1e1gw1ev4yg5cdyqj20ia0c4q3w.jpg" class="full-image"></p>
<blockquote class="blockquote-center">还有很长的路要走<br>还有很多的事要做</blockquote>

<a id="more"></a>
<ol>
<li><p>什么是ARC（ARC是为了解决什么问题诞生的）？</p>
<ul>
<li>ARC是Auto Reference Counting的缩写，即自动引用计数，由编译器在代码合适的位置中自动添加retain/Release/Autorelease/dealloc方法从而进行内存管理.</li>
<li>ARC几个要点：<br>在对象被创建时 retain count +1，在对象被release时 retain count -1.当retain count 为0 时，销毁对象。<br>程序中加入autoreleasepool的对象会由系统自动加上autorelease方法，如果该对象引用计数为0，则销毁。<br>那么ARC是为了解决什么问题诞生的呢？这个得追溯到MRC手动内存管理时代说起。<br>MRC下内存管理的缺点：<ul>
<li>当我们要释放一个堆内存时，首先要确定指向这个堆空间的指针都被release了。（避免提前释放）</li>
<li>释放指针指向的堆空间，首先要确定哪些指针指向同一个堆，这些指针只能释放一次。（MRC下即谁创建，谁释放，避免重复释放）</li>
<li>模块化操作时，对象可能被多个模块创建和使用，不能确定最后由谁去释放。</li>
<li>多线程操作时，不确定哪个线程最后使用完毕</li>
</ul>
</li>
</ul>
</li>
<li><p>请解释一下关键词的区别:</p>
<ul>
<li>assign &amp;&amp; weak<ul>
<li>assign不会改变引用计数，通常用于非指针变量的基础数据类型直接赋值，weak通常用于指向同一块内存地址的对象.</li>
<li>weak修饰的指针默认nil。在OC中向nil对象发送消息是安全的</li>
<li><strong>block对应property的copy </strong>weak对象proerty的weak</li>
<li>加了_block的局部变量才可以在block内进行修改</li>
<li>__block修改数组或指针时,block只修改指针上的内容</li>
<li>__block修改变量，内存管理的关键字为copy，会引起内存泄露。在ARC下，要避免block出现循环引用 weak typedof(self)weakSelf = self;</li>
<li>__weak修饰变量是弱引用</li>
</ul>
</li>
</ul>
</li>
<li><p>__block在ARC和非ARC下含义一样吗？</p>
<ul>
<li><p>不一样的。在MRC中的block variable在block中使用是不会retain的<br>但是在ARC中的block则retain的，取而代之的是用weak或者unsafe-unretained来更精确的描述weak reference的目的。<br>其中前者只能iOS5以后才能用，但是比较好(对象release之后，指针会直接nil),后者则是ARC环境为了兼容4.x下面的</p>
<figure class="highlight lasso"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"> __block MyClass *temp = <span class="attribute">...</span>;<span class="comment">//MRC环境下使用</span></span><br><span class="line">__weak MyClass *temp = <span class="attribute">...</span>;<span class="comment">//ARC支持iOS5.0以上的版本</span></span><br><span class="line">__unsafe_retained MyClass *temp = <span class="attribute">...</span>;<span class="comment">//ARC且可兼容到4.x以下的版本</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
</li>
<li><p>为什么其他语言里叫函数调用，Object-C里则叫给我对象发消息(或者谈下对runtime的理解)</p>
<ul>
<li>在java中，类和方法在编译期就绑定在一起</li>
<li>在OC中，方法调用是向类发送消息,如（bady cry）在运行时会转换成objc_msgSend(bady,cry),向对象发送消息时根据isa指针找到类，在根据类的调度表查找方法，没找到方法则在父类中查找直至基类，如果始终没有找到返回nil</li>
<li>Objective-C 的 Runtime 铸就了它动态语言的特性，这些深层次的知识虽然平时写代码用的少一些，但是却是每个 Objc 程序员需要了解的。Objc Runtime使得C具有了面向对象能力，在程序运行时创建，检查，修改类、对象和它们的方法。可以使用runtime的一系列方法实现。</li>
</ul>
</li>
<li><p>什么是method swizzling?</p>
<ul>
<li><p>在Objective-C中调用一个方法，其实是向一个对象发送消息，查找消息的唯一依据是selector的名字。利用Objective-C的动态特性，可以实现在运行时偷换selector对应的方法实现，达到给方法挂钩的目的。<br>每个类都有一个方法列表，存放着selector的名字和方法实现的映射关系。IMP有点类似函数指针，指向具体的Method实现。<br><img src="http://ww2.sinaimg.cn/large/7c00f1e1gw1eujww2bidbj20e5078jrp.jpg" alt="image1"></p>
<p>我们可以利用 method_exchangeImplementations 来交换2个方法中的IMP，我们可以利用 class_replaceMethod 来修改类，我们可以利用 method_setImplementation 来直接设置某个方法的IMP，归根结底，都是偷换了selector的IMP，如下图所示：</p>
<p><img src="http://ww1.sinaimg.cn/large/7c00f1e1gw1eujwwo45b0j20df0b774w.jpg" alt="image2"></p>
<p>详情：<a href="http://blog.csdn.net/yiyaaixuexi/article/details/9374411" target="_blank" rel="external">http://blog.csdn.net/yiyaaixuexi/article/details/9374411</a></p>
</li>
</ul>
</li>
<li><p>UIView和CALayer是什么关系?</p>
<ul>
<li>UIView显示在屏幕上归功于CALayer，通过调用drawRect方法来渲染自身的内容，调节CALayer属性可以调整UIView的外观，UIView继承自UIControl，比起CALayer可以响应用户操作，Xcode6之后可以方便的通过视图调试功能查看图层之间的关系</li>
<li>UIView是iOS系统中界面元素的基础，所有的界面元素都继承自它。它本身完全是由CoreAnimation来实现的(Mac下似乎不是这样)，它真正的绘图部分，是由一个叫CALayer(Core ANimation Layer)的类来管理。UIView本身，更像是一个CALayer的管理器，访问它的跟绘图和坐标有关的属性，如frame，bounds等，实际上内部都是访问它所在CALayer的相关属性</li>
<li><p>UIView有个layer属性，可以返回它的主CALayer实例，UIView有一个layerClass方法，返回主layer所使用的 类，UIView的子类，可以通过重载这个方法，来让UIView使用不同的CALayer来显示，例如通过</p>
<figure class="highlight crystal"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">  - (<span class="class"><span class="keyword">class</span>) <span class="title">layerClass</span> &#123;</span></span><br><span class="line"></span><br><span class="line">      <span class="keyword">return</span> ([<span class="constant">CAEAGLLayer</span> <span class="class"><span class="keyword">class</span>]);</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<p>使某个UIView的子类使用GL来进行绘制。</p>
<ul>
<li><p>UIView的CALayer类似UIView的子View树形结构，也可以向它的layer上添加子layer，来完成某些特殊的表 示。例如下面的代码<br>会在目标View上敷上一层黑色的透明薄膜。</p>
<figure class="highlight inform7"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">grayCover = <span class="comment">[<span class="comment">[CALayer alloc]</span>init]</span>;</span><br><span class="line">grayCover.backgroudColor = <span class="comment">[<span class="comment">[UIColor blackColor]</span>colorWithAlphaComponent:0.2]</span>.CGColor;</span><br><span class="line"><span class="comment">[self.layer addSubLayer:grayCover]</span>;</span><br></pre></td></tr></table></figure>
<ul>
<li>UIView的layer树形在系统内部，被系统维护着三份copy（这段理解有点吃不准）。</li>
</ul>
<ul>
<li>逻辑树，就是代码里可以操纵的，例如更改layer的属性等等就在这一份。</li>
<li>动画树，这是一个中间层，系统正在这一层上更改属性，进行各种渲染操作。</li>
<li>显示树，这棵树的内容是当前正被显示在屏幕上的内容。<br>这三棵树的逻辑结构都是一样的，区别只有各自的属性。</li>
</ul>
</li>
</ul>
</li>
<li><p>loadView干嘛用的?</p>
<ul>
<li><p>loadView在View为nil时调用，早于ViewDidLoad，通常用于代码实现控件，收到内存警告时会再次调用。loadView默认做的事情是:如果此VIewcontroller存在一个对应的nib文件，那么就加载这个nib。否则，就创建一个UIView对象。如果你用Interface BVuilder来创建界面，那么不应该重载这个方法。</p>
</li>
<li><p>如果你想自己创建View对象，那么可以重载这个方法，此时你需要自己给View属性赋值。你自定义的方法不应该调用super。如果你需要对View做一些其他定制操作，在ViewDidload中去做</p>
<p>根据上面的文档可以知道，有两种情况：</p>
<p>1、如果你用了nib文件，重载这个方法就没有太大意义。因为loadView的作用就是加载nib。如果你重载了这个方法不调用super，那么nib文件就不会被加载。如果调用了super，那么view已经加载完了，你需要做的其他事情在viewDidLoad里面做更合适。</p>
<p>2、如果你没有用nib，这个方法默认就是创建一个空的view对象。如果你想自己控制view对象的创建，例如创建一个特殊尺寸的view，那么可以重载这个方法，自己创建一个UIView对象，然后指定 self.view = myView; 但这种情况也没有必要调用super，因为反正你也不需要在super方法里面创建的view对象。如果调用了super，那么就是浪费了一些资源而已</p>
<p>参考：<a href="http://www.cnblogs.com/dyllove98/archive/2013/06/06/3123005.html" target="_blank" rel="external">http://www.cnblogs.com/dyllove98/archive/2013/06/06/3123005.html</a></p>
</li>
</ul>
</li>
<li><p>GCD有哪几种Queue?你自己建立过串行的Queue吗？背后的线程模型是什么样的？</p>
<ul>
<li>globalQueue和mainQueue</li>
<li>建立过，欢迎页完成一系列的动画后，弹出登录框</li>
<li>欢迎页动画并行执行，前者和后者串行执行</li>
<li>主队列dispatch_main_queue();串行更新UI</li>
<li>全局队列dispatch_global_queue();并行，四个优先级：background，low，default，high</li>
<li>自定义队列dispatch_queue_t queue;可以自定义是并行DISPATCH_QUEUE_CONCURRENT或DISPATCH_QUEUE_SERIAL</li>
</ul>
</li>
<li><p>用过Core Data 或者 SQLite吗？读写是分线程的吗？遇到过死锁没？如何解决的？</p>
<ul>
<li>用过SQLite，丢给FMDatabaseQueue或者NSLock加锁</li>
</ul>
</li>
<li><p>HTTP协议中POST方法和GET方法有那些区别?</p>
<ul>
<li>GET用于向服务器请求数据POST用于提交数据</li>
<li>GET请求，请求提以参数拼接形式暴露在地址栏，而POST请求则放在请求体里面，因此GET请求不适合用于验证密码等操作</li>
<li>更加服务器不同，POST请求会有不同的长度限制</li>
</ul>
</li>
<li><p>什么是二叉搜索树？时间复杂度是什么？</p>
<ul>
<li>采用二叉树链表作为存储结构，每个左节点均小于父节点，每个右节点均大于父节点</li>
<li>O(log2(n))</li>
</ul>
</li>
<li><p>沙盒目录结构是怎样的？各自用于那些场景？</p>
<ul>
<li>Application//存放程序源文件，上架前经过数字签名，上架后不可修改</li>
<li>Documents//常用目录，iCloud备份目录，存放数据</li>
<li>Library<ul>
<li>Caches//存放体积大又不需要备份的数据</li>
<li>Preference//设置目录，iCloud会备份设置信息</li>
</ul>
</li>
<li>tmp//存放临时文件</li>
</ul>
</li>
<li><p>#define和const变量有什么区别?</p>
<ul>
<li>define在预处理阶段进行简单的替换，const在编译阶段使用</li>
<li>宏不做类型检查，仅仅展开替换，const有数据类型，会执行类型检查</li>
<li>宏不分配内存，仅仅展开替换，const会分配内存</li>
<li>define不能调试，const可以调试</li>
<li>define定义的常量在替换后运行过程中会不断地占用内存，而const定义的常量存储在数据段，只有一份copy，效率更高</li>
<li>definde可以定义一些简单的函数，const不可以</li>
</ul>
</li>
<li><p>TCP和UDP有什么区别？</p>
<ul>
<li>TCP是面向连接的，建立连接需要经历三次握手，保证数据正确性和数据顺序</li>
<li>UDP是非连接的协议，传送数据受生成速度，传输带宽等限制，可能造成丢包</li>
<li>UDP一台服务端可以同时向多个客户端传输信息</li>
<li>TCP报头体积更大，对系统资源要求更多 </li>
</ul>
</li>
<li><p>如何制作一个静态库/动态库?他们的区别是什么？</p>
<ul>
<li>Xcode6支持制作静态库/动态库 framework</li>
<li>无论是动态库还是静态库都是区分真机和模拟器的，需要lipo命令进行合并</li>
<li>静态库编译静态库文件装入程序空间，动态库是文件动态装入内存</li>
<li>动态库执行到相关函数才会被调用，节省空间</li>
</ul>
</li>
<li><p>请简单的介绍下APNS发送系统消息的机制</p>
<ul>
<li>为什么需要APNS？为了杜绝安卓那种为了接受通知不停后台唤醒保持长连接的行为</li>
<li>由iOS系统和APNS进行长连接替代<ul>
<li>应用在通知中心就像注册，由iOS系统向APNS请求返回设备令牌</li>
<li>应用程序接收到设备令牌并发送给服务器</li>
<li>服务器把要推送的内容和设备发送给APNS</li>
<li>APNS根据设备令牌找到设备，再由iOS根据APPID把推送内容展示</li>
</ul>
</li>
</ul>
</li>
<li><p>请简述Responder Chain？</p>
<ul>
<li>UIResponder是UIView 和 UIViewController共同的父类，负责分发处理事件</li>
<li>在捕获到UIEvent后从AppDelegate-&gt;UIAppcation-&gt;UIWindow-&gt;UIViewController-&gt;UIView-&gt;SubView 进行查找</li>
<li>然后从SubView开始尝试响应这个事件，并传递给nextResponder，如果父节点不能响应则不再继续传递</li>
</ul>
</li>
<li><p>pushViewController和presentViewController有什么区别？</p>
<ul>
<li>两者都是在多个试图控制器间跳转的函数</li>
<li>presentViewController提供的是一个模态视图控制器</li>
<li>pushViewController提供一个栈控制器数组，push/pop</li>
</ul>
</li>
<li><p>请简述UITableView的复用机制</p>
<ul>
<li>UITableView在创建表视图时，不会创建numberOfRowsInSection那么多的cell，不然在所有APP标配上拉加载更多条件下，iPhone内存必然是吃不消的，通常只会创建当前页面最大可显示Cell个数加一个（实际测试有时会加二），Cell离开当前屏幕后会从队列中移除，也是基于这个原因，确定高度的Cell因为页面要显示的Cell个数唯一确定，所以在性能上能够有所提高</li>
<li>复用队列的元素增加：只有在cell被滑动出界面的时候，此cell才会被加入到复用队列中。每次在创建cell的时候，程序会首先通过调用dequeueReusableCellWithIdentifier:cellType方法，到复用队列中去寻找标示符为”cellType”的cell，如果找不到，返回nil，然后程序去通过调用[[[UITableViewCell alloc] initWithStyle:style reuseIdentifier:cellType] autorelease]来创建标示符为”cellType”的cell。</li>
</ul>
</li>
<li><p>如何应对APP版本升级，数据结构随之变化?</p>
<ul>
<li>自己解除的Sqlite相对多一些，通常的作法是重命名旧版数据库文件-&gt;创建新版本表格-&gt;导入旧版本数据-&gt;删除旧版本表</li>
<li>跨版本升级的问题，数据库更新的相关操作不做合并，依次迭代更新</li>
<li>Core data接触不多，大部分改动都在轻量化迁移支持范围内，复杂的需要重写指定映射关系</li>
</ul>
</li>
<li><p>描述一个你所遇到retain cycle例子</p>
<p>block中的循环引用:一个ViewController</p>
<figure class="highlight objectivec"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">@property</span> (<span class="keyword">nonatomic</span>,<span class="keyword">strong</span>)HttpRequestHandler * handler;</span><br><span class="line"><span class="keyword">@property</span> (<span class="keyword">nonatomic</span>,<span class="keyword">strong</span>)<span class="built_in">NSData</span>             *data;</span><br><span class="line">_handler = [httpRequestHandler sharedManager];</span><br><span class="line">[ downloadData:^(<span class="keyword">id</span> responseData)&#123;</span><br><span class="line">    _data = responseData;</span><br><span class="line">&#125;];</span><br></pre></td></tr></table></figure>
<p>self 拥有_handler, _handler 拥有block, block拥有self（因为使用了self的_data属性，block会copy 一份self）<br>解决方法：</p>
<figure class="highlight objectivec"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"> __<span class="keyword">weak</span> typedof(<span class="keyword">self</span>)weakSelf = <span class="keyword">self</span></span><br><span class="line">[ downloadData:^(<span class="keyword">id</span> responseData)&#123;</span><br><span class="line">    weakSelf<span class="variable">.data</span> = responseData;</span><br><span class="line">&#125;];</span><br></pre></td></tr></table></figure>
</li>
<li><p>+(void)load; +(void)initialize；有什么用处？</p>
<ul>
<li><p>当类对象被引入项目时, runtime 会向每一个类对象发送 load 消息. load 方法还是非常的神奇的, 因为它会在每一个类甚至分类被引入时仅调用一次, 调用的顺序是父类优先于子类, 子类优先于分类. 而且 load 方法不会被类自动继承, 每一个类中的 load 方法都不需要像 viewDidLoad 方法一样调用父类的方法. 由于 load 方法会在类被 import 时调用一次, 而这时往往是改变类的行为的最佳时机. 我在 DKNightVersion 中使用 method swizlling 来修改原有的方法时, 就是在分类 load 中实现的.</p>
<p> initialize 方法和 load 方法有一些不同, 它虽然也会在整个 runtime 过程中调用一次, 但是它是在该类的第一个方法执行之前调用, 也就是说 initialize 的调用是惰性的, 它的实现也与我们在平时使用的惰性初始化属性时基本相同. 我在实际的项目中并没有遇到过必须使用这个方法的情况, 在该方法中主要做静态变量的设置并用于确保在实例初始化前某些条件必须满足.</p>
</li>
<li><p>在Objective-C中，runtime会自动调用每个类的两个方法。+load会在类初始加载时调用，+initialize会在第一次调用类的类方法或实例方法之前被调用。这两个方法是可选的，且只有在实现了它们时才会被调用。<br>共同点：两个方法都只会被调用一次。</p>
</li>
</ul>
</li>
<li><p>如何高性能的给 UIImageView 加个圆角? (不准说 layer.cornerRadius!)</p>
<ul>
<li>一般情况下给 UIImageView 或者说 UIKit 的控件添加圆角都是改变 <code>clipsToBounds</code> 和 <code>layer.cornerRadius</code>, 这样大约两行代码就可以解决这个问题. 但是, 这样使用这样的方法会强制<br><strong>Core Animation</strong> 提前渲染屏幕的离屏绘制, 而离屏绘制就会为性能带来负面影响.</li>
</ul>
<p>我们也可以使用另一种比较复杂的方式来为图片添加圆角, 这里就用到了贝塞尔曲线.</p>
<figure class="highlight objectivec"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">    <span class="built_in">UIImageView</span> *imageView = [[<span class="built_in">UIImageView</span> alloc] initWithFrame:<span class="built_in">CGRectMake</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">100</span>, <span class="number">100</span>)];  </span><br><span class="line">imageView<span class="variable">.center</span> = <span class="built_in">CGPointMake</span>(<span class="number">200</span>, <span class="number">300</span>);  </span><br><span class="line"><span class="built_in">UIImage</span> *anotherImage = [<span class="built_in">UIImage</span> imageNamed:<span class="string">@"image"</span>];  </span><br><span class="line"><span class="built_in">UIGraphicsBeginImageContextWithOptions</span>(imageView<span class="variable">.bounds</span><span class="variable">.size</span>, <span class="literal">NO</span>, <span class="number">1.0</span>);  </span><br><span class="line">[[<span class="built_in">UIBezierPath</span> bezierPathWithRoundedRect:imageView<span class="variable">.bounds</span></span><br><span class="line">                           cornerRadius:<span class="number">50</span>] addClip];</span><br><span class="line">[anotherImage drawInRect:imageView<span class="variable">.bounds</span>];</span><br><span class="line">imageView<span class="variable">.image</span> = <span class="built_in">UIGraphicsGetImageFromCurrentImageContext</span>();  </span><br><span class="line"><span class="built_in">UIGraphicsEndImageContext</span>();  </span><br><span class="line">[<span class="keyword">self</span><span class="variable">.view</span> addSubview:imageView];</span><br></pre></td></tr></table></figure>
<p>在这里使用了贝塞尔曲线”切割”个这个图片, 给 <code>UIImageView</code> 添加了的圆角.</p>
</li>
<li><p>使用drawRect有什么影响？（这个可深可浅，你至少得用过。。）</p>
<ul>
<li><p>drawRect方法依赖Core Graphics框架来进行自定义的绘制，但这种方法主要的缺点就是它处理touch事件的方式：每次按钮被点击后，都会用setNeddsDisplay进行强制重绘；而且不止一次，每次单点事件触发两次执行。这样的话从性能的角度来说，对CPU和内存来说都是欠佳的。特别是如果在我们的界面上有多个这样的UIButton实例。</p>
<ul>
<li><p>这个方法的主要作用是根据传入的 rect 来绘制图像 <a href="https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/occ/instm/UIView/drawRect:" target="_blank" rel="external">参见文档</a>. 这个方法的默认实现没有做任何事情, 我们可以在这个方法中使用 Core Graphics 和 UIKit 来绘制视图的内容.</p>
<p>这个方法的调用机制也是非常特别. 当你调用 setNeedsDisplay 方法时, UIKit 将会把当前图层标记为 dirty, 但还是会显示原来的内容, 直到下一次的视图渲染周期, 才会为标记为 dirty 的图层重新建立 Core Graphics 上下文, 然后将内存中的数据恢复出来, 再使用 CGContextRef 进行绘制.</p>
<p>相关参考:<a href="http://xyxdasnjss.iteye.com/blog/1827954" target="_blank" rel="external">UIView的layoutSubviews和drawRect方法何时调用</a></p>
</li>
</ul>
</li>
</ul>
</li>
<li><p>ASIHttpRequest 或者 SDWebImage 里面给 UIImageView 加载图片的逻辑是什么样的?</p>
<ul>
<li><p>我曾经阅读过 SDWebImage 的源代码, 就在这里对如何给 UIImageView 加载图片做一个总结吧, SDWebImage 中为 UIView 提供了一个分类叫做 WebCache, 这个分类中有一个最常用的接口, sd_setImageWithURL:placeholderImage:, 这个分类同时提供了很多类似的方法, 这些方法最终会调用一个同时具有 option progressBlock completionBlock 的方法, 而在这个类最终被调用的方法首先会检查是否传入了 placeholderImage 以及对应的参数, 并设置 placeholderImage.</p>
<p>然后会获取 SDWebImageManager 中的单例调用一个 downloadImageWithURL:… 的方法来获取图片, 而这个 manager 获取图片的过程有大体上分为两部分, 它首先会在 SDWebImageCache 中寻找图片是否有对应的缓存, 它会以 url 作为数据的索引先在内存中寻找是否有对应的缓存, 如果缓存未命中就会在磁盘中利用 MD5 处理过的 key 来继续查询对应的数据, 如果找到了, 就会把磁盘中的缓存备份到内存中.</p>
<p>然而, 假设我们在内存和磁盘缓存中都没有命中, 那么 manager 就会调用它持有的一个 SDWebImageDownloader 对象的方法 downloadImageWithURL:… 来下载图片, 这个方法会在执行的过程中调用另一个方法 addProgressCallback:andCompletedBlock:fotURL:createCallback: 来存储下载过程中和下载完成的回调, 当回调块是第一次添加的时候, 方法会实例化一个 NSMutableURLRequest 和 SDWebImageDownloaderOperation, 并将后者加入 downloader 持有的下载队列开始图片的异步下载.<br>而在图片下载完成之后, 就会在主线程设置 image, 完成整个图像的异步下载和配置.</p>
</li>
</ul>
</li>
<li><p>使用atomic一定是线程安全的吗？</p>
<ul>
<li>不是，atomic的本意是指属性的存取方法是线程安全的（thread safe)，并不保证整个对象是线程安全的。比如，声明一个NSMutableArray的原子属性stuff，此时self.stuff 和self.stuff = othersulf都是线程安全的。但是，使用[self.stuff objectAtIndex:index]就不是线程安全的，需要用锁来保证线程安全性。</li>
</ul>
</li>
</ol>
<hr>
<blockquote>
<p>参考:<br><a href="http://www.zhihu.com/question/19604641" target="_blank" rel="external">http://www.zhihu.com/question/19604641</a><br> <a href="http://draveness.me/guan-yu-xie-ios-wen-ti-de-jie-da/" target="_blank" rel="external">http://draveness.me/guan-yu-xie-ios-wen-ti-de-jie-da/</a><br><a href="http://www.jianshu.com/p/d72c4b595c7b" target="_blank" rel="external">http://www.jianshu.com/p/d72c4b595c7b</a><br><a href="http://weibo.com/1832164643/Ct3B4hzl3?type=comment#_rnd1438104612567" target="_blank" rel="external">http://weibo.com/1832164643/Ct3B4hzl3?type=comment#_rnd1438104612567</a></p>
</blockquote>
]]></content>
    <summary type="html">
    <![CDATA[<p><img src="http://ww4.sinaimg.cn/large/7c00f1e1gw1ev4yg5cdyqj20ia0c4q3w.jpg" class="full-image" /></p>
<blockquote class="blockquote-center">还有很长的路要走<br>还有很多的事要做</blockquote>]]>
    
    </summary>
    
      <category term="面试" scheme="http://tasselx.github.io/tags/%E9%9D%A2%E8%AF%95/"/>
    
      <category term="iOS" scheme="http://tasselx.github.io/categories/iOS/"/>
    
  </entry>
  
  <entry>
    <title><![CDATA[面试题]]></title>
    <link href="http://tasselx.github.io/2015/07/16/Interview/"/>
    <id>http://tasselx.github.io/2015/07/16/Interview/</id>
    <published>2015-07-16T05:31:57.000Z</published>
    <updated>2016-01-22T05:09:25.000Z</updated>
    <content type="html"><![CDATA[<p><img src="http://ww3.sinaimg.cn/large/7c00f1e1gw1ev506yzdjyj20ia0c7405.jpg" class="fullimage"></p>
<blockquote class="blockquote-center">一叶障目<br>不见泰山</blockquote>

<a id="more"></a>
<blockquote>
<p> 记一次面试过程遇到的东西吧,总结一下</p>
</blockquote>
<h2 id="笔试题">笔试题</h2><p>###题1</p>
<blockquote>
<p>int a[5]={1,2,3,4,5};int <em>p=(int </em>)(&amp;a+1);问<em>(a+1),</em>(p-1)是多少</p>
</blockquote>
<p>答:<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">*(a+<span class="number">1</span>）就是a[<span class="number">1</span>]，*(p-<span class="number">1</span>)就是a[<span class="number">4</span>],执行结果是<span class="number">2</span>，<span class="number">5</span></span><br><span class="line">&amp;a+<span class="number">1</span>不是首地址+<span class="number">1</span>，系统会认为加一个a数组的偏移，是偏移了一个数组的大小（本例是<span class="number">5</span>个<span class="keyword">int</span>）</span><br><span class="line"><span class="keyword">int</span> *p=(<span class="keyword">int</span> *)(&amp;a+<span class="number">1</span>);</span><br><span class="line">则p实际是&amp;(a[<span class="number">5</span>]),也就是a+<span class="number">5</span></span><br><span class="line">原因如下：</span><br><span class="line"> &amp;a是数组指针，其类型为 <span class="keyword">int</span> (*)[<span class="number">5</span>];</span><br><span class="line">而指针加<span class="number">1</span>要根据指针类型加上一定的值，不同类型的指针+<span class="number">1</span>之后增加的大小不同。</span><br><span class="line">a是长度为<span class="number">5</span>的<span class="keyword">int</span>数组指针，所以要加 <span class="number">5</span>*<span class="keyword">sizeof</span>(<span class="keyword">int</span>)</span><br><span class="line">所以p实际是a[<span class="number">5</span>]</span><br><span class="line">但是p与(&amp;a+<span class="number">1</span>)类型是不一样的(这点很重要)</span><br><span class="line">所以p-<span class="number">1</span>只会减去<span class="keyword">sizeof</span>(<span class="keyword">int</span>*)</span><br><span class="line">a,&amp;a的地址是一样的，但意思不一样</span><br><span class="line">a是数组首地址，也就是a[<span class="number">0</span>]的地址，&amp;a是对象（数组）首地址，</span><br><span class="line">a+<span class="number">1</span>是数组下一元素的地址，即a[<span class="number">1</span>],&amp;a+<span class="number">1</span>是下一个对象的地址，即a[<span class="number">5</span>].</span><br></pre></td></tr></table></figure></p>
<h3 id="题2">题2</h3><blockquote>
<p>frame和bounds有什么不同，size是否会不同？</p>
</blockquote>
<h3 id="题3">题3</h3><blockquote>
<p>readwrite，readonly，assign，retain，copy，nonatomic 属性的作用</p>
</blockquote>
<p>答<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">@property是一个属性访问声明，扩号内支持以下几个属性：</span><br><span class="line"><span class="number">1</span>，getter=getterName，setter=setterName，设置setter与 getter的方法名</span><br><span class="line"><span class="number">2</span>，readwrite,readonly，设置可供访问级别</span><br><span class="line"><span class="number">2</span>，assign，setter方法直接赋值，不进行任何retain操作，为了解决原类型与环循引用问题</span><br><span class="line"><span class="number">3</span>，retain，setter方法对参数进行release旧值再retain新值，所有实现都是这个顺序(CC上有相关资料)</span><br><span class="line"><span class="number">4</span>，copy，setter方法进行Copy操作，与retain处理流程一样，先旧值release，再 Copy出新的对象，retainCount为<span class="number">1</span>。</span><br><span class="line">   这是为了减少对上下文的依赖而引入的机制。</span><br><span class="line"><span class="number">5</span>，nonatomic，非原子性访问，不加同步，多线程并发访问会提高性能。注意，如果不加此属性，则默认是两个访问方法</span><br><span class="line">   都为原子型事务访问。锁被加到所属对象实例级(我是这么理解的...)。</span><br></pre></td></tr></table></figure></p>
<h3 id="题4">题4</h3><blockquote>
<p>求2-100之间的素数(质数)和</p>
</blockquote>
<p>答</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">int</span> <span class="built_in">num</span>;</span><br><span class="line"><span class="built_in">int</span> i;</span><br><span class="line"><span class="built_in">int</span> sum;</span><br><span class="line">        </span><br><span class="line"><span class="keyword">for</span> (<span class="built_in">num</span> = <span class="number">2</span>; <span class="built_in">num</span>&lt;=<span class="number">100</span>; <span class="built_in">num</span>++) &#123;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">for</span> (i=<span class="number">2</span>; i&lt;=<span class="built_in">num</span>; i++) &#123;</span><br><span class="line">            <span class="comment">//遇到能相除余为0的就跳出循环，然后当前num 和 当前除数相比，除数最大的那一时刻的num值</span></span><br><span class="line">                <span class="keyword">if</span> (<span class="built_in">num</span>%i==<span class="number">0</span>) &#123;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">//也即是本事是自己最大的能相除的数</span></span><br><span class="line">            <span class="keyword">if</span> (i&gt;=<span class="built_in">num</span>) &#123;</span><br><span class="line">                sum+=<span class="built_in">num</span>;</span><br><span class="line">                printf(<span class="string">"素数 %d"</span>,<span class="built_in">num</span>);</span><br><span class="line">            &#125;</span><br><span class="line">            </span><br><span class="line">        &#125;</span><br><span class="line">    </span><br><span class="line">        printf(<span class="string">"总和为 %d"</span>,sum);</span><br></pre></td></tr></table></figure>
<h2 id="逻辑题">逻辑题</h2><h3 id="逻辑题1">逻辑题1</h3><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#19968;&#23618;&#27004;,&#26377;10&#32423;&#21488;&#38454;,&#21487;&#20197;&#19968;&#27493;&#12289;&#20108;&#27493;&#25110;&#19977;&#27493;&#36208;,&#26377;&#20960;&#31181;&#36208;&#27861;?&#10;&#20855;&#20307;&#22320;&#35828;</span><br></pre></td></tr></table></figure>
<p>答</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line">逐次累加法</span><br><span class="line">到第一层：<span class="number">1</span>种</span><br><span class="line">到第二层：<span class="number">2</span>种</span><br><span class="line">到第三层：<span class="number">4</span>种,分别为</span><br><span class="line"><span class="number">1</span> <span class="number">1</span> <span class="number">1</span> </span><br><span class="line"><span class="number">1</span> <span class="number">2</span></span><br><span class="line"><span class="number">2</span> <span class="number">1</span></span><br><span class="line"><span class="number">3</span></span><br><span class="line">到第四层 <span class="number">7</span>种.计算过程为：</span><br><span class="line">到第一层的方法数 + 到第二层方法数 + 到第三层方法数.分别为</span><br><span class="line"><span class="number">1</span> -- <span class="number">3</span></span><br><span class="line"><span class="number">1</span> <span class="number">1</span> -- <span class="number">2</span></span><br><span class="line"><span class="number">2</span> -- <span class="number">2</span></span><br><span class="line"><span class="number">1</span> <span class="number">1</span> <span class="number">1</span> -- <span class="number">1</span></span><br><span class="line"><span class="number">1</span> <span class="number">2</span> -- <span class="number">1</span></span><br><span class="line"><span class="number">2</span> <span class="number">1</span> -- <span class="number">1</span></span><br><span class="line"><span class="number">3</span> -- <span class="number">1</span></span><br><span class="line">到第五层方法数：<span class="number">13</span>种</span><br><span class="line">计算过程为：到第二层的方法数 + 到第三层方法数 + 到第四层方法数.</span><br><span class="line">具体为</span><br><span class="line"><span class="number">1</span> <span class="number">1</span> -- <span class="number">3</span></span><br><span class="line"><span class="number">2</span> -- <span class="number">3</span></span><br><span class="line"><span class="number">1</span> <span class="number">1</span> <span class="number">1</span> -- <span class="number">2</span></span><br><span class="line"><span class="number">1</span> <span class="number">2</span> -- <span class="number">2</span></span><br><span class="line"><span class="number">2</span> <span class="number">1</span> -- <span class="number">2</span></span><br><span class="line"><span class="number">3</span> -- <span class="number">2</span></span><br><span class="line"><span class="number">1</span> <span class="number">3</span> -- <span class="number">1</span></span><br><span class="line"><span class="number">1</span> <span class="number">1</span> <span class="number">2</span> -- <span class="number">1</span></span><br><span class="line"><span class="number">2</span> <span class="number">2</span> -- <span class="number">1</span></span><br><span class="line"><span class="number">1</span> <span class="number">1</span> <span class="number">1</span> <span class="number">1</span> -- <span class="number">1</span></span><br><span class="line"><span class="number">1</span> <span class="number">2</span> <span class="number">1</span> -- <span class="number">1</span></span><br><span class="line"><span class="number">2</span> <span class="number">1</span> <span class="number">1</span> -- <span class="number">1</span></span><br><span class="line"><span class="number">3</span> <span class="number">1</span> -- <span class="number">1</span></span><br><span class="line">余此类推：</span><br><span class="line">到第六层 = 到第三层+到第四层+到第五层 = <span class="number">4</span>+<span class="number">7</span>+<span class="number">13</span> = <span class="number">24</span></span><br><span class="line">到第七层 = 到第四层+到第五层+到第六层 = <span class="number">7</span>+<span class="number">13</span>+<span class="number">24</span> = <span class="number">44</span></span><br><span class="line">到第八层 = 到第五层+到第六层+到第七层 = <span class="number">13</span>+<span class="number">24</span>+<span class="number">44</span> = <span class="number">81</span></span><br><span class="line">到第九层 = 到第六层+到第七层+到第八层 = <span class="number">24</span>+<span class="number">44</span>+<span class="number">81</span> = <span class="number">149</span></span><br><span class="line">到第十层 = 到第七层+到第八层+到第九层 = <span class="number">44</span>+<span class="number">81</span>+<span class="number">149</span> = <span class="number">274</span></span><br><span class="line">---------------------------</span><br><span class="line">说明：在这种思路中,比如计算到达第九层的方法数时候,到第<span class="number">6</span>层后要直接迈<span class="number">3</span>步到达第<span class="number">9</span>层,到第<span class="number">7</span>层后要直接迈<span class="number">2</span>步到达第<span class="number">9</span>层.不考虑从第<span class="number">6</span>层开始迈<span class="number">1</span>步或<span class="number">2</span>步的情况,以免重复计算.</span><br></pre></td></tr></table></figure>
<h3 id="逻辑题2">逻辑题2</h3><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">甲、乙、丙三人讨论一道题，当每一个人都把自己的解法说出后，甲说：“我做错了。”乙说：“甲做对了。”丙说：“我做错了。”老师看过他们的答案，并听了他们的上述意见后，说三个人中有一个答案正确，有一个意见正确。 ? ?由此可知，谁的意见正确</span><br></pre></td></tr></table></figure>
<p>答</p>
<figure class="highlight gcode"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">三个人的意见只有一人正确，首先可以看出甲和乙的意见矛盾，必有一真一假，据此推出丙的意见必然为假，即丙没做错，丙的答案是对的。三人中只有一人答案正确，据此可以推出甲说真话<span class="comment">(甲的意见正确)</span></span><br></pre></td></tr></table></figure>
<h3 id="逻辑题3">逻辑题3</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">12</span>个相同小球里面有一个重量不一样<span class="number">3</span>次找出来</span><br></pre></td></tr></table></figure>
<p>答</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
    <summary type="html">
    <![CDATA[<p><img src="http://ww3.sinaimg.cn/large/7c00f1e1gw1ev506yzdjyj20ia0c7405.jpg" class = "fullimage" /></p>
<blockquote class="blockquote-center">一叶障目<br>不见泰山</blockquote>]]>
    
    </summary>
    
      <category term="iOS开发" scheme="http://tasselx.github.io/tags/iOS%E5%BC%80%E5%8F%91/"/>
    
      <category term="面试" scheme="http://tasselx.github.io/tags/%E9%9D%A2%E8%AF%95/"/>
    
  </entry>
  
</feed>
