<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.0">Jekyll</generator><link href="https://dcell.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://dcell.github.io/" rel="alternate" type="text/html" /><updated>2021-12-14T11:38:46+00:00</updated><id>https://dcell.github.io/feed.xml</id><title type="html">Dcell Blog</title><subtitle>iOS/android/webapp developer.
</subtitle><author><name>Dcell</name><email>767536477@qq.com</email></author><entry><title type="html">手机控制软件[wormhole] 破解</title><link href="https://dcell.github.io/2021/06/28/%E6%89%8B%E6%9C%BA%E6%8E%A7%E5%88%B6%E8%BD%AF%E4%BB%B6-wormhole-%E7%A0%B4%E8%A7%A3.html" rel="alternate" type="text/html" title="手机控制软件[wormhole] 破解" /><published>2021-06-28T00:00:00+00:00</published><updated>2021-06-28T00:00:00+00:00</updated><id>https://dcell.github.io/2021/06/28/%E6%89%8B%E6%9C%BA%E6%8E%A7%E5%88%B6%E8%BD%AF%E4%BB%B6%5Bwormhole%5D%E7%A0%B4%E8%A7%A3</id><content type="html" xml:base="https://dcell.github.io/2021/06/28/%E6%89%8B%E6%9C%BA%E6%8E%A7%E5%88%B6%E8%BD%AF%E4%BB%B6-wormhole-%E7%A0%B4%E8%A7%A3.html">&lt;h2 id=&quot;前言&quot;&gt;前言&lt;/h2&gt;

&lt;p&gt;平时我们开发过程中，难免会要进行真机的调试。有没有一款应用能让真机和模拟器一样方便使用呢？ 我在搜索了一番后，发现一款应用叫 &lt;em&gt;Wormhole&lt;/em&gt; ，免费使用3天，后续升级Pro 45元。&lt;/p&gt;

&lt;h2 id=&quot;破解&quot;&gt;破解&lt;/h2&gt;

&lt;h3 id=&quot;方式1&quot;&gt;方式1&lt;/h3&gt;

&lt;p&gt;本想通过抓包分析下应用协议，然后进行拦截替换，但是发现协议包都是加密的，而且是双向证书认证，无法进行中间者模式攻击。该方式在尝试后放弃。&lt;/p&gt;

&lt;h3 id=&quot;方式2&quot;&gt;方式2&lt;/h3&gt;

&lt;p&gt;直接进行硬核破解，修改汇编指令集，替换可执行2进制文件&lt;/p&gt;

&lt;h4 id=&quot;第一步&quot;&gt;第一步&lt;/h4&gt;

&lt;p&gt;安装相关程序包  &lt;a href=&quot;https://er.run/&quot;&gt;Wormhole&lt;/a&gt; ，将程序包安装到 Applications&lt;/p&gt;

&lt;h4 id=&quot;第二步&quot;&gt;第二步&lt;/h4&gt;

&lt;p&gt;将 /Applications/Wormhole.app/Contents/MacOS/Wormhole 二进制文件拖到 Hopper&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.loli.net/2021/08/18/nFEDcZs8w4NS9Kl.png&quot; alt=&quot;截屏2021-08-18 下午2.04.02&quot; /&gt;&lt;/p&gt;

&lt;p&gt;选择 Debug -&amp;gt; Select Debugger&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.loli.net/2021/08/18/aH9szTu6qSro4i7.png&quot; alt=&quot;截屏2021-08-18 下午2.08.43&quot; /&gt;&lt;/p&gt;

&lt;p&gt;启动应用后，我们可以通过LLDB 或者 Hopper工具 调试挂载进去。接下来我们分析汇编的一些代码逻辑，我们省略中间过程直接讲结果。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.loli.net/2021/08/18/9hmOrnapXdzfAei.png&quot; alt=&quot;截屏2021-08-18 下午2.16.20&quot; /&gt;&lt;/p&gt;

&lt;p&gt;搜索关键字 &lt;em&gt;active&lt;/em&gt; , 双击打开 CheckActiveResponse函数&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.loli.net/2021/08/18/nXtNHiwVrqhOekR.png&quot; alt=&quot;截屏2021-08-18 下午2.18.21&quot; /&gt;&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int32_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rsi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xc8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//判断返回Code是否是200&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ChoosePlatformWidget&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UpdateProState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rdi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//判断该用户状态是否 激活状态&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;所以我们只需要修改下面这个判断，让他永久成立即可。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.loli.net/2021/08/18/gWYt9M2xpQDLn4a.png&quot; alt=&quot;截屏2021-08-18 下午2.24.02&quot; /&gt;&lt;/p&gt;

&lt;p&gt;找到对应的汇编代码，修改 je =&amp;gt; jne ，然后重新生成二进制文件，替换原先的文件。&lt;/p&gt;</content><author><name>Dcell</name><email>767536477@qq.com</email></author><summary type="html">前言</summary></entry><entry><title type="html">Dark mode on the web</title><link href="https://dcell.github.io/2021/03/22/Dark-mode-on-the-web.html" rel="alternate" type="text/html" title="Dark mode on the web" /><published>2021-03-22T00:00:00+00:00</published><updated>2021-03-22T00:00:00+00:00</updated><id>https://dcell.github.io/2021/03/22/Dark%20mode%20on%20the%20web</id><content type="html" xml:base="https://dcell.github.io/2021/03/22/Dark-mode-on-the-web.html">&lt;p&gt;随着App混合开发的流行，一些复杂App往往会加载一些H5相关的网页；自从iOS 13加入暗黑模式以后，android的一些厂商也加入了暗黑模式。如果在暗黑模式中加载了一个正常的H5样式，那么对视觉的冲击是比较大的，所以我们需要H5 Web能随着系统的模式自动切换。&lt;/p&gt;

&lt;h2 id=&quot;toggling-themes&quot;&gt;Toggling Themes&lt;/h2&gt;

&lt;h4 id=&quot;using-a-body-class&quot;&gt;Using a Body Class&lt;/h4&gt;

&lt;p&gt;我们通过css样式切换，可以简单的切换一个主题。&lt;/p&gt;

&lt;iframe height=&quot;265&quot; style=&quot;width: 100%;&quot; scrolling=&quot;no&quot; title=&quot;Method 1 - Class Swapping&quot; src=&quot;https://codepen.io/adhuham/embed/dyodgPj?height=265&amp;amp;theme-id=light&amp;amp;default-tab=html,result&quot; frameborder=&quot;no&quot; loading=&quot;lazy&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot;&gt;
  See the Pen &lt;a href=&quot;https://codepen.io/adhuham/pen/dyodgPj&quot;&gt;Method 1 - Class Swapping&lt;/a&gt; by Mohamed Adhuham
  (&lt;a href=&quot;https://codepen.io/adhuham&quot;&gt;@adhuham&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;

&lt;h4 id=&quot;using-separate-stylesheets&quot;&gt;Using Separate Stylesheets&lt;/h4&gt;

&lt;p&gt;一个优秀的前端开发工程师，在做项目开发的时候，会做一套样式管理，合理利用CSS 样式继承。我们假如你的工程已经有了一套样式 ‘Light Theme’，那么我们开发Dark Theme，只需要按照现有的样式开发一套对立的样式。&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;lang=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;en&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Light theme stylesheet --&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;light-theme.css&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;theme-link&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- etc. --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Select the button&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;btn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.btn-toggle&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Select the stylesheet &amp;lt;link&amp;gt;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;theme&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;#theme-link&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Listen for a click on the button&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;btn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// If the current URL contains &quot;ligh-theme.css&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;theme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;light-theme.css&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ... then switch it to &quot;dark-theme.css&quot;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;theme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;href&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;dark-theme.css&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Otherwise...&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ... switch it to &quot;light-theme.css&quot;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;theme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;href&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;light-theme.css&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://codepen.io/adhuham/project/editor/AqjdGV&quot;&gt;Demo&lt;/a&gt;&lt;/p&gt;

&lt;h4 id=&quot;using-custom-properties&quot;&gt;Using Custom Properties&lt;/h4&gt;

&lt;p&gt;我们也可以通过自定义属性来做样式的切换，如果你是多人协作开发，我认为这是个不错的方案。&lt;/p&gt;

&lt;iframe height=&quot;265&quot; style=&quot;width: 100%;&quot; scrolling=&quot;no&quot; title=&quot;KKaPMWM&quot; src=&quot;https://codepen.io/dcell/embed/KKaPMWM?height=265&amp;amp;theme-id=light&amp;amp;default-tab=html,result&quot; frameborder=&quot;no&quot; loading=&quot;lazy&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot;&gt;
  See the Pen &lt;a href=&quot;https://codepen.io/dcell/pen/KKaPMWM&quot;&gt;KKaPMWM&lt;/a&gt; by Dcell
  (&lt;a href=&quot;https://codepen.io/dcell&quot;&gt;@dcell&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;

&lt;h2 id=&quot;dark-mode-at-the-operating-system-level&quot;&gt;Dark Mode at the Operating System Level&lt;/h2&gt;

&lt;p&gt;上面我们讲了些，如何通过手动的方式来切换模式（当然你可以通过URL?mode=dark），那么有没有自动跟随系统的方式呢？&lt;/p&gt;

&lt;p&gt;CSS提供了一个参数：&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prefers-color-scheme&lt;/code&gt;&lt;/strong&gt; &lt;a href=&quot;https://developer.mozilla.org/zh-CN/docs/Web/CSS/Media_Queries/Using_media_queries#media_features&quot;&gt;媒体特性&lt;/a&gt;用于检测用户是否有将系统的主题色设置为亮色或者暗色。&lt;/p&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prefers-color-scheme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;/* Dark theme styles go here */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prefers-color-scheme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;light&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;/* Light theme styles go here */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;iframe height=&quot;265&quot; style=&quot;width: 100%;&quot; scrolling=&quot;no&quot; title=&quot;Prefers Color Scheme: Demo Use Case&quot; src=&quot;https://codepen.io/team/css-tricks/embed/mdVrQXV?height=265&amp;amp;theme-id=light&amp;amp;default-tab=html,result&quot; frameborder=&quot;no&quot; loading=&quot;lazy&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot;&gt;
  See the Pen &lt;a href=&quot;https://codepen.io/team/css-tricks/pen/mdVrQXV&quot;&gt;Prefers Color Scheme: Demo Use Case&lt;/a&gt; by CSS-Tricks
  (&lt;a href=&quot;https://codepen.io/css-tricks&quot;&gt;@css-tricks&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;

&lt;p&gt;我们也可以检测当前浏览器是否有暗黑模式&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;prefersDarkScheme&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;matchMedia&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;(prefers-color-scheme: dark)&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prefersDarkScheme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;matches&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;//add dark theme&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;//remove dark theme&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这样一看真是非常的方便，但是我们忽略了一点，这个特性只支持 Chrome 76+, Firefox 67+, Chrome Android 76+, Safari 12.5+ (13+ on iOS), and Samsung Internet Browser.&lt;/p&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;

&lt;p&gt;现阶段来说，如果要实现暗黑模式还是需要手动管理CSS样式，当然在高级版本可以自动做些切换，做一些体验上的优化。&lt;/p&gt;</content><author><name>Dcell</name><email>767536477@qq.com</email></author><summary type="html">随着App混合开发的流行，一些复杂App往往会加载一些H5相关的网页；自从iOS 13加入暗黑模式以后，android的一些厂商也加入了暗黑模式。如果在暗黑模式中加载了一个正常的H5样式，那么对视觉的冲击是比较大的，所以我们需要H5 Web能随着系统的模式自动切换。</summary></entry><entry><title type="html">objc4 流言终结者</title><link href="https://dcell.github.io/2021/03/08/objc4-%E6%B5%81%E8%A8%80%E7%BB%88%E7%BB%93%E8%80%85.html" rel="alternate" type="text/html" title="objc4 流言终结者" /><published>2021-03-08T00:00:00+00:00</published><updated>2021-03-08T00:00:00+00:00</updated><id>https://dcell.github.io/2021/03/08/objc4%20%E6%B5%81%E8%A8%80%E7%BB%88%E7%BB%93%E8%80%85</id><content type="html" xml:base="https://dcell.github.io/2021/03/08/objc4-%E6%B5%81%E8%A8%80%E7%BB%88%E7%BB%93%E8%80%85.html">&lt;blockquote&gt;
  &lt;p&gt;源码都是基于objc-782，818版本，Swift5 ；老版本可能有不同的地方&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;nsobject-alloc-init-和-nsobject-new-的区别&quot;&gt;[[NSObject alloc] init] 和 [NSObject new] 的区别&lt;/h2&gt;

&lt;p&gt;我采用3种方式来验证&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-objective-c&quot;&gt;id a = [ClassA alloc];

id aa = [[ClassA alloc] init];

id aaa = [ClassA new];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;第一个，执行的堆栈，发现执行了2次 &lt;strong&gt;callAlloc&lt;/strong&gt;，最终执行到&lt;strong&gt;_objc_rootAllocWithZone&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-objective-c&quot;&gt;id a = [ClassA alloc];
        
#0 _objc_rootAllocWithZone 
#1 callAlloc(objc_class*, bool, bool) 
#2 _objc_rootAlloc
#3 +[NSObject alloc]
#4 callAlloc(objc_class*, bool, bool)
#5 objc_alloc
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;第二个，执行堆栈，这里就有点奇怪了，感觉编译器做了优化，如果 alloc 后面紧跟 init，那么直接就执行&lt;strong&gt;objc_alloc_init&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#0 _objc_rootAllocWithZone 
#1 callAlloc(objc_class*, bool, bool)
#2 objc_alloc_init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;第三个，执行堆栈，除了入口函数不一样，其他一模一样。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#0 _objc_rootAllocWithZone 
#1 callAlloc(objc_class*, bool, bool)
#2 objc_opt_new
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;总结：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;[alloc] init ] 和 new ，执行的结果是一样的 , 面试的时候可以理直气壮的说两者是“一模一样的”。&lt;/li&gt;
  &lt;li&gt;id a = [ClassA alloc]; [a init];    和  id aa = [[ClassA alloc] init]; 结果是一样的，但是堆栈有较大不同&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;nsobject-alloc-init-中-init-是做初始化的工作么&quot;&gt;[[NSObject alloc] init] 中 init 是做初始化的工作么？&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&quot;language-objective-c&quot;&gt;id
_objc_rootInit(id obj)
{
    // In practice, it will be hard to rely on this function.
    // Many classes do not properly chain -init calls.
    return obj;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;总结：init 没有做任何事情&lt;/p&gt;

&lt;h2 id=&quot;弱引用指针存储是用什么数据结构&quot;&gt;弱引用指针存储是用什么数据结构？&lt;/h2&gt;

&lt;p&gt;摘取了部分源码：&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;weak_entry_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;weak_entry_for_referent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;weak_table_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;weak_table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;objc_object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;referent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ASSERT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;referent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;weak_entry_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;weak_entries&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;weak_table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;weak_entries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;weak_entries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hash_pointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;referent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;weak_table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hash_displacement&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;weak_table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;weak_entries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;referent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;referent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;weak_table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bad_weak_table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;weak_table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;weak_entries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;hash_displacement&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hash_displacement&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;weak_table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_hash_displacement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;weak_table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;weak_entries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;答案：存储的方式是数组，但是用了Hash算法-开放定位法，所以存储的是Hash表&lt;/p&gt;

&lt;h2 id=&quot;分类重写主类的方法会把函数替换掉么&quot;&gt;分类重写主类的方法，会把函数替换掉么？&lt;/h2&gt;

&lt;p&gt;答：不会，函数替换只是表面现象；主要原因是函数寻找过程，优先寻找到分类的方法，主函数的方法其实还是存在的。&lt;/p&gt;

&lt;h2 id=&quot;classa-load-中执行-classb-alloc在classb-load-执行-classa-alloc-会怎么样&quot;&gt;ClassA +load 中执行 [ClassB alloc]，在ClassB +load 执行 [ClassA alloc] 会怎么样&lt;/h2&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Call +load methods (without runtimeLock - re-entrant)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;call_load_methods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;答：不会存在任何问题，1:load方法执行的时候，类的相关信息都已经准备完毕 2：执行load方法，没有添加 runtime lock，所以不会出现死锁现象&lt;/p&gt;

&lt;h2 id=&quot;uiview设置frame是直接设置calayer的frame么为什么calayer有隐式动画而uiview没有&quot;&gt;UIView设置Frame，是直接设置CALayer的Frame么，为什么CALayer有隐式动画而UIView没有&lt;/h2&gt;

&lt;p&gt;答：大部分设置UIView的属性，都会设置到CALayer上，而没有出现动画是因为CAAction，只有在UIView.animation block里面，uiview作为calayer的代理才会返回CAAction , 参考官方文档&lt;/p&gt;

&lt;h2 id=&quot;nsnumber-number1--1-和-nsnumber-number2--0xefffffffffffffff-有什么区别&quot;&gt;NSNumber *number1 = @(1); 和 NSNumber *number2 = @(0xEFFFFFFFFFFFFFFF); 有什么区别&lt;/h2&gt;

&lt;p&gt;总结：TaggedPointer的区别，理论上TaggedPointer可以存储7个字节+ 4bit = 60bit的大小数据&lt;/p&gt;

&lt;h2 id=&quot;arc下-什么情况下会执行对象的autorelease方法&quot;&gt;ARC下 什么情况下会执行对象的autoRelease方法&lt;/h2&gt;

&lt;p&gt;//todo&lt;/p&gt;

&lt;h2 id=&quot;swift中函数调用用什么方式&quot;&gt;Swift中函数调用用什么方式&lt;/h2&gt;

&lt;p&gt;答：静态派发和动态派发，动态派发又分 虚拟表派发 和 消息发送(@objc)&lt;/p&gt;

&lt;h2 id=&quot;swift中结构体或者基础数据中函数是调用是什么方式&quot;&gt;Swift中结构体或者基础数据中，函数是调用是什么方式&lt;/h2&gt;

&lt;p&gt;答：静态派发&lt;/p&gt;

&lt;h2 id=&quot;swift中扩展的函数是什么调用方式&quot;&gt;Swift中扩展的函数，是什么调用方式&lt;/h2&gt;

&lt;p&gt;答：静态派发&lt;/p&gt;

&lt;h2 id=&quot;swift中结构体中使用block会出现循环引用的情况么&quot;&gt;Swift中结构体中使用Block，会出现循环引用的情况么？&lt;/h2&gt;

&lt;p&gt;//todo&lt;/p&gt;

&lt;h2 id=&quot;swift中数组范型可以用协议么为什么&quot;&gt;Swift中数组范型可以用协议么？为什么&lt;/h2&gt;

&lt;p&gt;答：可以，如果数组范型是协议，那么数组存储的是一个特殊的数据结构，witnessTable，具体参考文档&lt;/p&gt;</content><author><name>Dcell</name><email>767536477@qq.com</email></author><summary type="html">源码都是基于objc-782，818版本，Swift5 ；老版本可能有不同的地方</summary></entry><entry><title type="html">iOS模拟B站智能防挡弹幕效果</title><link href="https://dcell.github.io/2021/01/30/iOS%E6%A8%A1%E6%8B%9FB%E7%AB%99%E6%99%BA%E8%83%BD%E9%98%B2%E6%8C%A1%E5%BC%B9%E5%B9%95%E6%95%88%E6%9E%9C.html" rel="alternate" type="text/html" title="iOS模拟B站智能防挡弹幕效果" /><published>2021-01-30T00:00:00+00:00</published><updated>2021-01-30T00:00:00+00:00</updated><id>https://dcell.github.io/2021/01/30/iOS%E6%A8%A1%E6%8B%9FB%E7%AB%99%E6%99%BA%E8%83%BD%E9%98%B2%E6%8C%A1%E5%BC%B9%E5%B9%95%E6%95%88%E6%9E%9C</id><content type="html" xml:base="https://dcell.github.io/2021/01/30/iOS%E6%A8%A1%E6%8B%9FB%E7%AB%99%E6%99%BA%E8%83%BD%E9%98%B2%E6%8C%A1%E5%BC%B9%E5%B9%95%E6%95%88%E6%9E%9C.html">&lt;p&gt;最近晚上一直在学习算法和数据结构，人菜瘾还大，一直被虐；特别是一些常用的算法写的想哭。&lt;/p&gt;

&lt;p&gt;刷累了就看看B站视频，发现B站有个防人物被弹幕遮挡的功能，感觉挺有意思的。&lt;/p&gt;

&lt;h2 id=&quot;原理&quot;&gt;原理&lt;/h2&gt;

&lt;p&gt;看到这个效果，八九不离十猜到是 &lt;strong&gt;mask&lt;/strong&gt; 作用。前端正常播放一个视频，然后在视频上发加一个 空心的 mask，这样弹幕就无法在空心的地方显示，就会有一个类似钻过去的效果。&lt;/p&gt;

&lt;p&gt;那么就是这个mask是怎么计算出来的呢？看了下前端的网络，B站应该通过一些算法，将视频中人物的描边在服务端计算好，然后前端不断请求修改这个 mask 的 path。&lt;/p&gt;

&lt;p&gt;优点：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;前后端通力配合，降低了前端开发难度&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;缺点：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;如果请求这个 mask，网络异常了或者延迟，那么可能会出现反面效果&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;思考下：能不能把 mask信息藏到视频帧的扩展信息中呢？🤔&lt;/p&gt;

&lt;h2 id=&quot;在ios中模拟下效果&quot;&gt;在iOS中模拟下效果&lt;/h2&gt;

&lt;p&gt;我在iOS使用系统的人脸追踪CIFaceFeature和CALayer，模拟了下B站的效果。只能防止脸被遮住… 而不是像B站一样人体描边。&lt;/p&gt;

&lt;p&gt;具体的实现不细写了，参考&lt;a href=&quot;https://github.com/Dcell/bilibili-mask&quot;&gt;demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://github.com/Dcell/bilibili-mask/blob/main/Jan-30-2021%2016-09-41.gif&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;</content><author><name>Dcell</name><email>767536477@qq.com</email></author><summary type="html">最近晚上一直在学习算法和数据结构，人菜瘾还大，一直被虐；特别是一些常用的算法写的想哭。</summary></entry><entry><title type="html">UIView 和 CALayer 的协作</title><link href="https://dcell.github.io/2021/01/11/UIView-%E5%92%8C-CALayer-%E7%9A%84%E5%8D%8F%E4%BD%9C.html" rel="alternate" type="text/html" title="UIView 和 CALayer 的协作" /><published>2021-01-11T00:00:00+00:00</published><updated>2021-01-11T00:00:00+00:00</updated><id>https://dcell.github.io/2021/01/11/UIView-%E5%92%8C-CALayer-%E7%9A%84%E5%8D%8F%E4%BD%9C</id><content type="html" xml:base="https://dcell.github.io/2021/01/11/UIView-%E5%92%8C-CALayer-%E7%9A%84%E5%8D%8F%E4%BD%9C.html">&lt;p&gt;在几年前，我浏览过由猫神翻译的一篇Objc中国的文章。讲的是UIView和CALayer的协作关系，讲的非常好；但是一段时间过去后，发现自己慢慢的又遗忘了，所以打算自己写一下，并且跑一些Demo来加深自己的理解。&lt;/p&gt;

&lt;h2 id=&quot;uiview-和-calayer-的关系&quot;&gt;UIView 和 CALayer 的关系&lt;/h2&gt;

&lt;p&gt;iOS面试特别喜欢问这个问题，一般回答都是UIView负责事件的交互，CALayer负责绘制；再深入一点，UIView是CALayer的代理，我们基于代理里面的函数 &lt;strong&gt;action&lt;/strong&gt; 展开讲讲。&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CALayer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;forKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CAAction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;CAAction在我印象中没有接触过，查看了下文档是用于响应 layer 属性的变化。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;An interface that allows objects to respond to actions triggered by a CALayer change.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;CALayer默认是有隐式动画，隐约的感觉到有一丝丝的关系🤔&lt;/p&gt;

&lt;h2 id=&quot;calayer-隐式动画-和-uiview-的关系&quot;&gt;CALayer 隐式动画 和 UIView 的关系&lt;/h2&gt;

&lt;p&gt;CALayer大部分属性都是有隐性动画的，这也是我认为 iOS 动画开发体验比 android 好。回到上面的议题，UIView 和 CALayer是一一对应的，你修改了UIView 的属性，其实是设置到CALayer上，但是我们发现一个问题：在UIView 上修改属性，并没有动画效果，但是在animation block中又有了动画效果。&lt;/p&gt;

&lt;p&gt;是不是CAAction搞的鬼，如果返回nil默认没有动画，如果有就执行相关的动画，让我们继续思考🤔&lt;/p&gt;

&lt;p&gt;继续观察上面提到的&lt;strong&gt;CAAction&lt;/strong&gt; ，在 CALayer  找到如下函数&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;forKey&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CAAction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;ol&gt;
    &lt;li&gt;If the layer has a delegate that implements the action(for:forKey:) method, the layer calls that method. The delegate must do one of the following:
      &lt;ol&gt;
        &lt;li&gt;Return the action object for the given key.&lt;/li&gt;
        &lt;li&gt;Return the NSNull object if it does not handle the action.&lt;/li&gt;
      &lt;/ol&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;The layer looks in the layer’s actions dictionary for a matching key/action pair.&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;The layer looks in the style dictionary for an actions dictionary for a matching key/action pair.&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;The layer calls the defaultAction(forKey:) class method to look for any class-defined actions.&lt;/li&gt;
  &lt;/ol&gt;

  &lt;p&gt;If any of the above steps returns an instance of NSNull, it is converted to nil before continuing.&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;大概就是通过：代理（UIView） –&amp;gt; layer actions –&amp;gt; style actions –&amp;gt; class-defined actions. 获取对应的action.&lt;/p&gt;

&lt;p&gt;如果任何一层返回NSNull，则不再向下寻找。&lt;/p&gt;

&lt;p&gt;验证下：&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;//自定义Layer&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;DLayer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CALayer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;layer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CALayer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;forKey&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CAAction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;layer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;forKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    		&lt;span class=&quot;c1&quot;&gt;//查看action&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//自定义view 并且自定Layer&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;DView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIView&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;layerClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AnyClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;DLayer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;//测试代码&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;DView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CGRect&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zero&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addSubview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CGRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;------&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;UIView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;animate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;withDuration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CGRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;------&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;其中1处，打印action 为 **&lt;null&gt;** ,  2处打印为 **_UIViewAdditiveAnimationAction** 应该是个实现了CAAction协议的内部类，验证了我们上面的猜想。&lt;/null&gt;&lt;/p&gt;

&lt;p&gt;继续打印 CALayer  添加动画的函数&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;anim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CAAnimation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;forKey&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;anim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;debugDescription&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;anim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;forKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;position&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;CABasicAnimation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x600001d9cf20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSPoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;additive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;delegate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UIViewAnimationState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x7f9122c084b0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fillMode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;both&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timingFunction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;easeInEaseOut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;duration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fromValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSPoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyPath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;bounds&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;CABasicAnimation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x600001d9d2c0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSPoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;additive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fromValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSPoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyPath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bounds&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;delegate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UIViewAnimationState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x7f9122c084b0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fillMode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;both&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timingFunction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;easeInEaseOut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;duration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;bounds&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;CABasicAnimation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x600001d9d400&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;toValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;additive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fromValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyPath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bounds&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;delegate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UIViewAnimationState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x7f9122c084b0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fillMode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;both&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timingFunction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;easeInEaseOut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;duration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;是不是感觉非常熟悉，这就是我们平常自定义动画的方式。我们在修改frame时候，默认系统添加了3个animation，分别是 position、bounds.origin、bounds.size。&lt;/p&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;

&lt;p&gt;通过上面的思考，我们对 Layer 和 View 关系有了进一步的了解，特别是 CA Animation这一块。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;UIView 持有 CALayer， 并且是 CALayer的代理&lt;/li&gt;
  &lt;li&gt;如果是通过UIView修改属性造成Layer属性变化时，Layer会通过4个方式来获取CAAction。&lt;/li&gt;
  &lt;li&gt;获取action后，添加对应CALayer CAAnimation&lt;/li&gt;
&lt;/ol&gt;</content><author><name>Dcell</name><email>767536477@qq.com</email></author><summary type="html">在几年前，我浏览过由猫神翻译的一篇Objc中国的文章。讲的是UIView和CALayer的协作关系，讲的非常好；但是一段时间过去后，发现自己慢慢的又遗忘了，所以打算自己写一下，并且跑一些Demo来加深自己的理解。</summary></entry><entry><title type="html">创建Xcode自定义模版</title><link href="https://dcell.github.io/2020/12/25/%E5%88%9B%E5%BB%BAxcode%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A8%A1%E7%89%88.html" rel="alternate" type="text/html" title="创建Xcode自定义模版" /><published>2020-12-25T00:00:00+00:00</published><updated>2020-12-25T00:00:00+00:00</updated><id>https://dcell.github.io/2020/12/25/%E5%88%9B%E5%BB%BAxcode%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A8%A1%E7%89%88</id><content type="html" xml:base="https://dcell.github.io/2020/12/25/%E5%88%9B%E5%BB%BAxcode%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A8%A1%E7%89%88.html">&lt;p&gt;最近有个需求要搞一个大基座，要求项目都按照某种方式生成，然后功能模版就和组件一样，一个个勾选就可以了。&lt;/p&gt;

&lt;h2 id=&quot;思考&quot;&gt;思考&lt;/h2&gt;

&lt;p&gt;对于模版的功能，我第一个念头就想到是元编程&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;按照需求生成一个元模版&lt;/li&gt;
  &lt;li&gt;通过自定义参数生成出基于元模版的一些功能模块&lt;/li&gt;
  &lt;li&gt;编写脚本，提供一套手脚架&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;xcode模版&quot;&gt;Xcode模版&lt;/h2&gt;

&lt;p&gt;平时我们创建iOS工程的时候，选择的一些模版，包括App、framework、App Extension其实都是一个模版，模版分2类：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Project Templates 工程模版&lt;/li&gt;
  &lt;li&gt;File Templates 文件模版&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;路径在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates&lt;/code&gt; (不同的Xcode版本可能有所不同)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.loli.net/2020/12/24/deVMpqGXtjIzBbc.png&quot; alt=&quot;截屏2020-12-24 下午2.43.07.png&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;自定义模版&quot;&gt;自定义模版&lt;/h2&gt;

&lt;p&gt;如果我们要创建一个自定义模版，不能在系统的模版上重新创建，需要在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/Library/Developer/Xcode/Templates&lt;/code&gt;去创建&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# ~/Library/Developer/Xcode/Templates/{模版类别}/{模版名称}.xctemplate&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; ~/Library/Developer/Xcode/Templates/ding_qili
&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/Project&lt;span class=&quot;se&quot;&gt;\ &lt;/span&gt;Templates/iOS/Application/App.xctemplate ~/Library/Developer/Xcode/Templates/ding_qili/ding_qili.xctemplate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后重启Xcode，新建一个工程，在选择中多了一个类别和一个模版，因为模版是完全拷贝过来的，创建的自定义项目和默认创建项目是一样的&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.loli.net/2020/12/24/5mRxtY6gbeLljaq.png&quot; alt=&quot;截屏2020-12-24 下午2.56.50.png&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;appxctemplate-模版分析&quot;&gt;App.xctemplate 模版分析&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;TemplateIcon.png：  模版显示的图片&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;https://i.loli.net/2020/12/24/SRTPo59hElQJU74.png&quot; alt=&quot;截屏2020-12-24 下午3.51.02.png&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;TemplateInfo.plist&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
  &lt;li&gt;Kind ：类别好像没发现什么特殊的作用&lt;/li&gt;
  &lt;li&gt;Identifier： 唯一标记，不要和系统的冲突，会出现覆盖现象&lt;/li&gt;
  &lt;li&gt;Ancestors：继承与哪个模版，可以多选&lt;/li&gt;
  &lt;li&gt;Concrete：是否展示出来，如果选择NO，那就变成匿名的模版，只能被别人继承使用&lt;/li&gt;
  &lt;li&gt;Description：描述&lt;/li&gt;
  &lt;li&gt;SortOrder：显示的排序，越小越显示在前面&lt;/li&gt;
  &lt;li&gt;NameOfInitialFileForEditor: 未知好像和SwiftUI相关&lt;/li&gt;
  &lt;li&gt;Options: 可选项&lt;/li&gt;
  &lt;li&gt;…其他&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;实战创建一个带podfile的模版&quot;&gt;实战–创建一个带Podfile的模版&lt;/h2&gt;

&lt;p&gt;因为模版没有相关的开发文档，只能通过网上的一些信息加上自己的摸索，接下来我通过修复官方的模版，创建一个自带Podfile的模版。&lt;/p&gt;

&lt;p&gt;我们先看下效果&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.loli.net/2020/12/25/6JduiG7PEgCqVvW.png&quot; alt=&quot;截屏2020-12-25 下午2.50.24.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.loli.net/2020/12/25/OQxcqyeHWR6prS9.png&quot; alt=&quot;截屏2020-12-25 下午3.33.47.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.loli.net/2020/12/25/KPcbnLdpzuytA4r.png&quot; alt=&quot;截屏2020-12-25 下午3.34.01.png&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Options添加一个新的选项&lt;/li&gt;
  &lt;li&gt;类型是Popup，支持2种包的集成方式，Pod和Swift Package，默认是Pod（Swift Package未实现）&lt;/li&gt;
  &lt;li&gt;在Units添加选择类型的实现，这边是Copy 模版下的Podfile文件 到 当前工程下，并且不选中任何的Target&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/Dcell/my-test/tree/master/ding_qili.xctemplate&quot;&gt;demo模版&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/Dcell/my-test/tree/master/ding_qili.xctemplate/Xcode 4 Template Documentation.pdf&quot;&gt;收集的开发文档&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;

&lt;p&gt;这边就不在发散开来讲了，模版的需求本来就不多而且没有官方的文档，如果要自定义一个，我建议参考官方的文档摸索着写写，可以立马上手。&lt;/p&gt;</content><author><name>Dcell</name><email>767536477@qq.com</email></author><summary type="html">最近有个需求要搞一个大基座，要求项目都按照某种方式生成，然后功能模版就和组件一样，一个个勾选就可以了。</summary></entry><entry><title type="html">Swift Memory Layout</title><link href="https://dcell.github.io/2020/12/21/Swift-Memory-Layout.html" rel="alternate" type="text/html" title="Swift Memory Layout" /><published>2020-12-21T00:00:00+00:00</published><updated>2020-12-21T00:00:00+00:00</updated><id>https://dcell.github.io/2020/12/21/Swift%20Memory%20Layout</id><content type="html" xml:base="https://dcell.github.io/2020/12/21/Swift-Memory-Layout.html">&lt;h2 id=&quot;swift-memory-layout&quot;&gt;Swift Memory Layout&lt;/h2&gt;

&lt;h4 id=&quot;unsafe-pointer&quot;&gt;Unsafe Pointer&lt;/h4&gt;

&lt;p&gt;在开始介绍&lt;strong&gt;Memory Layout&lt;/strong&gt;之前，先介绍下Swift指针。如图所示，除了黑色Unsafe和Pointer固定外，其他都是可选的，一共有8种不同的类型。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.loli.net/2020/12/16/8Sf9GysgvDE1bjT.png&quot; alt=&quot;截屏2020-12-16 下午2.10.23.png&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;memory--layout&quot;&gt;Memory  Layout&lt;/h4&gt;

&lt;p&gt;早在Swift3.0的时候就推出函数&lt;strong&gt;MemoryLayout&lt;/strong&gt;计算内存大小。其中分为如下3个参数&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//内存大小&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stride&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//分配的内存大小&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alignment&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//内存对齐大小&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;比如:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//4&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stride&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//4 &lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alignment&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;size&quot;&gt;size&lt;/h3&gt;

&lt;p&gt;**MemoryLayout&lt;T&gt;.size** 表示一个数据在内存中占用的大小，比如常见的Int32 4个字节，Int64 8个字节。&lt;/T&gt;&lt;/p&gt;

&lt;p&gt;除了计算基础类型外，也可以计算结构体和对象&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int64&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;sex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 9&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stride&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//16&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alignment&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//8&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;stride--alignment&quot;&gt;stride &amp;amp; alignment&lt;/h3&gt;

&lt;h4 id=&quot;什么是内存对齐&quot;&gt;什么是内存对齐&lt;/h4&gt;

&lt;p&gt;CPU 更高效地读写内存，采用了&lt;strong&gt;word size&lt;/strong&gt;读取方式，避免造成额外的开销；但是也要求类型的存储地址要与其内存对齐。&lt;/p&gt;

&lt;p&gt;我们修改下上面的demo如下：为什么修改了下属性的顺序，结构体的size变化了呢？&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;sex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int64&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 16&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stride&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 16&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alignment&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;首先我们分别获取属性&lt;strong&gt;Bool&lt;/strong&gt;和&lt;strong&gt;Int64&lt;/strong&gt;的内存模型&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//1&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stride&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//1 &lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alignment&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//1&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int64&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//8&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int64&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stride&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//8&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int64&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alignment&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;首先是Bool类型，内存对齐是1，当前内存对象是1的倍数不需要padding，所以第一个字节是赋值Bool&lt;/li&gt;
  &lt;li&gt;第2个属性是Int64，内存对齐是8，当前内存地址是1，不是8的倍数，需要padding7个字节&lt;/li&gt;
  &lt;li&gt;地址8-16是Int64赋值，所以MemoryLayout&lt;Person&gt;.size = 16&lt;/Person&gt;&lt;/li&gt;
  &lt;li&gt;MemoryLayout&lt;Person&gt;.alignment = Max( MemoryLayout&lt;Bool&gt;.alignment  ，MemoryLayout&lt;Bool&gt;.alignment ) = 8&lt;/Bool&gt;&lt;/Bool&gt;&lt;/Person&gt;&lt;/li&gt;
  &lt;li&gt;Person.alignment 满足8字节的内存对齐，不需要再padding，所以MemoryLayout&lt;Person&gt;.stride = 16&lt;/Person&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://i.loli.net/2020/12/23/efQR4EK8pP2xM3V.png&quot; alt=&quot;截屏2020-12-23 下午2.58.04.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;请画出：未交换属性之前的内存图&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.loli.net/2020/12/23/Lxr1caFZADozbsi.png&quot; alt=&quot;截屏2020-12-23 下午3.17.35.png&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;实战&quot;&gt;实战&lt;/h3&gt;

&lt;p&gt;在xcode中，去真正内存中看下是否满足我们的猜想&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;初始化一个结构体 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var person = Person(sex: true, age: 11)&lt;/code&gt; ，打印结构体地址 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;withUnsafeMutablePointer(to: &amp;amp;self)&lt;/code&gt; 或者通过如下方式&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;https://i.loli.net/2020/12/23/72VNIgqaxO3mikG.png&quot; alt=&quot;截屏2020-12-23 下午3.52.44.png&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;查看该地址在内存的信息&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;https://i.loli.net/2020/12/23/EAXPCBad5kvRF4i.png&quot; alt=&quot;截屏2020-12-23 下午3.55.51.png&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;第一个字节是01 表示 &lt;strong&gt;let sex:Bool&lt;/strong&gt; ，然后padding7个0x00 字节，最后0x000000000000000B 表示 11，就是我们设置的 &lt;strong&gt;let age:Int64&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;猜想&quot;&gt;猜想&lt;/h3&gt;

&lt;p&gt;从结构体的内存模型来看，好像无法区分是什么类型，如果我定义一个一摸一样的结构体，是不是可以偷天换日呢？&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;sex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int64&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Person2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;sex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int64&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;person&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;sex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;rawPointer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UnsafeMutableRawPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;allocate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;byteCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Person2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stride&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;alignment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Person2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alignment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;personPointer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;  &lt;span class=&quot;nf&quot;&gt;withUnsafeMutablePointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UnsafeMutableRawPointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bindMemory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;capacity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stride&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;rawPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;copyMemory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;personPointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;byteCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Person2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stride&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;person2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rawPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Person2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;XCTAssertTrue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;age&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;总结&quot;&gt;总结&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;MemoryLayout&lt;T&gt;.alignment = Max( MemoryLayout&lt;T.var1&gt;.alignment  ，MemoryLayout&lt;T.varn&gt;.alignment )&lt;/T.varn&gt;&lt;/T.var1&gt;&lt;/T&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;MemoryLayout&lt;T&gt;.size =  MemoryLayout&lt;T.var1&gt;.size + padding + ... + MemoryLayout&lt;T.varn&gt;.size&lt;/T.varn&gt;&lt;/T.var1&gt;&lt;/T&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;MemoryLayout&lt;T&gt;.stride = MemoryLayout&lt;T&gt;.size + padding&lt;/T&gt;&lt;/T&gt;&lt;/p&gt;

    &lt;p&gt;其中padding是通过内存对其来计算的&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;</content><author><name>Dcell</name><email>767536477@qq.com</email></author><summary type="html">Swift Memory Layout</summary></entry><entry><title type="html">小程序之美团外卖邀请链接</title><link href="https://dcell.github.io/2020/12/14/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E4%B9%8B%E7%BE%8E%E5%9B%A2%E5%A4%96%E5%8D%96%E9%82%80%E8%AF%B7%E9%93%BE%E6%8E%A5.html" rel="alternate" type="text/html" title="小程序之美团外卖邀请链接" /><published>2020-12-14T00:00:00+00:00</published><updated>2020-12-14T00:00:00+00:00</updated><id>https://dcell.github.io/2020/12/14/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E4%B9%8B%E7%BE%8E%E5%9B%A2%E5%A4%96%E5%8D%96%E9%82%80%E8%AF%B7%E9%93%BE%E6%8E%A5</id><content type="html" xml:base="https://dcell.github.io/2020/12/14/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E4%B9%8B%E7%BE%8E%E5%9B%A2%E5%A4%96%E5%8D%96%E9%82%80%E8%AF%B7%E9%93%BE%E6%8E%A5.html">&lt;p&gt;前不久无意中刷到一个同学说：自己做了个&lt;a href=&quot;https://github.com/Dcell/coupons&quot;&gt;小程序&lt;/a&gt;，里面可以分享各种外卖平台红包，然后用户下单后可以分红。这极大的引起了我的兴趣，赚不赚钱(🐶当然要)无所谓就是自己也想搞一个…&lt;/p&gt;

&lt;p&gt;大概看了下流程，首先你要在各个外卖平台联盟里注册推广，比如：饿了么，你需要在淘宝联盟注册；但是问题就出在我最常用的外卖平台美团，暂不支持个人账号申请推广，这让我很难受啊… 我得想个办法。&lt;/p&gt;

&lt;h2 id=&quot;第一步&quot;&gt;第一步&lt;/h2&gt;

&lt;p&gt;首先打开美团小程序，在【我的】【邀请有奖页面】&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.loli.net/2020/12/17/IVK3W7m28qSO6uF.png&quot; alt=&quot;IMG_2360.PNG&quot; style=&quot;zoom:30%;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.loli.net/2020/12/17/Wzgif1NVRFsTx3l.png&quot; alt=&quot;image.png&quot; style=&quot;zoom:33%;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;把邀请发送到自己的Mac 微信【文件传输组手】。&lt;/p&gt;

&lt;h2 id=&quot;第二步&quot;&gt;第二步&lt;/h2&gt;

&lt;p&gt;把Mac微信的聊天记录给导出来，我用的解密db文件的方式，因为微信采用的是&lt;strong&gt;SQLCipher&lt;/strong&gt;加密，这里就不展开讲了网上有很多的教程。等我们拿到db数据后，找到对应的聊天信息，基本可以通过肉眼就能确定，刚才分享过来的小程序链接；我截取了一段放出来看看。&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;weappinfo&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;username&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;![CDATA[gh_72a4eb2d4324@app]]&amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/username&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;appid&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;![CDATA[wx2c348cf579062e56]]&amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/appid&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;type&amp;gt;&lt;/span&gt;2&lt;span class=&quot;nt&quot;&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;340&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;weappiconurl&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;![CDATA[http://mmbiz.qpic.cn/mmbiz_png/IXJic6HOb8QT02PwzH5wCUicpuGmIagaUJLxzGRKtoY8PLQqBR1UDHwK5DpsyRJnQ0OHAFGaA8jweXGUh8RsJpCA/640?wx_fmt=png&amp;amp;wxfrom=200]]&amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/weappiconurl&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;pagepath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;![CDATA[outer_packages/r2xinvite/coupon/coupon.html?inviteCode=NnOIp-QOs8SiYF1dcSlL5r8phPrCf6qkH7evMyjIoup2NXxNCLYcBbd3bqpv2X2IOn5qfM4c28lrF49RL3kN7qKldLOV5bXOLrtjmuKQXOw_WKb38eCOvByJfrhKaFDEhpJ4NUwgFIKgxUTvIqoimgbBWQ6Ul_shsw1YN_XlAWM]]&amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/pagepath&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;shareId&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;![CDATA[0_wx2c348cf579062e56_06c58c1a452776ed22d64f6b62cbe83a_1608020809_0]]&amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/shareId&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;appservicetype&amp;gt;&lt;/span&gt;0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/appservicetype&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;tradingguaranteeflag&amp;gt;&lt;/span&gt;0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/tradingguaranteeflag&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;brandofficialflag&amp;gt;&lt;/span&gt;0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/brandofficialflag&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;subType&amp;gt;&lt;/span&gt;0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/subType&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;isprivatemessage&amp;gt;&lt;/span&gt;0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/isprivatemessage&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/weappinfo&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;其中appid是小程序id，这个我查看美团小程序id后已经确认&lt;/li&gt;
  &lt;li&gt;pagepath是小程序的路由地址，其中inviteCode应该是我的邀请码啦&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;第三步&quot;&gt;第三步&lt;/h2&gt;

&lt;p&gt;开发一个小程序，拿出CV大法直接在github上找个开源的，把美团小程序链接改成&lt;strong&gt;pagepath&lt;/strong&gt;（主要：去掉 .html），然后上架。&lt;/p&gt;

&lt;h2 id=&quot;最后&quot;&gt;最后&lt;/h2&gt;

&lt;p&gt;求求你们扫描二维码再下单吧～～～ 😭😭😭&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.loli.net/2020/12/17/XaZBfECLzHp62cm.jpg&quot; alt=&quot;IMG_2359.JPG&quot; style=&quot;zoom:50%;&quot; /&gt;&lt;/p&gt;</content><author><name>Dcell</name><email>767536477@qq.com</email></author><summary type="html">前不久无意中刷到一个同学说：自己做了个小程序，里面可以分享各种外卖平台红包，然后用户下单后可以分红。这极大的引起了我的兴趣，赚不赚钱(🐶当然要)无所谓就是自己也想搞一个…</summary></entry><entry><title type="html">shell命令中 单引号和双引号的区别</title><link href="https://dcell.github.io/2020/12/11/shell%E5%91%BD%E4%BB%A4%E4%B8%AD-%E5%8D%95%E5%BC%95%E5%8F%B7%E5%92%8C%E5%8F%8C%E5%BC%95%E5%8F%B7%E7%9A%84%E5%8C%BA%E5%88%AB.html" rel="alternate" type="text/html" title="shell命令中 单引号和双引号的区别" /><published>2020-12-11T00:00:00+00:00</published><updated>2020-12-11T00:00:00+00:00</updated><id>https://dcell.github.io/2020/12/11/shell%E5%91%BD%E4%BB%A4%E4%B8%AD-%E5%8D%95%E5%BC%95%E5%8F%B7%E5%92%8C%E5%8F%8C%E5%BC%95%E5%8F%B7%E7%9A%84%E5%8C%BA%E5%88%AB</id><content type="html" xml:base="https://dcell.github.io/2020/12/11/shell%E5%91%BD%E4%BB%A4%E4%B8%AD-%E5%8D%95%E5%BC%95%E5%8F%B7%E5%92%8C%E5%8F%8C%E5%BC%95%E5%8F%B7%E7%9A%84%E5%8C%BA%E5%88%AB.html">&lt;p&gt;​	在没有碰到shell命令单引号和双引号之前，我一直以为shell里面&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;''&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;&quot;&lt;/code&gt;是和JS里面一样没什么区别的；今天在做android重签名工具的时候，测试在修改应用名称带空格的情况下一直签名失败，如：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;测试 空格&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;问题1shell命令传入带空格的参数&quot;&gt;问题1：shell命令传入带空格的参数&lt;/h3&gt;

&lt;p&gt;因为shell命名对参数的解析是通过空格的方式解析的&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;如：1    2   测试 ，那么对应的参数获取就是：&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;测试&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果你参数带了空格&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;如：1    2   测试 空格，那么对应的参数获取就是：&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;测试&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
其中‘空格’是对应参数 &lt;span class=&quot;s1&quot;&gt;'$4'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;解决方法&quot;&gt;解决方法&lt;/h3&gt;

&lt;p&gt;我们可以采用读取全末尾参数方式&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;如 &lt;span class=&quot;nv&quot;&gt;APP_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;:3&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
表示读取第3个参数直到最后字符
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;问题2--sed--i-替换带空格的问题&quot;&gt;问题2:  sed -i 替换带空格的问题&lt;/h3&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;rp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;:1&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PWD&lt;/span&gt;/txt
&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'.bak'&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'s/**/'&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$rp&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'/g'&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;测试空格输入，报错了，当时花了很多时间去google这个问题，当时搜索的思路是 “sed -i 替换文字 参数带空格”，但没什么收获。&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sh shell.sh 测试 空格
error &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt;: 1: &lt;span class=&quot;s2&quot;&gt;&quot;s/**/测试&quot;&lt;/span&gt;: unterminated substitute &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;regular expression
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;后面换了个思路，尝试更改单引号为双引号。&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'$rp'&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;===&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'$rp'&lt;/span&gt; 如果是单引号，则不会执行取值，直接输出&lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;内所有内容
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$rp&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;===&amp;gt;&lt;/span&gt; 测试 空格 如果是双引号，输出值内容
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;但是！我发现&lt;/strong&gt;，如果用2个单引号包裹和一个双引号是一样的效果，没找到什么区别。&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$rp&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;===&amp;gt;&lt;/span&gt; 测试 空格
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;解决问题&quot;&gt;解决问题&lt;/h3&gt;

&lt;p&gt;修改shell如下，成功修改&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;rp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;:1&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PWD&lt;/span&gt;/txt
&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'.bak'&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;s/**/&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$rp&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/g&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#sed -i '.bak' 's/**/'$rp'/g' $file #为什么这样不行，讲道理 2个单引号和一个双引号效果一样，关于这个疑问，还没有解决&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;可以查看&lt;a href=&quot;https://github.com/Dcell/my-test/tree/master/test-quote&quot;&gt;Demo&lt;/a&gt;&lt;/p&gt;</content><author><name>Dcell</name><email>767536477@qq.com</email></author><summary type="html">​ 在没有碰到shell命令单引号和双引号之前，我一直以为shell里面'' 和 &quot;&quot;是和JS里面一样没什么区别的；今天在做android重签名工具的时候，测试在修改应用名称带空格的情况下一直签名失败，如：测试 空格</summary></entry><entry><title type="html">WWDC20 WKWebView新特性</title><link href="https://dcell.github.io/2020/12/09/WWDC20-WKWebView%E6%96%B0%E7%89%B9%E6%80%A7.html" rel="alternate" type="text/html" title="WWDC20 WKWebView新特性" /><published>2020-12-09T00:00:00+00:00</published><updated>2020-12-09T00:00:00+00:00</updated><id>https://dcell.github.io/2020/12/09/WWDC20-WKWebView%E6%96%B0%E7%89%B9%E6%80%A7</id><content type="html" xml:base="https://dcell.github.io/2020/12/09/WWDC20-WKWebView%E6%96%B0%E7%89%B9%E6%80%A7.html">&lt;p&gt;WWDC20中，有一个讲座是对于iOS14中WKWebView的新特性，其中一个特性还是比较有意思的，那就是&lt;strong&gt;WKScriptMessageHandlerWithReply&lt;/strong&gt; 。&lt;/p&gt;

&lt;h2 id=&quot;wkscriptmessagehandlerwithreply-和-wkscriptmessagehandler-的区别&quot;&gt;&lt;strong&gt;WKScriptMessageHandlerWithReply&lt;/strong&gt; 和 &lt;strong&gt;WKScriptMessageHandler&lt;/strong&gt; 的区别&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;WKScriptMessageHandlerWithReply&lt;/strong&gt;其实是对&lt;strong&gt;WKScriptMessageHandler&lt;/strong&gt;的扩展，在&lt;strong&gt;WKScriptMessageHandler&lt;/strong&gt;中JS调用&lt;strong&gt;PostMessage&lt;/strong&gt;，返回的是undefine;而&lt;strong&gt;WKScriptMessageHandlerWithReply&lt;/strong&gt;中调用&lt;strong&gt;PostMessage&lt;/strong&gt; 返回的Promise；在Native中，&lt;strong&gt;WKScriptMessageHandlerWithReply&lt;/strong&gt;多了一个&lt;strong&gt;replyHandler&lt;/strong&gt;回调调&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-objective-c&quot;&gt;- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message replyHandler:(void (^)(id _Nullable reply, NSString *_Nullable errorMessage))replyHandler API_AVAILABLE(macos(11.0), ios(14.0));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;当Native调用&lt;strong&gt;replyHandler&lt;/strong&gt;回调后，在JS端就执行了Promise的resolve函数，从而完成了这个JS调用Native的闭环。&lt;/p&gt;

&lt;p&gt;从这个现象来看，在iOS14的WKWebView中，系统支持了JS调用Native，并且返回Native执行结果。可以通过新的API来替换原先那些开源的JSBridge方案。现在越发手痒想自己搞一个JSBridge了。&lt;/p&gt;</content><author><name>Dcell</name><email>767536477@qq.com</email></author><summary type="html">WWDC20中，有一个讲座是对于iOS14中WKWebView的新特性，其中一个特性还是比较有意思的，那就是WKScriptMessageHandlerWithReply 。</summary></entry></feed>