2015年,我是一個普通的全棧Web開發。
我有一臺Mac,玩了一段時間以后,我就被它充滿活力的應用生態系統所吸引了。
有一天,我看到了一個叫做IA Writer的Markdown編輯器,又簡單又優雅。
我也決定自己做一個。
懷著滿腔熱情,我開始學習如何制作Mac原生文本編輯器。
XCode,AppKit,Objective-C,所有這一切對我來說都是全新的。
我打算把我的文本編輯器叫做Paper,它就像一張紙,非常簡潔。
重要的決定
我的第一個決定就是:這個應用一定要是原生的!
我是Web開發,完全可以復用Electron這樣的框架,但是我不想用它。
我寧愿學習全新的技能,為用戶提供最好的體驗。
這個體驗就是:軟件很小,下載速度超快,使用起來是原生的UI。
這樣才能與其他非常精美的編輯器競爭。
我不想縮短開發時間,因為我擁有世界上所有的時間。
第二,我選擇了Objective-C。
2015年,Swift剛剛出現,我做了一個實驗,用Objective-C和Swift分別在XCode中寫了一個空的項目,然后檢查各自生成的.app包。
我驚訝地發現,Swift中嵌入了完整的運行時,.app包是5M,而Objective-C只有幾十K。
(如果你現在進行這個實驗,差異不會那么大)
我想要最好的,寧愿付出更難學習和語言過時的代價,以便得到更精簡的軟件包。
第三,我不想依賴第三方。
從自己不熟悉的生態系統中,選擇依賴項,這實在是不容易。
恐怕大家都有這樣痛苦的經驗:在編寫一行代碼之前,添加一大堆不知道的第三方包和庫......
我要構建一切內容,這樣我可以按需定制,獲得一點競爭優勢。
比如Markdown的解析引擎,因為Paper不像那些傳統的編輯器,并不支持全部的Markdown語言,所以在解析引擎中我只需要寫我需要的代碼,并且我可以做大量優化。
Paper 僅使用 AppKit 和 UIKit 中的本機 UI 元素,因為它們的維護開銷最低:由Apple自動更新,向后兼容,保證在每個設備上工作。
我的愿景
非常簡單,超越IA Writer,更加精簡,更加優雅,讓用戶專注于寫作這件事。
為了實現目標,我盡最大可能減少干擾。
應用程序窗口內沒有一個按鈕。
沒有標準的“首選項”窗口,將所有內容分散到菜單項和菜單小部件中。
將滾動條縮小為2個像素的線。
上下滾動時可以隱藏標題欄,使得編輯器周圍的空白可以拖動
不知道是否有人注意到了我這些努力,很可能是有的,因為有人寫了一個非常簡潔的評論,我至今依然將其作為宣傳語:
這是一個超級干凈的寫作空間,有大量可配置的東西,當你不需要時,它們可以隱藏在實現之外。
根據我的觀察,奉行極簡主義的寫作軟件通常會走向兩條路:
(1)變得流行,為了滿足大量用戶的新需求,偏離極簡主義初心,變得復雜起來。
(2)繼續保持極簡和小眾,最終被創造者所拋棄。
Paper不會走(1),但是可能在(2)的路上。
我的計劃是:讓Paper永遠保持它發布時的樣子,拒絕增加多余的視覺混亂,正如用戶所說:
請不要讓 Paper 變得更復雜!市面上有很多“全功能”編輯器,但它們不適合專注寫作。
同時,通過緩慢的、可預測的更新節奏,我會向應用程序的邊緣地帶添加功能,同時保持默認路徑超級干凈。
![]()
與瀏覽器中可預測的JavaScript運行時相比,閉源原生UI是一個脆弱的地方。
如果你不努力的投入精力去重構應用,fix bug,很快,你的軟件就會因為崩潰而被大家棄用。
架構設計
我發現將Paper的代碼看做兩個作用域非常方便
1.應用程序作用域
包括菜單,狀態欄,圖標,暗黑模式,全局配置,單實例視圖
2.文檔作用域
視圖和邏輯的集合,存在于表示單個文檔的視圖控制器中。
一個新的文檔作用域在文檔打開的那一刻產生,在文檔關閉的那一刻死亡。
與單一應用程序作用域不同,多個文檔作用域可以同時存在
對每個作用域,我都會定義一個storyboard,完成以下功能:
描述作用域內使用的各種視圖和小部件
充當依賴注入容器,將作用域內所有的模塊粘合在一起。
付費功能
從2015到2017年,訂閱制在App Store中還不普遍。大家還都是付費下載,但是我覺得如果不使用的話,大家不會為一個不知名的App付費。
我其實并不想設置什么“付費墻”或者試用期啥的,我想給用戶提供更好的體驗,我的辦法就是給專業版(Pro)的某些視覺效果收費,對于基本功能如文件同步、PDF導出等保證免費。
然后我讓大家無限期的試用,感受外觀和效果,如果大家覺得不錯的話,就可以購買Pro版。
當然,必須得有辦法防止無限期地使用高級功能而不掏錢,最早的時候,我設置了一個60秒的定時器:如果有一個Pro版的功能處于激活狀態,就提醒人們購買。
說實話,60秒提醒一次挺煩人的,后來,我想了一招,把這些提醒和文字聯系起來,一旦你用Paper開始寫作,每輸入幾百個字符提示一次,這樣大家就可以盡可能不受干擾的情況下嘗試所有功能。
![]()
事實證明,從用戶反饋看,這種和文字結合的付費提醒方式很不錯:
“......Paper可以讓你隨意擺弄和測試專業功能,而不是鎖在付費墻后面(這也是我不喜歡很多應用的原因)....你不必相信我說的,自己跳進去看看,Paper讓你試用每一個特性...”
粗糙的部分
文本編輯器有太多的功能了,復制粘貼、拖放、撤銷、插入符號交互、從右到左的語言、非字母語言、聽寫、語音文本、掃描文本、文本中的非文本對象、點擊并按住鏈接預覽、文本搜索替換、拼寫檢查、自動更正、自動完成、人工智能建議......
你還得被新版的操作系統擺布,它可能增加了新的方式來插入、更新文本,和文本交互。
在iOS上,弄清楚“文本編輯器矩形”背后的數學原理尤其難,因為有各種因素,例如靈動島,主頁欄、動態顯示的軟件鍵盤,這些都會造成阻礙。
![]()
輸入語言和字體也是一個令人頭疼的問題。
字母語言相對容易處理,因為大多數主要字體甚至支持古怪的字形,例如元音變音和西里爾字母。
然而,非字母語言需要特定的字體來顯示其字形。
幸運的是,蘋果系統為每種非字母輸入語言至少預裝了一種字體。
唯一的問題是:沒有 API 將輸入語言映射到支持的字體 - 所以我不得不用大量的switch語句暴力破解它。
還有就是批量更新,對簡單的情況很容易,但是對于那些邊邊角角的情況,處理起來太痛苦了,比如加粗一段文本就耗費了很多步驟
![]()
用戶反饋
Paper最早用的是一個叫做HockeyApp的平臺,Mac版自帶聊天功能,這可比電子郵件反饋好多了,用戶可以直接啟用聊天,進行反饋。
微軟收購了 HockeyApp后, 將其變成了 AppCenter,聊天功能沒有了。
沒辦法,我只好自己做:
![]()
后來我還發現了一些小“秘密”,我寫了一些代碼,能夠從用戶未發送消息中查找一些關鍵字,然后自動回復。
![]()
自動回復回答了很多常見的問題,大大減少了我的“客服”工作量。
軟件發布
我會收集聊天中的反饋,每月做一次新版本發布。
我會使用單個遞增的數字做版本號,這是個簡單的事情,為啥要用2個以上的用點分隔的數字呢?
這是我的release note 模板:
![]()
我覺得release note 一定得簡單,這樣用戶才能真正閱讀。
錯誤修復,微調,較小的功能通常不會提及,我不喜歡類似“我們已經修復了一些錯誤并進行了一些性能改進”這樣的廢話。
不斷地更新讓用戶覺得他們的訂閱是值得的,也會告訴App Store算法,這個應用沒有被放棄。
最后,正是這種緩慢而穩定的節奏讓我能在未來幾年繼續做這件事情。
后記
這篇文章翻譯來自https://papereditor.app/dev,作者是Mihhail Lapushkin,一個愛沙尼亞的程序員。
![]()
原文中有更多章節,我做了刪減,翻譯也不是直譯,而是在保留原意的情況下,轉換成了更輕松的風格。
這篇文章讓我最為感慨的是這么幾點:
1.跨界開發
一個Web開發,毅然進入桌面領域,學習全新的知識,并且獲得成功。
所以,喜歡什么東西,就動手搞起來吧,別把現有的技術棧自己給圈住了。
現在AIGC很厲害,完全可以利用起來。
2. 目標明確,追求極致。
他追求的就是最佳的用戶體驗,為了縮小軟件大小,直接用最“原始”的Objective-C。
為了完全掌控,竟然不依賴第三方類庫,完全從頭打造。
在我的記憶中,可能只有SQLite的作者也是這么干了。
3. 不但會編程,還得有藝術品位。
這個Paper編輯器界面做得賞心悅目,就連這篇文章的網站也做得讓人看起來非常舒心。
可見Mihhail Lapushkin不但是個程序員,還是個優秀的用戶體驗設計師,很有藝術品位。
這一點我很羨慕,我一直在弄后端,就是因為搞不好界面相關的東西。
程序員眾多,把不同領域的知識結合起來,才能脫穎而出啊。
4.長時間打磨,真有時間
2015年開始做,2017年作出第一個版本,在Mac上發布,2019年發布iOS版本。
然后就是持續的打磨,到今年已經11年了。
除了真正喜歡之外,很難找到別的原因了。
Mihhail Lapushkin說“我擁有世界上所有的時間”,嗯,這些國外程序員確實太幸福了。
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.