原文:http://joeshang.github.io/2015/04/10/fix-xcode-upgrade-plugin-invalid/
Xcode 的插件大大豐富了 Xcode 的功能,而且有了 Alcatraz ,插件的管理也非常容易,像我這種 Vim 黨完全離不開 XVim。但是有個非常惱人的問題:一旦升級 Xcode ,插件就失效!
之前 Xcode 升級到6.2的時候遇到過插件失效的問題,Google 之后把一段很長命令復制到 Terminal 后運行一下即可,當時一看解決了,頓時覺得滿足感爆棚,自己可以拯救地球了~就沒有再深入,結果升級到6.3時又遇到了。“同樣的招式對圣斗士是不能使用第二次的!”,同樣的坑對有節操的程序員是不能掉進去第二次的!因此這一次一定要搞清楚為什么會這樣,以后再次遇到了如何解決。
問題原因
Xcode 的插件放置在 ~/Library/Application\ Support/Developer/Shared/Xcode/Plug-ins
目錄下,為 .xcplugin 格式。通過 Show Content 可以看到 xcplugin 中存在一個 Info.plist,其中有一項為 DVTPlugInCompatibilityUUIDs,而這就是插件失效的原因。
由于 Apple 沒有公開插件開發的相關資料,這里我只能通過命名跟值猜測 DVTPlugInCompatibilityUUIDs 的作用:插件通過 DVTPlugInCompatibilityUUIDs 來指定能夠運行此插件的 Xcode 版本。因此,DVTPlugInCompatibilityUUIDs 中存放的是 Xcode 版本對應的 UUID,Xcode 在啟動加載控件時,將當前 UUID 同插件 Info.plist 中 DVTPlugInCompatibilityUUIDs 存放的 UUID 數組進行匹配,如果沒有匹配項,說明此插件無法在該版本的 Xcode 運行,插件也就失效了。
解決辦法
解決辦法非常簡單:將當前版本的 UUID 加到 DVTPlugInCompatibilityUUIDs 中即可。但是插件比較多(1個及以上)的情況下,一個個的打開修改非常無聊跟低效,作為“懶惰”的程序員,這時候就要用上命令行,讓重復勞動自動化。思路為將命令分為兩部分:
- 通過
find
命令在插件目錄下找到所有插件的 Info.plist 文件。 - 通過
barges
命令對上一步的搜索結果進行“for 循環”(就這樣理解吧),針對每一個 Info.plist 文件,利用defaults write
命令將當前版本的 UUID 加到 DVTPlugInCompatibilityUUIDs 中。
此時問題來了,挖掘機技術。。。不對,是如何獲取當前版本 Xcode 的 UUID 呢?首先關掉 Xcode,打開 Terminal,輸入tail -f /var/log/system.log
,再次打開 Xcode,就能看到如下 log 信息:
[MT] PluginLoading: Required plug-in compatibility UUID 9F75337B-21B4-4ADC-B558-F9CADF7073A7 for plug-in at path ‘~/Library/Application Support/Developer/Shared/Xcode/Plug-ins/Alcatraz.xcplugin’ not present in DVTPlugInCompatibilityUUIDs
可以看到,log 信息表明 Xcode 加載插件失敗的原因,并且能夠看到當前版本(6.3)Xcode 的 UUID 為9F75337B-21B4-4ADC-B558-F9CADF7073A7
。經過 @Kyrrr 的提醒,有一種更好的方式來獲取當前版本 Xcode 的 UUID:通過defaults read
命令從 Xcode 的 Info.plist 讀取 DVTPlugInCompatibilityUUID。
最終的命令為:
find ~/Library/Application\ Support/Developer/Shared/Xcode/Plug-ins -name Info.plist -maxdepth 3 | xargs -I{} defaults write {} DVTPlugInCompatibilityUUIDs -array-add `defaults read /Applications/Xcode.app/Contents/Info.plist DVTPlugInCompatibilityUUID`
在 Terminal 中運行上述命令就解決了插件失效的問題,在插件 Info.plist 的 DVTPlugInCompatibilityUUIDs 中也能看到新增的 UUID 了。