新出的 Wireguard 很多人都想嘗試,這裡 VPN 到底適不適合用來翻牆我們先不討論,先來看看怎麼快速在 vps 上起一個 wireguard 服務。很多人聽說這個服務配置起來特別複雜,所以望而卻步,實際上很簡單。
環境
這裡我用最新的 ubuntu 18.04.2 來配置,首先你得有一個 vps,創建好後最好按照我的 購買了VPS之後你應該做足的安全措施裡配置ssh的證書訪問。
新出的 Wireguard 很多人都想嘗試,這裡 VPN 到底適不適合用來翻牆我們先不討論,先來看看怎麼快速在 vps 上起一個 wireguard 服務。很多人聽說這個服務配置起來特別複雜,所以望而卻步,實際上很簡單。
這裡我用最新的 ubuntu 18.04.2 來配置,首先你得有一個 vps,創建好後最好按照我的 購買了VPS之後你應該做足的安全措施裡配置ssh的證書訪問。
在開發落格輸入法 macOS 的時候,我遇到了一個比較奇葩的問題,這個問題一直困擾我到現在——當有些地方需要垂直居中顯示一排文字的時候,如何讓這些字真正的“居中”?
乍看之下這似乎沒什麼道理,垂直居中嘛……等等,macOS 上的 的NSTextField 還真沒有辦法讓你的一行文字垂直居中……🤷♂️
後來,我[……]
作為 iOS 開發者的你,肯定是知道 Promo codes 這個東西的,也就是我們常說的兌換碼。(當然,作為 iOS 用戶興許你也對此不陌生)
這次,我們就來看看,這個看似無窮無盡的兌換碼,到底有哪些限制。
蘋果後台生成的兌換碼有效期一直是一個謎,雖然官方的說法的 4 週,也就是 28 天,但實際上如果這期間你的 app 更新了,那麼兌換碼很可能就會失效[1]。
&國家統計局[……]
在使用 Swift 進行開發落格輸入法時,我遇到了一個很有意思的問題——去重。
眾所周知,輸入法的候選在計算出來後總會有可能是重複的選項(比如碼表和詞庫中都有某個詞,也許他們編碼不同,但字是一樣的之類),這時候就需要去重,但又要保持候選的先後順序不變。
如果你去網上找,那麼你可能找到的是這樣的:
1 2 3 4 5 |
extension Array where Element : Hashable { var unique: [Element] { return Array(Set(self)) } } |
來源:[……]
辦公軟件這東西,文字處理、表格編輯、還有著名的“ppt”幻燈片,畢業後我幾乎就沒再碰過微軟係了,偶爾需要文字編輯用的也是蘋果的 iWork 系列(當然寫論文什麼的就別想了),總之,這次我要軟一次,推一下 Office 365.
其實就是微軟的辦公套件,各位可能還在用盜版——這次是絕佳的機會把它洗白——價格足夠便宜。
我的 落格輸入法 macOS 2 的中國區[……]
在兩年前,我曾寫過一篇名為《ios 為視障用戶支持 VoiceOver》的文章,裡邊主要介紹了 iOS 端該如何為 VoiceOver 進行必要的支持,後來我又開發了 macOS 端的落格輸入法,但很遺憾由於 macOS 自身系統 bug,第三方輸入法根本無法獲得 VoiceOver 焦點(主要是 10.13 及以下版本),所以我也就沒有過多關注——甚至直到這款輸入法整個生命週期結束也沒能實現 V[……]
用 Linux 的朋友可能會對這個命令比較熟悉,它可以在腳本里快速和批量地對文本文檔進行操作,比如改動某一行或者替換具體內容……
MACOS 自然也是有這個命令的,但有一點不太一樣,如果你執行 和 -一世 ,那麼多半你會得到一個奇怪的報錯 和: 1: “......”: 無效 command 碼 。
[……]
2018年11月02日 更新,切換到 DoT 一天后,所有 stubby 內置服務器運行異常緩慢,直到日常使用都難……只好放棄。
2018年11月01日 更新,使用了 5 天 DoH 後,由於目前提供此服務的服務器只有 1.1.1.1,這個地址在我這裡被運營商屏蔽了。
1 2 3 4 5 6 |
PING 1.1.1.1 (1.1.1.1): 56 data bytes Request timeout for icmp_seq 0 Request timeout for icmp_seq 1 ^C --- 1.1.1.1 ping statistics --- 3 packets transmitted, 0 packets received, 100.0% packet loss |
三年前[……]
廢話不多說,直接上代碼。
得到:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// 创建一个会话,这个会话可以复用 let session = URLSession(configuration: .default) // 设置URL let url = "http://127.0.0.1/api/" var UrlRequest = URLRequest(url: URL(string: url)!) // 创建一个网络任务 let task = session.dataTask(with: UrlRequest) {(data, response, error) in do { // 返回的是一个json,将返回的json转成字典r let r = try JSONSerialization.jsonObject(with: data!, options: []) as! NSDictionary print(r) } catch { // 如果连接失败就... print("无法连接到服务器") return } } // 运行此任务 task.resume() |
POST:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// 这个session可以使用刚才创建的。 let session = URLSession(configuration: .default) // 设置URL let url = "http://127.0.0.1/api/" var request = URLRequest(url: URL(string: url)!) request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") request.httpMethod = "POST" // 设置要post的内容,字典格式 let postData = ["email":"user@xxx.com","password":"123456"] let postString = postData.compactMap({ (key, value) -> String in return "\(key)=\(value)" }).joined(separator: "&") request.httpBody = postString.data(using: .utf8) // 后面不解释了,和GET的注释一样 let task = session.dataTask(with: request) {(data, response, error) in do { let r = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary print(r) } catch { print("无法连接到服务器") return } } task.resume() |
[……]