Skip to content

Instantly share code, notes, and snippets.

View pofat's full-sized avatar

Pofat pofat

View GitHub Profile
@pofat
pofat / type_erasure.swift
Last active February 17, 2020 08:58
如何用 generic struct 消除 PAT 的問題
// 利用 init with closure 來自動代入 `Element` 真實的型別,而不是直接用 <某型別> 的方式來指定
// 先宣告一個 generic struct
struct MyAnyIterator<Element> {
// 內部使用的 Box ,裡面就是把 closure 存起來,本身也滿足 IteratorProtocol
private class AnyIteratorBox<Element>: IteratorProtocol {
typealias Base = () -> Element?
private var _base: Base
init(_ base: @escaping Base) {
self._base = base
@pofat
pofat / Dictionary+Extension.swift
Last active December 28, 2019 22:23
String KeyPath accessor of Dictionary
import Foundation
// Time Complexity: O(N), N stands for the level of key path
extension Dictionary where Key == String {
subscript(keyPath keyPath: String) -> Any? {
get {
guard !keyPath.isEmpty else { return nil }
var value: Any? = self
for key in keyPath.components(separatedBy: ".") {
if let node = (result as? [Key: Any])?[key] {

Keybase proof

I hereby claim:

  • I am pofat on github.
  • I am pofat (https://keybase.io/pofat) on keybase.
  • I have a public key ASDG9WSBfhua2AKTJqJhSDqdAuCPFwSEfVnVlhryt9fTVQo

To claim this, I am signing this object:

@pofat
pofat / ORT.swift
Created October 19, 2019 05:15
Use `Opaque Return Type` to erase type.
// 想像以下 function 定義在某一個 module 裡,外部無法決定也不依賴具體的型別 (此 func 你可以呼叫但裡面實作看不到)
func getIterator() -> some IteratorProtocol {
var state = (0, 1)
return MyAnyIterator { () -> Int in
let upcomingNumber = state.0
state = (state.1, state.0 + state.1)
return upcomingNumber
}
}
@pofat
pofat / PAT.swift
Last active October 19, 2019 03:37
PAT 好讀版
// 有 associatedtype 的 protocol
public protocol IteratorProtocol {
associatedtype Element
mutating func next() -> Element?
}
// 有 Self 的 protocol, Hashable 的 Self 來自所繼承的 Equatable
public protocol Hashable: Equatable {
var hashValue: Int { get }
func hash(into hasher: inout Hasher)
@pofat
pofat / Describer.swift
Last active August 21, 2019 08:45
weak self podcast episode 1 附錄: 用 generic struct 取代 Protocol
/*
* Standard library 有個 protocol `CustomStringConvertible`,需要實作 `description: String` 來將一個物件轉化成 description string
* 但是若你對同一個物件想要有兩種描述方式,比如
* 想要用 JSON 的方式印出來 model 的所有 property,且希望有的時候是 pretty printed 有的時候是 sorted key 怎麼辦?
* 你會需要有兩個物件來遵守 CustomStringConvertible,因為一個 protocol 在一個物件裡只能有一種實作
* 然而用 generic struct 的話就能做到這件事
* 下面的實例中你可以宣告兩個不同的 instance ,`prettyPrintedDescribing` 和 `sortedKeyDescribing`
* 想用哪個就用哪個,方便多了,也讓 compiler 有更多參與最佳化的空間
*
*/
@pofat
pofat / GetCreationTime.swift
Last active June 20, 2019 17:20
Get the timestamp of creation time of the process which runs your application in iOS
func getProcessStartTime() -> TimeInterval {
let pid = ProcessInfo.processInfo.processIdentifier
var procInfo = kinfo_proc()
var cmd: [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, pid]
var size = MemoryLayout.stride(ofValue: procInfo)
if sysctl(&cmd, UInt32(cmd.count), &procInfo, &size, nil, 0) == 0 {
// tv_sec is timestamp measured in second; tv_usec is the rest fraction part in microsecond
return Double(procInfo.kp_proc.p_un.__p_starttime.tv_sec) * 1000.0 + Double(procInfo.kp_proc.p_un.__p_starttime.tv_usec) / 1000.0
} else {
print("Can't get information of process \(pid)")
@pofat
pofat / archive_framework.sh
Last active June 19, 2019 07:42
A post-action to Xcode Archive to generate final universal framework
######################
# Create log file
######################
exec > ~/Desktop/tmp/UniversalBuild_Log_$(date +"%Y%m%d%H%M%S").log 2>&1
######################
import Foundation
import RxSwift
// MARK: Model
struct User: Decodable {
let id: Int
let name: String
}
let usersDecode: (Data) -> [User]? = { data in
// From:
protocol Drawable {
func draw()
}
// To:
struct Drawing<Shape> {
var draw: (Shape) -> ()
}