填平 macOS 和 iOS 之间的鸿沟

2,434 阅读4分钟
原文链接: www.jianshu.com

tags:开发随笔


mac and iOS

虽然mac存在了很多年之后才有了iOS,但是对很多程序员而言,可能是先熟悉了 UIKit之后才去熟悉AppKit。

我自己也是这样。在开发了MarkNote之后,我想把MarkNote的笔记体验延伸到mac。

有没有工具或者库可以直接将iOS应用转换为macOS应用

最初我只是想让iOS版本的MarkNote照搬过来,于是我想看看是否有捷径可走。最理想的情况下,有一个工具,直接把iOS上的代码转换一下,就可以在mac下运行。或者直接在mac上给iOS应用提供一个runtime?

查了一下之后,发现真有人有类似的想法。

  • chameleon将UIKit移植到OS X。然而,这个库只实现了UIKit中的大部分API。更可惜的是,这个库三年前就停止更新了。
  • UMEKit也做了类似的事,然而,实现的更少。而且,7年前就停了。

这些库之所以夭折,在很大程度上是因为其复杂程度远远超过看起来的那样。桌面应用和移动应用的机制有很大的不同。虽然UIKit和AppKit共享了很多概念,但是API依然有很大的不同。比如UIView和 NSView虽然看起来很像,但是实现细节和使用上有很多不同。

MarkNote的macOS实现策略

虽然Chameleon看起来很有意思,但是我最终没有采用这个方案。一来我担心其局限性的制约,二来我找到了现在看来效果非常好的策略。

我的设计策略总结起来是以下两点:

  • 正视macOS和iOS的不同。 mac有mac擅长的地方,在很多方面受的局限更小,应用之可以获得更好的用户体验。比如这篇文字,虽然在iOS上也可以撰写,还是不如mac上写起来畅快淋漓。
  • 尽量在2个平台间复用代码。对于MarkNote而言,我希望核心的代码是完全通用的。比如markdown解析,笔记管理等等。

我采用了以下的办法来提高复用:

  • 业务逻辑和UI操作彻底分离。 核心的业务逻辑在理想情况下应该只依赖于 Foundation 而不依赖于 Cocoa 或者UIKit。比如Markdown解析,就仅仅依赖于Foundation。
  • 将通用的代码单独建project并打包为framewok。MarkNote的工程视图如下:

project

其中:
MarkNoteParserOC 是Obj-C版的markdown 解析器,已经开源
MarkEditor是语法高亮编辑器,支持iOS和macOS。不仅为mac版和iOS版的MarkNote使用,同时也是InstantCoder的代码编辑器。其一个早期版本也已经开源
MarkNoteEngine是笔记管理和iCloud同步的核心库,为mac版和iOS版的MarkNote使用。
MarkNotes是mac版的MarkNote。
MarkNote是iOS版的MarkNote。

  • 一个Framework,两个target
    在同一个工程中,分别给macOS和iOS创建不同的target。

target
  • 使用宏来区分不同的版本
    虽然代码很多相同,但是还是有很多系统之间的差异。这个时候可以用宏来处理。比如我需要给mac版的加openWithCompletionHandler,而无需给iOS版添加它,就可以用类似下面的代码:
#if !TARGET_OS_IPHONE
- (void)openWithCompletionHandler:(void (^)(BOOL success))completionHandler;
#endif
  • 使用宏来融合UIKit和AppKit的不同
    AppKit和UIKit中很多API都是相似的。比如NSColor和UIColor,NSView和UIView,等等。这个时候,用宏定义一个别名,可能是融合使用的一个好办法。
    比如,我的文本编辑器在本质上只是NSTextView或者 UITextViewUI的一个category。
    因此我定义了一个宏BaseTextView来分别在macOS上指向NSTextView,而在iOS上指向UITextView:
    #if TARGET_OS_IPHONE
    #import <UIKit/UIKit.h>
    #define BaseTextView UITextView
    #else
    #import <Cocoa/Cocoa.h>
    #define BaseTextView NSTextView
    #endif
    这样,我后面也就直接用BaseTextView好了。比如
@interface BaseTextView(Editor)

MarkNote IOS版在2015年5月上线,mac版在2015年11月上线。之后两个版本都分别更新了十多次。上面所描述的策略和方法,使得我的代码维护起来清晰而简单。