<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Shadowsocks on Chen</title><link>https://hechen.github.io/zh-cn/tags/shadowsocks/</link><description>Recent content in Shadowsocks on Chen</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Thu, 25 Apr 2019 11:30:30 +0800</lastBuildDate><atom:link href="https://hechen.github.io/zh-cn/tags/shadowsocks/index.xml" rel="self" type="application/rss+xml"/><item><title>Build Process</title><link>https://hechen.github.io/zh-cn/post/xcode-build-system/</link><pubDate>Thu, 25 Apr 2019 11:30:30 +0800</pubDate><guid>https://hechen.github.io/zh-cn/post/xcode-build-system/</guid><description>&lt;p&gt;编程语言的处理过程大致会有五个阶段，其每个阶段均有对应的工具：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;预处理器 Preprocessor&lt;/li&gt;
&lt;li&gt;编译器 Compiler&lt;/li&gt;
&lt;li&gt;汇编器 Assembler&lt;/li&gt;
&lt;li&gt;链接器 Linker&lt;/li&gt;
&lt;li&gt;加载器 Loader&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;我们以一个简单的源文件，来看看具体这几个步骤都做了哪些事情。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// main.m
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// MachO
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Created by chen he on 2019/4/22.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Copyright © 2019 chen he. All rights reserved.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#import &amp;lt;stdio.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello World.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="预处理器-preprocessor"&gt;预处理器 Preprocessor&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;符号化&lt;/li&gt;
&lt;li&gt;宏定义展开&lt;/li&gt;
&lt;li&gt;头文件引入展开&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在命令行执行如下命令，我们导出输出到本地文件&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;xcrun&lt;/span&gt; &lt;span class="n"&gt;clang&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt; &lt;span class="n"&gt;helloworld&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;preprocessed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;打开 preprocessed.txt 看输出如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;# 1 &amp;#34;helloworld.c&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;# 1 &amp;#34;&amp;lt;built-in&amp;gt;&amp;#34; 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;# 1 &amp;#34;&amp;lt;built-in&amp;gt;&amp;#34; 3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;# 361 &amp;#34;&amp;lt;built-in&amp;gt;&amp;#34; 3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;# 1 &amp;#34;&amp;lt;command line&amp;gt;&amp;#34; 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;# 1 &amp;#34;&amp;lt;built-in&amp;gt;&amp;#34; 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;# 1 &amp;#34;helloworld.c&amp;#34; 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;# 1 &amp;#34;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include&lt;/span&gt;&lt;span class="cpf"&gt;/stdio.h&amp;#34; 1 3 4&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;# 64 &amp;#34;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include&lt;/span&gt;&lt;span class="cpf"&gt;/stdio.h&amp;#34; 3 4&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;# 1 &amp;#34;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include&lt;/span&gt;&lt;span class="cpf"&gt;/_stdio.h&amp;#34; 1 3 4&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;# 68 &amp;#34;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include&lt;/span&gt;&lt;span class="cpf"&gt;/_stdio.h&amp;#34; 3 4&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;# 1 &amp;#34;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include&lt;/span&gt;&lt;span class="cpf"&gt;/sys/cdefs.h&amp;#34; 1 3 4&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 省略一万字
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;__vsnprintf_chk&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;restrict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;restrict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;va_list&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;# 412 &amp;#34;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include&lt;/span&gt;&lt;span class="cpf"&gt;/stdio.h&amp;#34; 2 3 4&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;# 2 &amp;#34;helloworld.c&amp;#34; 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello World!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;可以看到预编译处理之后的源文件，仅仅只有几行的源文件进行头文件展开之后能增加到几百行，而我们仅仅只引入了 &lt;code&gt;stdio.h&lt;/code&gt; 一个头文件。当然，你可以使用 Xcode 来执行预处理命令。&lt;/p&gt;</description></item><item><title>写个小工具 Swwwitch</title><link>https://hechen.github.io/zh-cn/post/swwwitch/</link><pubDate>Sat, 30 Mar 2019 11:29:54 +0800</pubDate><guid>https://hechen.github.io/zh-cn/post/swwwitch/</guid><description>&lt;p&gt;最近看到开发圈某热点，做了个小工具，总结下最近的几个 CocoaApp 上的功能，仅做练手。现在只包含了两个开关：切换系统主题和隐藏桌面 icon 的功能。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Swwwitch-c500" loading="lazy" src="https://i.imgur.com/U9RTmVU.png"&gt;&lt;/p&gt;
&lt;h2 id="功能点"&gt;功能点&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;切换系统主题&lt;/li&gt;
&lt;li&gt;显式或者印象桌面图标&lt;/li&gt;
&lt;li&gt;完全的 Menu Only 应用&lt;/li&gt;
&lt;li&gt;开机自启动&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;关于第三点的实现在&lt;a href="https://hechen.github.io/post/dockless-cocoaapps/"&gt;另外一篇文章&lt;/a&gt;有讲过，第四点的实现在 &lt;a href="https://hechen.github.io/post/autostartwhenlogin/"&gt;这一篇&lt;/a&gt; 中有讲。&lt;/p&gt;
&lt;h3 id="系统主题切换"&gt;系统主题切换&lt;/h3&gt;
&lt;p&gt;关于系统主题切换主要是基于 AppleScript 所写，&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-applescript" data-lang="applescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;tell&lt;/span&gt; &lt;span class="nb"&gt;application&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;System Events&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;tell&lt;/span&gt; &lt;span class="nv"&gt;appearance&lt;/span&gt; &lt;span class="nv"&gt;preferences&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;dark&lt;/span&gt; &lt;span class="nv"&gt;mode&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nv"&gt;dark&lt;/span&gt; &lt;span class="nv"&gt;mode&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;tell&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;tell&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;你完全可以自行执行这段 Apple Script 来切换主题，你可以点击下面链接尝试。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://hechen.github.io/zh-cn/post/swwwitch/#ZgotmplZ"&gt;Click Here to run&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="显式隐藏桌面图标"&gt;显式/隐藏桌面图标&lt;/h3&gt;
&lt;p&gt;关于隐藏桌面图标，实际上是执行系统的 Command 来实现的，Cocoa 应用可以显式使用 Process（也就是 NSTask）来执行任务，我们也是通过 NSTask 执行了一段如下的命令行达到的目的：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;defaults write com.apple.finder CreateDesktop &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;killall Finder
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;你可以自行点击以下链接尝试。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://hechen.github.io/zh-cn/post/swwwitch/#ZgotmplZ"&gt;Click here to hide Desktop Icons&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://hechen.github.io/zh-cn/post/swwwitch/#ZgotmplZ"&gt;Click here to show Desktop Icons&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;感兴趣可以去看下代码，领会意思即可。
&lt;a href="https://github.com/hechen/Swwwitch/releases"&gt;Releases&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="todo"&gt;TODO&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Add more switch&lt;/li&gt;
&lt;li&gt;Add User-Customized switch setting&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="links"&gt;Links&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://ss64.com/osx/"&gt;Checkout all command lines macOS Support&lt;/a&gt;&lt;/p&gt;</description></item><item><title>关于 Mac 应用的自启动是如何做到的</title><link>https://hechen.github.io/zh-cn/post/autostartwhenlogin/</link><pubDate>Mon, 18 Mar 2019 17:29:54 +0800</pubDate><guid>https://hechen.github.io/zh-cn/post/autostartwhenlogin/</guid><description>&lt;p&gt;开机自启动是 Cocoa 应用最常见的一种功能，尤其是针对需要常驻 Menu 的服务来说更是如此，今天我们对开机启动项的功能加入做个梳理。&lt;/p&gt;
&lt;p&gt;在 &lt;a href="https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLoginItems.html#//apple_ref/doc/uid/10000172i-SW5-SW1"&gt;Daemons and Services Programming Guide&lt;/a&gt; 中我们能找到关于自启动项的开发说明：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Applications can contain a helper application as a full application bundle, stored inside the main application bundle in the Contents/Library/LoginItems directory. Set either the LSUIElement or LSBackgroundOnly key in the Info.plist file of the helper application’s bundle.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Use the SMLoginItemSetEnabled function (available in OS X v10.6.6 and later) to enable a helper application. It takes two arguments, a CFStringRef containing the bundle identifier of the helper application, and a Boolean specifying the desired state. Pass true to start the helper application immediately and indicate that it should be started every time the user logs in. Pass false to terminate the helper application and indicate that it should no longer be launched when the user logs in. This function returns true if the requested change has taken effect; otherwise, it returns false. This function can be used to manage any number of helper applications.&lt;/p&gt;</description></item><item><title>Mac 平台上那些 Dockless 的 App 都是如何实现的？</title><link>https://hechen.github.io/zh-cn/post/dockless-cocoaapps/</link><pubDate>Wed, 13 Mar 2019 17:29:54 +0800</pubDate><guid>https://hechen.github.io/zh-cn/post/dockless-cocoaapps/</guid><description>&lt;p&gt;Menu Only 算是 Cocoa App 中最常见的一项，它使得 App 不占用你的 Dock 栏，在多 workspace 的时候也不影响正常使用，随时都可以在屏幕的菜单栏中执行快捷操作。尤其是针对一些需要便捷性要求比较高的应用来讲，Menu bar 的功能必不可少。本文就简单介绍一下关于 Menu App 中关键的几个开发步骤。&lt;/p&gt;
&lt;h1 id="介绍"&gt;介绍&lt;/h1&gt;
&lt;p&gt;以 &lt;a href="https://www.shimovpn.com/"&gt;Shimo&lt;/a&gt; 这个 App 举例，&lt;/p&gt;
&lt;p&gt;&lt;img alt="Shimo" loading="lazy" src="https://i.imgur.com/vT7EEVK.png"&gt;&lt;/p&gt;
&lt;p&gt;在其设置选项卡中能看到 Show Shimo in 的选项菜单，其中有三项：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Menubar only&lt;/li&gt;
&lt;li&gt;Dock only&lt;/li&gt;
&lt;li&gt;Menubar &amp;amp; Dock&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt="Shimo Menu" loading="lazy" src="https://i.imgur.com/WywIVkV.png"&gt;&lt;/p&gt;
&lt;p&gt;这也是常见的 Cocoa 应用的模式支持，很多常见的 App 都支持，比如 DayOne，Dash，Todoist 等。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Dash" loading="lazy" src="https://i.imgur.com/ioUvpNw.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Todoist" loading="lazy" src="https://i.imgur.com/ORYAEcZ.png"&gt;&lt;/p&gt;
&lt;p&gt;其实核心功能有两点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;可以显示或者隐藏 Dock 图标；&lt;/li&gt;
&lt;li&gt;可以显示或者隐藏 Menu 菜单这两者的组合。&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id="核心步骤"&gt;核心步骤&lt;/h1&gt;
&lt;h2 id="dock"&gt;Dock&lt;/h2&gt;
&lt;p&gt;普通的 Cocoa Application 创建之后，默认都是 Dock 上展示的，如果想隐藏 Dock 图标，首先它需要有这个能力，这个能力是通过 info.plist 文件中的 Key 来指定的，这个 Key 就是 &lt;code&gt;LSUIElement&lt;/code&gt;，我们将其值设置为 true&lt;/p&gt;</description></item><item><title>在英文语言系统的 Safari 中使用印象笔记</title><link>https://hechen.github.io/zh-cn/post/using-yinxiangbiji-system-english/</link><pubDate>Wed, 13 Mar 2019 00:30:49 +0800</pubDate><guid>https://hechen.github.io/zh-cn/post/using-yinxiangbiji-system-english/</guid><description>&lt;blockquote&gt;
&lt;p&gt;因为 Evernote 在国内使用了不同的账户体系，去年团队也彻底独立出来，但是 Safari 的剪藏插件是同一个，&lt;a href="https://safari-extensions.apple.com/details/?id=com.evernote.safari.clipper-Q79WDW8YH9"&gt;下载地址&lt;/a&gt;，但是当你系统是英文系统的时候，使用 Safari 剪藏有点尴尬，就是根本找不到印象笔记的登录入口，该文做个记录。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;首先 Safari 默认是没有 Develop 菜单的，因此先开启 Develop 模式，进入 Safari 的选项设置面板中，最后 Advanced 选项卡最下方如图勾选。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Capto_Capture 2019-03-13_12-39-08_A" loading="lazy" src="https://i.imgur.com/J5HvXn1.png"&gt;&lt;/p&gt;
&lt;p&gt;此时，在 Safari 的顶部菜单中会多出 Develop 菜单入口，如下图所示：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Capto_Capture 2019-03-13_12-40-57_A" loading="lazy" src="https://i.imgur.com/OxPf4Ji.png"&gt;&lt;/p&gt;
&lt;p&gt;安装印象笔记的插件之后，点击 Safari 上的印象笔记剪藏按钮，你会发现直接带到 Evernote 的登录界面，没有渠道让我登录印象笔记，即使你 Safari 已经登录了印象笔记，登录的 Session 和 Cookie 信息并没有任何用。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Capto_Capture 2019-03-13_12-50-48_A" loading="lazy" src="https://i.imgur.com/gVTWCOc.png"&gt;&lt;/p&gt;
&lt;p&gt;这时，你就登录国际版 Evernote 账户，如果你没有，那就注册一个。总之，你需要先登录进去，因为我们必须让剪藏菜单展示出来才行。&lt;/p&gt;
&lt;p&gt;登录 Evernote 之后，打开一个页面进行剪裁，之后如图，我们终于看到了剪藏菜单：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Capto_Capture 2019-03-13_12-52-36_A" loading="lazy" src="https://i.imgur.com/VtvROcP.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Capto_Capture 2019-03-13_12-53-45_A" loading="lazy" src="https://i.imgur.com/LsitsxG.png"&gt;&lt;/p&gt;
&lt;p&gt;点击下方的 Options，打开设置选项&lt;/p&gt;
&lt;p&gt;&lt;img alt="Capto_Capture 2019-03-13_12-56-16_A" loading="lazy" src="https://i.imgur.com/KpQefZc.png"&gt;&lt;/p&gt;
&lt;p&gt;此时，因为刚才开启了 Develop 菜单选项卡，此时右键点击该窗口，&lt;/p&gt;
&lt;p&gt;&lt;img alt="Capto_Capture 2019-03-13_12-58-02_A" loading="lazy" src="https://i.imgur.com/ylecnyS.png"&gt;&lt;/p&gt;
&lt;p&gt;点击 Inspect Element 打开页面元素查看器，在下方元素展示区为焦点的前提下，Command +F 搜索 &lt;strong&gt;DeveloperContainer&lt;/strong&gt; 关键字。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Capto_Capture 2019-03-13_12-59-28_A" loading="lazy" src="https://i.imgur.com/0DSMO39.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Capto_Capture 2019-03-13_01-02-18_A" loading="lazy" src="https://i.imgur.com/t3uqMa4.png"&gt;&lt;/p&gt;</description></item><item><title>为 NSView 增加 backgroundColor</title><link>https://hechen.github.io/post/nsview-backgroundcolor/</link><pubDate>Mon, 11 Mar 2019 15:19:49 +0800</pubDate><guid>https://hechen.github.io/post/nsview-backgroundcolor/</guid><description>&lt;p&gt;NSView 作为 Cocoa 中最基本的构成元素，是构成整个 Mac App 视图体系的基础，和 UIView 在 iOS 世界中的位置一样重要，可是在 UIView 里司空见惯的背景色设置，在 NSView 中却不见身影。&lt;/p&gt;
&lt;p&gt;在 iOS 中，设置 UIView 的背景色很简单。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="nc"&gt;UIKit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;frame&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CGRect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zero&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CGSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;view&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UIView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;backgroundColor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;而在 macOS 上，使用 NSView 背景色需要如下设置：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="nc"&gt;Cocoa&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;frame&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CGRect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zero&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CGSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;view&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NSView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wantsLayer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layer&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;backgroundColor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NSColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cgColor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;UIView 自身有一个 backgroundColor 的属性，而在 NSView 中是没有的，你需要做的是设置 View 所包含的 layer 的背景色。而且 layer 是 Optional 的，也就意味着 NSView 默认是不包含 layer 的，所以你还需要设置 wantsLayer 为 true 让 NSView 创建 layer 出来。&lt;/p&gt;
&lt;p&gt;在 Apple 的&lt;a href="https://developer.apple.com/documentation/appkit/nsview/1483695-wantslayer"&gt;官方文档&lt;/a&gt; 有针对 wantsLayer 的一些说明&lt;/p&gt;</description></item><item><title>RxSwift 中的几种 Subject</title><link>https://hechen.github.io/zh-cn/post/rxswift-subjects/</link><pubDate>Tue, 26 Feb 2019 10:24:38 +0800</pubDate><guid>https://hechen.github.io/zh-cn/post/rxswift-subjects/</guid><description>&lt;blockquote&gt;
&lt;p&gt;文中所用插图均出自书籍 《RxSwift - Reactive Programming with Swift》&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Subject 在 Rx 的世界里是这么一种存在，其既可以作为观测者，也可以作为被观测者。自然而然想到的是 Subject 本身就可以作为一种过渡桥接信号的手段，它订阅某个信号，一旦信号收到序列，转头它就又把信号散发给自己的观测者了。&lt;/p&gt;
&lt;p&gt;在 RxSwift 的世界里涉及几种 Subject，这里先行做个记录：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;PublishSubject&lt;/li&gt;
&lt;li&gt;BehaviorSubject&lt;/li&gt;
&lt;li&gt;ReplaySubject&lt;/li&gt;
&lt;li&gt;Variable （预计在 5.0 废弃）&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="publishsubject"&gt;PublishSubject&lt;/h2&gt;
&lt;p&gt;PublishSubject 只给订阅者发送新元素，也就是订阅者只能接受到订阅之后发出的信号。一图胜千言，看👇&lt;/p&gt;
&lt;p&gt;&lt;img alt="publishSubject" loading="lazy" src="https://i.imgur.com/Cw4FjCT.png"&gt;&lt;/p&gt;
&lt;p&gt;其中第一排是某个作为 Observable 角色的 Subject，自左至右为严格时间线， 2 和 3 排均为订阅了该 Subject 的观测者，向上的虚线表明订阅的时机，可以看到观测者只能接收到订阅之后由 Subject 新发射出的信号。&lt;/p&gt;
&lt;h2 id="behaviorsubject"&gt;BehaviorSubject&lt;/h2&gt;
&lt;p&gt;BehaviorSubject 会在订阅者订阅之后发送最新的一个信号元素，自然需要你在初始化该对象的时候给其设定初始化值（否则对于第一次订阅的观测者来说，哪来的最新发射的元素呢？）。如果初始化的时候无法提供默认值，那可能你就需要用到上面的 PublishSubject 了。其中常用的 Variable 和 BehaviorRelay 都是对其的封装。&lt;/p&gt;
&lt;p&gt;&lt;img alt="BehaviorSubject" loading="lazy" src="https://i.imgur.com/ei6pCwT.png"&gt;&lt;/p&gt;
&lt;p&gt;从图中可以看到和上方 Publish 区别的是其在观测者订阅之后会收到最新的最后一个信号。&lt;/p&gt;
&lt;h2 id="replaysubject"&gt;ReplaySubject&lt;/h2&gt;
&lt;p&gt;顾名思义，ReplaySubject 会重新发射在订阅者订阅之间发出的信号，具体发多少是由 bufferSize 决定的，其指定需要 cache 多少个信号，如下图中所示，Buffer Size 为 2，因此当第二个订阅者订阅 Subject 之后，其会收到最新的 1 和 2 两个信号。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;/// 指定发射多少最新信号&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;subject&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ReplaySubject&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bufferSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img alt="replaySubject" loading="lazy" src="https://i.imgur.com/uuHAQ9c.png"&gt;&lt;/p&gt;</description></item><item><title>Apple Event Sandboxing</title><link>https://hechen.github.io/zh-cn/post/appleevents-usage-description/</link><pubDate>Thu, 21 Feb 2019 23:25:38 +0800</pubDate><guid>https://hechen.github.io/zh-cn/post/appleevents-usage-description/</guid><description>&lt;h2 id="问题背景"&gt;问题背景&lt;/h2&gt;
&lt;p&gt;最近在修改某个 &lt;a href="https://github.com/hechen/vibe"&gt;Mac 应用&lt;/a&gt;，其原理就是通过执行一段 AppleScript 获取 OmniFocus 的信息，然后进行可视化展示，但是总取不到数据。&lt;/p&gt;
&lt;h2 id="原因"&gt;原因&lt;/h2&gt;
&lt;p&gt;关键数据获取阶段执行的 AppleScript 的时候总是取不到数据。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-applescript" data-lang="applescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;theProgressDetail&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;tell&lt;/span&gt; &lt;span class="nb"&gt;application&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;OmniFocus&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;tell&lt;/span&gt; &lt;span class="nb"&gt;front&lt;/span&gt; &lt;span class="na"&gt;document&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;theModifiedProjects&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;every&lt;/span&gt; &lt;span class="nv"&gt;flattened&lt;/span&gt; &lt;span class="nv"&gt;project&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;repeat&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="nv"&gt;length&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nv"&gt;theModifiedProjects&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;theCompletedTasks&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;every&lt;/span&gt; &lt;span class="nv"&gt;flattened&lt;/span&gt; &lt;span class="nv"&gt;task&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;item&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nv"&gt;theModifiedProjects&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;where&lt;/span&gt; &lt;span class="k"&gt;its&lt;/span&gt; &lt;span class="nv"&gt;number&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nv"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;theCompletedTasks&lt;/span&gt; &lt;span class="ow"&gt;is not&lt;/span&gt; &lt;span class="ow"&gt;equal to&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;repeat&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="nv"&gt;length&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nv"&gt;theCompletedTasks&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;theProgressDetail&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="nv"&gt;theProgressDetail&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;completion&lt;/span&gt; &lt;span class="nv"&gt;date&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;item&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nv"&gt;theCompletedTasks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="no"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;repeat&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;repeat&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;theInboxCompletedTasks&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;every&lt;/span&gt; &lt;span class="nv"&gt;inbox&lt;/span&gt; &lt;span class="nv"&gt;task&lt;/span&gt; &lt;span class="nb"&gt;where&lt;/span&gt; &lt;span class="k"&gt;its&lt;/span&gt; &lt;span class="nv"&gt;number&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nv"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;repeat&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nv"&gt;d&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="nv"&gt;length&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nv"&gt;theInboxCompletedTasks&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;theProgressDetail&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="nv"&gt;theProgressDetail&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;completion&lt;/span&gt; &lt;span class="nv"&gt;date&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;item&lt;/span&gt; &lt;span class="nv"&gt;d&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nv"&gt;theInboxCompletedTasks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="no"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;repeat&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;tell&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="k"&gt;tell&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;display dialog&lt;/span&gt; &lt;span class="nv"&gt;theProgressDetail&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="no"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;theProgressDetail&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在 Cocoa 中是通过执行如下代码执行：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;myAppleScript&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;I am a piece of applescript&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;scriptObject&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NSAppleScript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;myAppleScript&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;NSDictionary&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;output&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scriptObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;executeAndReturnError&lt;/span&gt;&lt;span class="p"&gt;(&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;进行 Debug 启动 App 或者 Archive 安装包执行可执行文件，均无法正常获取执行结果，直接报错。 具体错误原因：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;#34;NSAppleScriptErrorMessage&amp;#34; : &amp;#34;Not authorized to send Apple events to OmniFocus.&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;很显然，没有权限执行该脚本来发送 Apple Event 给 OmniFocus 从而执行对应操作。&lt;/p&gt;</description></item><item><title>关于一次 SS 流量丢失的过程记录</title><link>https://hechen.github.io/zh-cn/post/%E5%85%B3%E4%BA%8E%E4%B8%80%E6%AC%A1-ss-%E6%B5%81%E9%87%8F%E4%B8%A2%E5%A4%B1%E7%9A%84%E8%BF%87%E7%A8%8B%E8%AE%B0%E5%BD%95/</link><pubDate>Mon, 28 Jan 2019 17:51:35 +0000</pubDate><guid>https://hechen.github.io/zh-cn/post/%E5%85%B3%E4%BA%8E%E4%B8%80%E6%AC%A1-ss-%E6%B5%81%E9%87%8F%E4%B8%A2%E5%A4%B1%E7%9A%84%E8%BF%87%E7%A8%8B%E8%AE%B0%E5%BD%95/</guid><description>&lt;h2 id="2019-01-29-更新"&gt;2019-01-29 更新&lt;/h2&gt;
&lt;p&gt;早上一到办公室连接上公司网络，网速直接就飚到了 600KB/s，果不其然，还是 &lt;code&gt;com.apple.Safari.SafeBrowsing.Service&lt;/code&gt; 这个服务进程。这就尴尬了，看来并不是说你不用 Safari 就不会触发。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Surge Dashboard" loading="lazy" src="https://i.imgur.com/yifgIEZ.png"&gt;&lt;/p&gt;
&lt;p&gt;直接把 Surge 规则中的 Rule 由 Direct 改成了 Reject。&lt;/p&gt;
&lt;h2 id="问题追踪"&gt;问题追踪&lt;/h2&gt;
&lt;p&gt;在 2018 年 12 月底的时候，偶然间登录 AgentNEO 查看刚买的流量使用情况。但是发现，刚在前几天购买的 SS 流量在短短的 4 天之内就耗了将近 95GB，就在 1 月 1 日元旦当天就耗了接近 75GB，要知道，我平时的月均流量也就维持在 10 GB 不到，毕竟平时在公司办公，业余时间 Youtube 也看的相对少。&lt;/p&gt;
&lt;p&gt;&lt;img alt="AgentNEO 流量面板" loading="lazy" src="https://i.imgur.com/9tRs9vh.png"&gt;&lt;/p&gt;
&lt;p&gt;在最初看到这个统计数据之后，我一度怀疑是他们网站的流量统计有问题。&lt;/p&gt;
&lt;p&gt;后续几天，我实际上对流量耗损比较关注，有一天注意到，Surge 的流量监控速率一直持续不断的显示达五六百 KB/s 的下载流量，但是我知道自己当时并没有下载任何东西。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Surge Menu Bar" loading="lazy" src="https://i.imgur.com/nWz8JAt.png"&gt;&lt;/p&gt;
&lt;p&gt;打开 Surge Dashboard，看到如下的情形：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Surge Dashboard" loading="lazy" src="https://i.imgur.com/9kVX27V.png"&gt;&lt;/p&gt;
&lt;p&gt;可以看到当时在持续不断的进行下载动作的进程名称是 &lt;code&gt;com.apple.Safari.SafeBrowsing.Service&lt;/code&gt;，看请求地址是 safebrowsing.googleapis.com。&lt;/p&gt;
&lt;p&gt;从进程名字来看应该是 Safari 和安全流量相关的服务，通过 Snitch 的数据库查到对其的说明：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Safari has built-in support for Google’s Safe Browsing service to identify fraudulent and unsafe websites. Right before Safari navigates to a certain website, the website gets checked for possible security concerns using Google’s Safe Browsing online database. Accessing the online database requires connections to Google servers.&lt;/p&gt;</description></item></channel></rss>