在快手做分享、無(wú)用類檢查奶躯、在廣州做 SwiftUI 學(xué)習(xí)筆記分享帚桩、InfoQ二叉樹(shù)視頻

在快手做分享

前滴滴同事邀請(qǐng)我去快手做分享。下面是分享時(shí)的 Slides:

詳細(xì)文章介紹:如何對(duì) iOS 啟動(dòng)階段耗時(shí)進(jìn)行分析 | 星光社 - 戴銘的博客

代碼:GitHub - ming1016/MethodTraceAnalyze: 方法耗時(shí)分析

無(wú)用類檢查

如果包里有一堆沒(méi)用的類嘹黔,不光會(huì)影響用戶下載速度账嚎,也會(huì)影響啟動(dòng)加載速度。檢查無(wú)用類儡蔓,一次是無(wú)法獲得全部無(wú)用類的郭蕉,因?yàn)闊o(wú)用的類里用了其他無(wú)用的類就算是有用了,所以需要進(jìn)行遞歸查找喂江,這樣才能夠連根拔起召锈。這個(gè)過(guò)程如果是手動(dòng)做比較費(fèi)勁、收益無(wú)法一次評(píng)估获询,很難推動(dòng)涨岁。同時(shí)還需要在線上灰度運(yùn)行時(shí)檢查實(shí)際類的使用情況,很多靜態(tài)層面關(guān)聯(lián)的類使用吉嚣,實(shí)際運(yùn)行過(guò)程中也可能用不到梢薪。

思路和關(guān)鍵代碼如下。

第一步

使用 MethodTraceAnalyze 里 ParseOC 類的 ocNodes 函數(shù)尝哆,通過(guò)傳入 workspace 路徑獲取所有節(jié)點(diǎn)的結(jié)構(gòu)體 OCNode沮尿。

let allNodes = ParseOC.ocNodes(workspacePath: workSpacePath)

找出類型是方法的結(jié)構(gòu)體,因?yàn)轭惖某跏蓟褪褂枚际窃谶@些方法中進(jìn)行的较解。OCNode 針對(duì)不同類型所存儲(chǔ)的數(shù)據(jù)也是不同的,所以我定義一個(gè) OCNodeValueProtocol 協(xié)議屬性赴邻,這樣就可以針對(duì)不同類型的節(jié)點(diǎn)存儲(chǔ)不同的數(shù)據(jù)印衔。

public struct OCNodeDefaultValue: OCNodeValueProtocol {
    public var defaultValue: String
    init() {
        defaultValue = ""
    }
}

public struct OCNodeMethod: OCNodeValueProtocol {
    public var belongClass: String
    public var methodName: String
    public var tokenNodes: [OCTokenNode]
}

public struct OCNodeClass: OCNodeValueProtocol {
    public var className: String
    public var baseClass: String
    public var hMethod: [String]
    public var mMethod: [String]
    public var baseClasses: [String]
}

可以看到對(duì)方法類型會(huì)存所屬類、方法名和方法內(nèi)所有 token以便進(jìn)行進(jìn)一步分析姥敛。對(duì)類這種類型會(huì)記錄他的基類奸焙、類名、頭文件方法列表和實(shí)現(xiàn)文件方法列表,還用一個(gè)棧記錄繼承鏈与帆。

第二步

獲取所有類的節(jié)點(diǎn)了赌,通過(guò)對(duì)方法內(nèi)所有 token 的分析來(lái)看使用了哪些類,并記錄使用的類玄糟。

獲取所有類節(jié)點(diǎn)的代碼如下:

// 獲取所有類節(jié)點(diǎn)
var allClassSet:Set<String> = Set()
for aNode in allNodes {
    if aNode.type == .class {
        let classValue = aNode.value as! OCNodeClass
        allClassSet.insert(classValue.className)
        if classValue.baseClass.count > 0 {
            baseClasses.insert(classValue.baseClass)
        }
        
    }
} // end for aNode in allNodes

記錄使用的類關(guān)鍵代碼:

static func parseAMethodUsedClass(node: OCNode, allClass: Set<String>) -> Set<String> {
    var usedClassSet:Set<String> = Set()
    guard node.type == .method else {
        return usedClassSet
    }
    
    let methodValue:OCNodeMethod = node.value as! OCNodeMethod
    for aNode in methodValue.tokenNodes {
        if allClass.contains(aNode.value) {
            usedClassSet.insert(aNode.value)
        }
    }
    
    return usedClassSet
}

第三步

有了所有使用的類和所有的類勿她,就能夠獲取沒(méi)用到的類。為了跑一次就能夠?qū)⑺袥](méi)用的類找出阵翎,所以需要在找到無(wú)用類后逢并,將這些類自動(dòng)去掉再進(jìn)行下一次查找。我這里寫了個(gè)遞歸來(lái)干這件事郭卫。具體代碼如下:

var recursiveCount = 0

func recursiveCheckUnUsedClass(unUsed:Set<String>) -> Set<String> {
    recursiveCount += 1
    print("into recursive!!!!第\(recursiveCount)次")
    print("----------------------\n")
    for a in unUsed {
        print(a)
    }
    var unUsedClassSet = unUsed
    
    // 縮小范圍
    for aUnUsed in unUsedClassSet {
        if allClassSet.contains(aUnUsed) {
            allClassSet.remove(aUnUsed)
        }
    }
    
    var allUsedClassSet:Set<String> = Set()
    for aNode in allNodes {
        if aNode.type == .method {
            let nodeValue:OCNodeMethod = aNode.value as! OCNodeMethod
            // 過(guò)濾已判定無(wú)用類里的方法
            guard !unUsedClassSet.contains(nodeValue.belongClass) else {
                continue
            }
            
            let usedSet = ParseOCMethodContent.parseAMethodUsedClass(node: aNode, allClass: allClassSet)
            if usedSet.count > 0 {
                for aSet in usedSet {
                    allUsedClassSet.insert(aSet)
                }
            } // end if usedSet.count > 0
        } // end if aNode.type == .method
    } // end for aNode in allNodes
    var hasUnUsed = false
    // 找出無(wú)用類
    for aSet in allClassSet {
        if !allUsedClassSet.contains(aSet) {
            unUsedClassSet.insert(aSet)
            hasUnUsed = true
        }
    }
    
    if hasUnUsed {
        // 如果發(fā)現(xiàn)還有無(wú)用的類乃摹,需要繼續(xù)遞歸調(diào)用進(jìn)行分析
        return recursiveCheckUnUsedClass(unUsed: unUsedClassSet)
    }
    
    return unUsedClassSet
}

// 遞歸調(diào)用
var unUsedClassFromRecursive = recursiveCheckUnUsedClass(unUsed: Set<String>())

通過(guò)遞歸進(jìn)行多次能夠取到最終的結(jié)果陵像。

第四步

對(duì)于繼承和系統(tǒng)的類還需要進(jìn)行過(guò)濾,進(jìn)一步提高準(zhǔn)確性。

let unUsedClassSetCopy = unUsedClassFromRecursive
for aSet in unUsedClassSetCopy {
    // 過(guò)濾系統(tǒng)控件
    let filters = ["NS","UI"]
    var shouldFilter = false
    for filter in filters {
        if aSet.hasPrefix(filter) {
            shouldFilter = true
        }
    }
    // 過(guò)濾基類
    if baseClasses.contains(aSet) {
        shouldFilter = true
    }
    
    // 開(kāi)始過(guò)濾
    if shouldFilter {
        unUsedClassFromRecursive.remove(aSet)
    }
}

清理了通過(guò)這種靜態(tài)掃描出的無(wú)用類烁试,還可以通過(guò)運(yùn)行時(shí)來(lái)判斷類是否被初始化了,從而找出無(wú)用類饮怯。類運(yùn)行時(shí)是否初始化的這個(gè)信息是個(gè)布爾值废境,叫 isInitialized,存儲(chǔ)在元類 class_rw_t 結(jié)構(gòu)體的 flags 字段里寒跳,在 1<<29 位記錄聘萨。

完整代碼見(jiàn) ParseOCMethodContent 文件:MethodTraceAnalyze/ParseOCMethodContent.swift at master · ming1016/MethodTraceAnalyze · GitHub

在廣州做的 SwiftUI 學(xué)習(xí)筆記分享

下面是筆記內(nèi)容:

推薦喵神的 SwiftUI 新書(shū),ObjC 中國(guó) - SwiftUI 與 Combine 編程童太。

這本介紹 Combine 的書(shū)也介紹的非常詳細(xì):Using Combine

這個(gè)網(wǎng)站有大量 SwiftUI 的控件使用范例可以參考:SwiftUI by Example - free quick start tutorials for Swift developers

這個(gè)博客每篇都是 SwiftUI 相關(guān)的米辐,而且更新非常頻繁:Home | Majid’s blog about Swift development

InfoQ二叉樹(shù)視頻

五分鐘的視頻,在導(dǎo)演構(gòu)思下需要一天在四個(gè)地方進(jìn)行拍攝书释,由于前一天晚上慶功宴喝高了翘贮,拍攝當(dāng)天 iPad 筆也忘帶了,頭還有些懵爆惧。導(dǎo)演中午飯都沒(méi)吃專門回家拿了他的筆給我用狸页。下午地點(diǎn)安排在央美,先訪談再畫一張扯再。北京電影學(xué)院畢業(yè)14年專業(yè)繪畫經(jīng)驗(yàn)的導(dǎo)演賈成斌芍耘,在我畫時(shí)邊幫我改畫邊傳授了經(jīng)驗(yàn),我覺(jué)得這些經(jīng)驗(yàn)會(huì)讓我更進(jìn)一步熄阻。

下面是記者剡沛在 InfoQ 上發(fā)布的采訪內(nèi)容和視頻斋竞,原文在:“創(chuàng)造,就值得被肯定”秃殉,一名程序員的藝術(shù)人生丨二叉樹(shù)視頻

他是一名程序員坝初,同時(shí)也用自己的業(yè)余時(shí)間畫畫浸剩。無(wú)論是技術(shù)分享還是珍藏回憶,他都用畫筆記錄自己鳄袍,連接他人绢要。他覺(jué)得程序員很酷,無(wú)論編程還是畫畫拗小,都是在創(chuàng)造重罪,這就是最值得肯定的事情。

他在高德負(fù)責(zé)架構(gòu)研發(fā)工作十籍,也是大家眼中的藝術(shù)家蛆封,在他身上總能看到那些執(zhí)念與決心,它們發(fā)著光勾栗,無(wú)時(shí)無(wú)刻不影響著周圍的人惨篱。

他就是戴銘,一名酷酷的程序員围俘。

當(dāng)聊到”連接“這個(gè)詞的時(shí)候砸讳,他的眼神異常堅(jiān)定。

他覺(jué)得自己堅(jiān)持創(chuàng)作界牡,堅(jiān)持做很多沒(méi)有門檻的技術(shù)分享簿寂,很大一部分動(dòng)力就來(lái)自這種渴望,渴望連接自己的過(guò)去宿亡,也渴望連接他人常遂。

他就是戴銘,一個(gè)有點(diǎn)酷挽荠,還有點(diǎn)文藝的程序員克胳,在高德地圖負(fù)責(zé)架構(gòu)研發(fā)工作。除了把自己活的很年輕圈匆,在他身上總能看到一些發(fā)著光的東西漠另。

“是信念嗎?”

“是執(zhí)念跃赚“蚀辏”

“當(dāng)漫畫家,可能連飯都吃不飽纬傲÷埽”

故事的開(kāi)頭,多少有些遺憾叹括。

戴銘最早接觸畫畫葫录,是小學(xué)之前報(bào)過(guò)的一個(gè)高階國(guó)畫班,因?yàn)槔蠋熢谏虾A旎运慨嬐暌粡埗家倪^(guò)去并等待回信米同,當(dāng)其中一幅畫改到第三遍的時(shí)候老師回信說(shuō):這孩子可能沒(méi)什么天賦。因?yàn)檫@件事摔竿,當(dāng)時(shí)戴銘心里對(duì)畫畫的渴望面粮,幾乎降到了冰點(diǎn),對(duì)于畫畫的興趣也就此擱置继低。

直到六年級(jí)的一次美術(shù)作業(yè)熬苍,平時(shí)酷愛(ài)看漫畫的戴銘,才再一次下定決心把自己喜歡的角色搬到紙上袁翁。

“同學(xué)都說(shuō)畫的太像了柴底,那種被再次肯定的開(kāi)心,很難忘記粱胜”ぃ”

后來(lái)整個(gè)初中,戴銘都在課余時(shí)間畫漫畫焙压,也沒(méi)再報(bào)班鸿脓,一直到初中畢業(yè)戴銘跟父親說(shuō)不想上學(xué)了,“想去畫漫畫涯曲,做一名漫畫家”野哭。不難預(yù)料,這個(gè)想法并沒(méi)有得到父親的支持幻件,“當(dāng)漫畫家拨黔,可能連飯都吃不飽”。

但從戴銘的話語(yǔ)中绰沥,并沒(méi)有因?yàn)楦赣H這次選擇而聽(tīng)到絲毫氣餒篱蝇,似乎心里的種子已經(jīng)生根。

“興趣不是說(shuō)喜歡漫畫揪利,就要去從事漫畫态兴。當(dāng)我們從被動(dòng)的行為中獲得成就感時(shí),也會(huì)在無(wú)形中培養(yǎng)出興趣疟位,畫畫如此瞻润,編程也是一樣√鹂蹋“

“我不想讓自己投入了生命的熱愛(ài)绍撞,停滯不前〉迷海”

“從那后來(lái)傻铣,就一直在堅(jiān)持畫畫了∠榻剩”

從臨摹簡(jiǎn)單的漫畫非洲,到更復(fù)雜的畫風(fēng)鸭限、更多元的角色,再到臨摹寫實(shí)人物两踏、影視劇照败京,期間還專門自學(xué)過(guò)素描,直到現(xiàn)在的再創(chuàng)作梦染,戴銘除了把自己的愛(ài)好和回憶畫出來(lái)赡麦,還把自己的專業(yè)內(nèi)容做成漫畫,用更容易傳達(dá)的方式去做每一次技術(shù)分享帕识。

“大概是從四泛粹、五年前開(kāi)始,空閑的時(shí)候會(huì)花很長(zhǎng)的時(shí)間畫畫肮疗,平時(shí)每天也會(huì)擠出一個(gè)多小時(shí)堅(jiān)持練手晶姊,因?yàn)槲也幌M约簾釔?ài)的東西,停滯不前族吻,興趣不該只是興趣而已帽借。”

后來(lái)戴銘接觸了數(shù)繪超歌,就開(kāi)始把很多創(chuàng)作留在屏幕上砍艾。

“用 ipad 畫,更適合我現(xiàn)在的角色巍举,因?yàn)榭梢噪S時(shí)開(kāi)始和結(jié)束脆荷,不受環(huán)境和工具的影響,另一方面數(shù)字繪圖也讓他的作品在色彩方面懊悯,有了更多的提升空間蜓谋。”

從容地掏出平板炭分,只要自己想桃焕,就能隨時(shí)還原周遭的一切。這種感覺(jué)捧毛,就跟戴銘看待程序員時(shí)的表達(dá)一樣观堂,“都是很酷的事情,因?yàn)闊o(wú)論程序員的人還是藝術(shù)家呀忧,他們都在創(chuàng)造新的事物师痕,僅這一點(diǎn),就值得被肯定而账∫确兀”

“工作不用心的人,生活也不會(huì)太精彩”

類似畫畫這種需要大量時(shí)間去“熬”的愛(ài)好泞辐,堅(jiān)持總是最難的部分笔横。

“時(shí)間永遠(yuǎn)都是緊缺的竞滓,這是肯定。如果工作很忙吹缔,就先把時(shí)間全部投入到工作上虽界,用最快的速度做好、做完涛菠,才能有更多的精力和心情去做其他事情”。

戴銘上一份工作在滴滴撇吞,剛?cè)肼毦拖M貙捵约旱哪芰Ψ秶锥常瑤缀醭袚?dān)整個(gè)部門的研發(fā)任務(wù),后來(lái)臨近發(fā)版 Bug 實(shí)在解不完牍颈,第二天來(lái)公司發(fā)現(xiàn)都被領(lǐng)導(dǎo)默默解掉了迄薄,才意識(shí)到一個(gè)人的力量始終有限,“一個(gè)手指煮岁,肯定比不過(guò)一個(gè)拳頭的力量讥蔽。”

即便如此画机,戴銘也始終保持著對(duì)工作的熱血冶伞,當(dāng)時(shí)間不夠用的時(shí)候,他會(huì)換個(gè)角度去看待問(wèn)題步氏。

“我覺(jué)得工作上面不上心响禽、不拼命的人,生活也不會(huì)太精彩荚醒。工作是跟每個(gè)人的一生切實(shí)相關(guān)的事情芋类,如果連這個(gè)都做不好,又如何能在其他事情上更用心的經(jīng)營(yíng)界阁?”

時(shí)間看透了侯繁,剩下的就是堅(jiān)持。

當(dāng)聊到堅(jiān)持的原動(dòng)力時(shí)泡躯,除了用回憶和分享去推動(dòng)自己贮竟,在戴銘身上總散發(fā)著一股勁兒。一個(gè)興趣愛(ài)好而已精续,談信念可能過(guò)于悲壯坝锰,所以他認(rèn)為,這股勁兒更像是決心和執(zhí)念重付。

有剛?cè)脒M(jìn)入滴滴時(shí)顷级,想肩扛所有工作的執(zhí)念;

有為了興趣上一個(gè)臺(tái)階确垫,努力獲得央美朋友肯定的執(zhí)念弓颈;

也有怕自己的作品破壞了心中的完美角色帽芽,重復(fù)打磨的執(zhí)念。

結(jié)尾

戴銘是很強(qiáng)大的人翔冀,他講過(guò)的一段話令人印象深刻:

“幸福是面對(duì)過(guò)去导街,恐懼是面對(duì)未知的未來(lái)。我也忘記是從哪里看到的這句話纤子,但我自己會(huì)這樣理解:回憶是讓人幸福的搬瑰,未知是令人恐懼的。但如果我們沉湎在回憶中不敢面對(duì)未來(lái)控硼,幸福始終是有限的泽论,當(dāng)我們用決心去面對(duì)未來(lái),幸福就會(huì)越來(lái)越多卡乾,恐懼也會(huì)越來(lái)越少翼悴。”

裹著決心這把利劍幔妨,酷酷的戴銘就這樣用代碼和畫筆勾勒著自己的一生鹦赎,而畫卷展開(kāi)的部分就已經(jīng)足夠精彩,余下的误堡,定會(huì)更值得期待古话。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市埂伦,隨后出現(xiàn)的幾起案子煞额,更是在濱河造成了極大的恐慌,老刑警劉巖沾谜,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件膊毁,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡基跑,警方通過(guò)查閱死者的電腦和手機(jī)婚温,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)媳否,“玉大人栅螟,你說(shuō)我怎么就攤上這事±榻撸” “怎么了力图?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)掺逼。 經(jīng)常有香客問(wèn)我吃媒,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任赘那,我火速辦了婚禮刑桑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘募舟。我一直安慰自己祠斧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布拱礁。 她就那樣靜靜地躺著琢锋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪呢灶。 梳的紋絲不亂的頭發(fā)上吩蔑,一...
    開(kāi)封第一講書(shū)人閱讀 49,111評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音填抬,去河邊找鬼。 笑死隧期,一個(gè)胖子當(dāng)著我的面吹牛飒责,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播仆潮,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼宏蛉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了性置?” 一聲冷哼從身側(cè)響起拾并,我...
    開(kāi)封第一講書(shū)人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鹏浅,沒(méi)想到半個(gè)月后嗅义,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡隐砸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年之碗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片季希。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡褪那,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出式塌,到底是詐尸還是另有隱情博敬,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布峰尝,位于F島的核電站偏窝,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜囚枪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一派诬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧链沼,春花似錦默赂、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至疾捍,卻和暖如春奈辰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背乱豆。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工奖恰, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人宛裕。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓瑟啃,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親揩尸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蛹屿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345