<?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>Process on Chen</title><link>https://hechen.github.io/zh-cn/tags/process/</link><description>Recent content in Process on Chen</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Thu, 04 Jul 2019 01:19:10 +0800</lastBuildDate><atom:link href="https://hechen.github.io/zh-cn/tags/process/index.xml" rel="self" type="application/rss+xml"/><item><title>LetsMove 中的几个点</title><link>https://hechen.github.io/zh-cn/post/letsmove/</link><pubDate>Thu, 04 Jul 2019 01:19:10 +0800</pubDate><guid>https://hechen.github.io/zh-cn/post/letsmove/</guid><description>&lt;p&gt;当我们从网络上下载某个 mac app 之后，一般都会默认在 Downloads 目录里，但是某一些 App 是需要放置到 Application 目录才行，最常见的就是自更新功能是受到当前所处目录的限制的，这时候很多下载到本地的 .app 文件打开之后都会弹出提示框，让用户选择是否移动到 Applications 目录，LetsMove 就是大部分 mac app 参考或者集成的开源库，封装了这套逻辑。&lt;/p&gt;
&lt;p&gt;&lt;img alt="LetsMove" loading="lazy" src="https://i.imgur.com/99z1BQf.png"&gt;&lt;/p&gt;
&lt;p&gt;这个库已经好多年了，最近的一次 Commit 是 2017年，其中有几个点可以学习借鉴。&lt;/p&gt;
&lt;h3 id="大致思路"&gt;大致思路&lt;/h3&gt;
&lt;p&gt;虽然叫 Move，实际上是先行 Copy 一份当前的 App Bundle 到 Application 目录，然后杀掉自己并删除源目录的 App 文件。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Move to Applications Folder 确认之后&lt;/li&gt;
&lt;li&gt;复制当前 App 文件到 /Applications 目录中&lt;/li&gt;
&lt;li&gt;删除当前已经打开 App （Mac 上是可行的，不同于 Windows，不存在占用文件句柄的情况）&lt;/li&gt;
&lt;li&gt;执行子进程执行重启过程，具体后文会讲。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="权限获取提权"&gt;权限获取（提权）&lt;/h3&gt;
&lt;p&gt;检查文件路径是否可以写入的方法是 NSFileManager 的 isWritableFileAtPath ，如果返回 false，LetsMove 会主动进行权限获取。&lt;/p&gt;
&lt;p&gt;获取权限所使用的接口是 AuthorizationExecuteWithPrivileges，该接口实际在 OSX 10.7 Lion 之后就已经标记废弃了，但是一直到目前的 macOS 10.14 还一直可以使用。&lt;/p&gt;
&lt;p&gt;而作者为了避免苹果直接移除该代码导致提权接口不可用，使用了动态查找方法的形式，利用 dlsym 查找方法指针来获取，从而避免如果完全移除该方法导致功能不稳定的情况发生。&lt;/p&gt;</description></item><item><title>XPC Services</title><link>https://hechen.github.io/zh-cn/post/xpcservice/</link><pubDate>Thu, 04 Jul 2019 01:01:10 +0800</pubDate><guid>https://hechen.github.io/zh-cn/post/xpcservice/</guid><description>&lt;h2 id="关于-xpc"&gt;关于 XPC&lt;/h2&gt;
&lt;p&gt;因为最近在做的工作涉及到这一块，就大致的记录一下，针对 XPC 技术也做个总结。&lt;/p&gt;
&lt;p&gt;XPC 是 macOS 上一种进程间通信的技术统称，其使得我们可以将 Mac 应用的功能模块拆分成不同的多进程模式，关于进程之间的通信也被系统封装完整了，你只需要按照既定的模式做即可。其带来的最大的好处是&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;提高 App 自身的稳定性&lt;/li&gt;
&lt;li&gt;进行权限隔离&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;拿我目前在做的工作来讲，确实有针对以上这两点的需求。上层业务通过执行脚本命令获取执行结果，执行脚本命令使用的就是 NSTask，大概结构如下：&lt;/p&gt;
&lt;p&gt;&lt;img alt="shared-42f9e747-a47b-46fd-b445-0c7615b41020" loading="lazy" src="https://i.imgur.com/8glAV2u.png"&gt;&lt;/p&gt;
&lt;p&gt;对于执行 NSTask 的这层命令行执行模块来讲，拆分到独立的进程中使得安全性得以提高，即使 XPC 进程挂掉，一般情况下再次向 XPC 通信，系统会自行恢复启用新的 XPC 进程，而主应用无感知。&lt;/p&gt;
&lt;h2 id="xpc-架构"&gt;XPC 架构&lt;/h2&gt;
&lt;p&gt;在 Apple 官方文档中有如下图，很清楚的展示了整个 NSXPC 的架构。&lt;/p&gt;
&lt;p&gt;主应用和 XPC Service 之间是通过 NSXPCConnection 对象保持通信的，其通信接口由 Protocol 定义，然后暴露给外界一个符合了该协议的对象。&lt;/p&gt;
&lt;p&gt;所有的 XPC Service 本身是由系统级别程序 launchd 来管理和维护的。&lt;/p&gt;
&lt;p&gt;&lt;img alt="NSXPC_intro_2x-337fb6a3-4df5-47b3-a322-e52c48905753" loading="lazy" src="https://i.imgur.com/OdvfZk4.png"&gt;&lt;/p&gt;
&lt;h2 id="开发过程"&gt;开发过程&lt;/h2&gt;
&lt;p&gt;整体上主应用和 XPC 通信是标准的 Client-Server 模式。客户端询问 Server 端数据，Server 端应答即可。这之间的数据序列化完全交由系统管理。&lt;/p&gt;
&lt;h3 id="具体步骤"&gt;具体步骤&lt;/h3&gt;
&lt;h4 id="新建-xpc-service-的-target"&gt;新建 XPC Service 的 Target&lt;/h4&gt;
&lt;p&gt;&lt;img alt="Add New XPC Service Target" loading="lazy" src="https://i.imgur.com/BNFRaG7.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Input Target Info" loading="lazy" src="https://i.imgur.com/AyEq9Iv.png"&gt;&lt;/p&gt;</description></item><item><title>How to generate a NSViewController without a Nib?</title><link>https://hechen.github.io/zh-cn/post/create-nsviewcontroller-without-nib/</link><pubDate>Mon, 03 Jun 2019 20:55:54 +0800</pubDate><guid>https://hechen.github.io/zh-cn/post/create-nsviewcontroller-without-nib/</guid><description>&lt;p&gt;Recently, I created all the ViewControllers through the storyboard or the Nib (for views). Today, when I created a demo project without any Nib file, the ViewController did not show as I expected.&lt;/p&gt;
&lt;p&gt;WTF, Can you believe that? I cannot even create a ViewController now.&lt;/p&gt;
&lt;p&gt;There exist some differences between iOS and macOS.&lt;/p&gt;
&lt;h2 id="ios"&gt;iOS&lt;/h2&gt;
&lt;p&gt;In the previous development on the iOS platform, creating a ViewController — specifically a UIViewController instance — is dead simple, as below.&lt;/p&gt;</description></item><item><title>一道 Swift Quiz</title><link>https://hechen.github.io/zh-cn/post/a-swift-quiz/</link><pubDate>Tue, 14 May 2019 16:01:54 +0800</pubDate><guid>https://hechen.github.io/zh-cn/post/a-swift-quiz/</guid><description>&lt;p&gt;这两天在 &lt;a href="https://twitter.com/krzyzanowskim/status/1127875626579288064?s=12"&gt;Twitter&lt;/a&gt; 上看到一道题目，主要是考察 overload 和 type(of:) 的知识点，本文仅做记录，关于 MetaType 会单独写一篇文章来总结。&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;// Swift Quiz
&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;class View {}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;class A: View {}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;class B: View {}
&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;func add(_ v: View) { print(type(of: v)) }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;func add(_ v: A) { print(type(of: v)) }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;func add(_ v: B) { print(type(of: v)) }
&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;func build() -&amp;gt; View { return B() }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;add(build())
&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;// What is the output?
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &amp;#34;View&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &amp;#34;A&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &amp;#34;B&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;答案的分布说明，大家对这个输出结果还是有一定的疑惑🤔&lt;/p&gt;</description></item><item><title>关于 Library 和 Framework</title><link>https://hechen.github.io/zh-cn/post/library_framework/</link><pubDate>Fri, 26 Apr 2019 00:35:30 +0800</pubDate><guid>https://hechen.github.io/zh-cn/post/library_framework/</guid><description>&lt;p&gt;Library 和 Framework 的概念大家应该脑海里都有一些，本文旨在讲述下基本概念，没有对每个字节都了如指掌。关于基本的编译过程在 &lt;a href="https://hechen.github.io/post/xcode-build-system/"&gt;Build Process&lt;/a&gt; 一文中也大概讲述了一些。&lt;/p&gt;
&lt;p&gt;在链接 Library 以及 Framework 之前，我们需要先了解一下 Mach—O。&lt;/p&gt;
&lt;p&gt;提到 Mach-O ，需要明确下 object file（目标文件）的概念，其实质上是指那些由源代码编译之后生成的，还未进行链接的中间文件（比如 Linux 下的 .o 以及 Windows 下的 .obj），它和可执行文件的内容和结构很相似，所以一般上会跟可执行文件格式采用一样的格式存储。&lt;/p&gt;
&lt;p&gt;那在 Unix 系统上的 COFF 是当时发明的在 Unix 表示一个目标文件的存取格式，后来 Linux 基于 COFF 发明了 ELF，而 Windows 基于 COFF 发明了 PE 格式。广义上来说，目标文件与可执行文件几乎一样。在 Linux 下统称为 ELF 文件，Windows 上统称为 PE-COFF 文件，而在 iOS/macOS 上我们的目标文件就是 Mach-O 格式，其在目标文件的大体组成上和其他两种很相似。而 Mach-O 的全称就是 Mach Object 的缩写。&lt;/p&gt;
&lt;p&gt;&lt;img alt="目标文件" loading="lazy" src="https://i.imgur.com/CUrWruq.png"&gt;&lt;/p&gt;
&lt;p&gt;我们以 Linux 上 ELF 结构的一张图来大概说明一下情况，不同的源文件通过分类，将代码和数据，以及变量放入不同的职责段，代码段 _TEXT，数据段 _DATA 等。&lt;/p&gt;
&lt;p&gt;&lt;img alt="ELF" loading="lazy" src="https://i.imgur.com/ozMscrW.jpg"&gt;&lt;/p&gt;
&lt;p&gt;而 Mach-O 文件格式如下图（源自于 Apple 文档）, 和 ELF 格式类似，其也是将不同职责的代码和数据放置于不同的 Section 段，然后再集中成一个一个的 Segment，而 Load Commands 是用来控制每一个 Segment 是如何被加载的，数据是从哪里取的，等等。&lt;/p&gt;</description></item><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></channel></rss>