肇鑫的技术博客

业精于勤,荒于嬉

思路改变编程:记一次思路改变节省大量编程时间的小事

使用微博RestAPI一直存在一条人为的限制,就是必须要在文章末尾添加一个验证链接。

比如你发微博“这是我的第一条微博。”,用微博RestAPI是没法直接发的,必须发成“这是我的第一条微博。https://poster.parussoft.com/index.html”。

如果你不加上这个链接,微博服务器就会提示错误,不让发微博。

这个链接对于用户其实是没有意义的。并且直接加在微博末尾,就会有人点击它,然后奇怪为什么会有一个跟内容没什么关系的链接在那里。

为了尽量减少用户点击这个链接的可能,咕唧从2018年3月底发布的1.7.13版开始,增加了一个折叠隐藏该链接的功能。利用的原理是,微博官方微博网页版和客户端,会在内容过长时,自动折叠微博,而咕唧会在字数允许的情况下,添加空行,将该链接隐藏起来。

但是这个功能存在限制,因为只有官方的网页版和客户端才有折叠的功能。其它第三方的客户端,官方的html5版以及国际版,都不具备折叠的功能。在这些微博客户端中,咕唧发布的微博就会变得特别长。因此,时不时的,我就会收到评论或者私信,问为什么我发的微博会那么长?

咕唧2决定彻底解决这个问题

我的思路是,既然这个链接必不可少,那么我可以将其从无用的链接,转换为有用的链接。这样用户点击了也不会显得突兀。类似这样的查询“https://poster.parussoft.com/jumping.php?query_string”。

weibo_forcing_ur

思路1

思路确定好之后,我发现,生成的链接必须经过服务器的处理才可以。那么就有两个思路:

  1. 直接保存对应的html文件到磁盘。(这样占用磁盘较多)
  2. 将查询条件和结果保存的数据库,动态查询。(这样占用磁盘少,但是CPU占用高。因此还需要缓存查询结果。)

我觉得第2条更好。这样就需要在服务器端使用PHP和Sqlite。思路总结完,我在服务器远程安装好PHP和Sqlite3之后,就睡觉了。

思路2

第二天,开始继续前一天的工作。我发现微博账户的用户页,其实是需要和其它链接分开的。因为微博账户的用户页,可以直接根据微博用户的id自动生成。我又想到,既然可以自动生成,那么该项就不用保存到数据库,直接通过id生成并跳转就可以了。

之后,我又想到,链接的跳转也是同样的道理,可以直接将链接做为查询的字段,这样就能直接跳转了。

这样一来,思路1中的PHP、数据库、缓存就都不需要了,服务器端只需要写一个能判断查询类型并生成跳转链接的Javascript网页就全搞定。

结论

不同的思路,需要的工作量完全不同。多思考,比埋头苦干,效率更高。

Locale苹果官方文档补遗

我们知道,在Xcode中可以通过指定运行时的语言,来测试相应的翻译。如图,我指定了中文作为在测试时的语言。

测试时指定语言

这个方式,在测试翻译的情况下是没有问题的。

最近我需要在应用中通过WKWebView,根据用户所使用的语言来动态加载网页。为了达到这个目的,我使用了

Locale.current.languageCode

根据苹果的文档,languageCode的含义是

The language code of the locale, or nil if has none.

但是实际使用中,我发现它并不能返回zh

iOS_12.1_Locale_iPhoneX

如图,实际上返回的是en_CN

我就此问题向苹果提交了错误报告。苹果回复说,从macOS 10.13, iOS 11开始,Locale.current.languageCode返回的实际上是Bundle.main.preferredLocalizations.first。这是因为苹果认为这样的用户体验最好。

苹果举例说,如果一个用户对于语言的偏好顺序是[ "zh-CN", "de-CN", "en-CN" ],而某个应用仅支持德语和英语,那么Locale.current.languageCode返回的就是de_CN

按照苹果的建议,如果想要测试中文,那么第一步就是添加中文的翻译。于是我添加了简体中文的翻译。这一下,简体中文的内容正确了。

简体中文

另外,对比一下没有中文翻译时,iOS 10和iOS 11的不同。

Locale 对比

事情还没有完,因为我希望的是用户懂中文时,使用中文;否则使用英文。而现在的方式仅能识别简体中文,当用户使用繁体中文时,还是会显示英文。于是我改了代码,新的代码

private func isChinese() -> Bool {
    let languages = Locale.preferredLanguages
    
    for lang in languages {
        if lang.hasPrefix("zh") {
            return true
        }
    }
    
    return false
}