带有 Swift 超慢输入和自动完成功能的 Xcode 6
Posted
技术标签:
【中文标题】带有 Swift 超慢输入和自动完成功能的 Xcode 6【英文标题】:Xcode 6 with Swift super slow typing and autocompletion 【发布时间】:2014-11-14 21:08:50 【问题描述】:当您键入代码时,使用 Swift 的只有我还是 Xcode 6 (6.0.1) 似乎超级慢,尤其是自动完成?
一个普通的 Objective-C 类,即使在 Swift 项目中,也几乎和以前一样工作,所以是 Swift 杀死了它。
是否有其他人遇到同样的不便?您对如何提高性能有任何想法吗?
我尝试了一些设置,但没有成功。 我当然也尝试过重启 Xcode 和计算机,但没有成功。 没有其他重 应用已打开。我使用的是 2009 年中期的 Macbook Pro(2.26 GHz Intel Core 2 Duo),配备 8GB RAM 和 SSD HD,这根本不是最新的东西,但仍然不是一个完整的垃圾。
很遗憾,我很高兴开始使用 Swift,但现在真的难以忍受。
想法/提示?
【问题讨论】:
我和你有同样的问题。 Xcode 经常告诉我“SourceKit 已终止,编辑器暂时受限” 是的,这也是另一个问题,但我不确定它们是否相关。即使发生该错误,它也很慢。 我确定它们是相关的。在 beta 5 中,我更频繁地看到该消息,并且每当建议不起作用时,我都会看到该消息。 (当我输入一些字符并按 Esc 触发建议时) 我也有同样的问题。我的 XCode 使用了 300% 以上的 CPU,并将我的 macbook 视网膜速度减慢到蜗牛般的速度。这几天我几乎是盲目地打字,然后等待 xcode 完成。 在 2011 年末配备 8 GB RAM 和 SSD 的 15.6" MacBook Pro 上遇到同样的问题。90% 的时间代码完成会冻结 Xcode,当我检查活动监视器时,我看到 ~200% CPU使用情况。冻结时间从几秒钟到几分钟不等。 【参考方案1】: 退出 Xcode 并重新启动 Mac 不是必需的,但首选。 删除文件夹的内容 ~/Library/Developer/Xcode/DerivedData 删除内容 ~/Library/Caches/com.apple.dt.Xcode这是一个暂时的解决方案,但效果很好。
使用脚本编辑器应用程序在脚本下方。
tell application "Terminal"
do script "rm -frd ~/Library/Developer/Xcode/DerivedData/*"
do script "rm -frd ~/Library/Caches/com.apple.dt.Xcode/*"
end tell
或者,您可以像这样为您的终端创建一个别名:
alias xcodeclean="rm -frd ~/Library/Developer/Xcode/DerivedData/* && rm -frd ~/Library/Caches/com.apple.dt.Xcode/*"
您可以将其添加到您的~/.bash_profile
,然后每次您想清除这两个文件夹时在命令行中输入xcodeclean
。
【讨论】:
好吧,虽然它并不完美,但看起来您的解决方案确实显着改进了它。我将标记为解决,因为经过很长时间,这可能是它可以得到的最好的。很高兴听到其他人的消息...非常感谢! 我的笔记本电脑花了将近一分钟的时间从这两个文件夹中删除了所有内容。 Xcode 上的索引现在需要不到 30 秒。 它并没有让我的打字和自动完成速度更快,但它确实帮助我从我的 Mac 上释放了相当多的空间。 这个答案有助于自动完成,***.com/a/29849869/1213267【参考方案2】:我在输入一些“简单”代码时也体验到了 100% 以上的 CPU。通过构建代码的方式使 swift-parser 更快的一些小技巧。
不要在字符串中使用“+”连接符。对我来说,这很快就会触发缓慢。 每个新的“+”都会使解析器陷入困境,每次您在函数体的某处添加新字符时,它都必须重新解析代码。
代替:
var str = "This" + String(myArray.count) + " is " + String(someVar)
使用在 swift 中解析似乎更有效的模板语法:
var str = "This \(myArray.count) is \(someVar)"
这样我基本上注意到 strlen 没有限制 inline vars "\(*)" 。
如果你有计算,使用 + / * - 然后将它们分成更小的部分。
代替:
var result = pi * 2 * radius
使用:
var result = pi * 2
result *= radius
它可能看起来效率较低,但这样的 swift 解析器要快得多。 如果某些公式需要进行许多操作,即使它们在数学上是正确的,它们也无法编译。
如果你有一些复杂的计算,那么把它放在一个函数中。这样,解析器可以解析一次,而不必在每次更改函数体中的某些内容时重新解析它。
因为如果你的函数体中有一个计算,那么 swift 解析器每次都会检查它,如果类型、语法等仍然正确。如果计算上方的行发生更改,则计算/公式中的某些变量可能已更改。如果你把它放在一个外部函数中,那么它将被验证一次,并且 swift 很高兴它是正确的并且不会不断地重新解析它,这会导致 CPU 使用率很高。
这样我在打字时从每次按键的 100% 到低 CPU。 例如,这 3 行内联在你的函数体中可以使 swiftparser 爬行。
let fullPath = "\(NSHomeDirectory())/Library/Preferences/com.apple.spaces.plist"
let spacesData = NSDictionary(contentsOfFile: fullPath )! // as Dictionary<String, AnyObject>
let spaces : AnyObject = spacesData["SpacesDisplayConfiguration"]!["Management Data"]!!["Monitors"]!![0]["Spaces"]!!
println ( spaces )
但是如果我把它放在一个 func 中稍后调用它,swiftparser 会快得多
// some crazy typecasting here to silence the parser
// Autodetect of Type from Plist is very rudimentary,
// so you have to teach swift your types
// i hope this will get improved in swift in future
// would be much easier if one had a xpath filter with
// spacesData.getxpath( "SpacesDisplayConfiguration/Management Data/Monitors/0/Spaces" ) as Array<*>
// and xcode could detect type from the plist automatically
// maybe somebody can show me a more efficient way to do it
// again to make it nice for the swift parser, many vars and small statements
func getSpacesDataFromPlist() -> Array<Dictionary<String, AnyObject>>
let fullPath = "\(NSHomeDirectory())/Library/Preferences/com.apple.spaces.plist"
let spacesData = NSDictionary(contentsOfFile: fullPath )! as Dictionary<String, AnyObject>
let sdconfig = spacesData["SpacesDisplayConfiguration"] as Dictionary<String, AnyObject>
let mandata = sdconfig["Management Data"] as Dictionary<String, AnyObject>
let monitors = mandata["Monitors"] as Array<Dictionary<String, AnyObject>>
let monitor = monitors[0] as Dictionary<String, AnyObject>
let spaces = monitor["Spaces"] as Array<Dictionary<String, AnyObject>>
return spaces
func awakeFromNib()
....
... typing here ...
let spaces = self.getSpacesDataFromPlist()
println( spaces)
Swift 和 XCode 6.1 仍然有很多 bug,但是如果你遵循这些简单的技巧,编辑代码就会再次变得可以接受。我更喜欢 swift,因为它摆脱了 .h 文件并使用更简洁的语法。仍然需要许多类型转换,例如 "myVar as AnyObject" ,但与复杂的 Objective-C 项目结构和语法相比,这是较小的邪恶。
还有另一种体验,我尝试了 SpriteKit,它使用起来很有趣,但如果你不需要以 60 fps 的速度不断重绘,它的效率就很低了。如果您的“精灵”不经常更改,则使用旧的 CALayers 对 CPU 来说要好得多。如果您不更改图层的 .contents,则 CPU 基本上处于空闲状态,但如果您在后台运行 SpriteKit 应用程序,则由于硬限制 60fps 更新循环,其他应用程序中的视频播放可能会开始卡顿。
有时 xcode 在编译时显示奇怪的错误,然后进入菜单“Product > Clean”并再次编译它会有所帮助,这似乎是缓存的错误实现。
在另一个 *** 帖子 here 中提到了当 xcode 卡在您的代码中时改进解析的另一种好方法。基本上,您将 .swift 文件中的所有内容复制到外部编辑器中,然后逐个函数将其复制回来,看看您的瓶颈在哪里。在我的项目因 100% CPU 而疯狂之后,这实际上帮助我让 xcode 再次达到合理的速度。在将代码复制回来时,您可以对其进行重构并尝试保持函数体简短且函数/公式/表达式简单(或分成几行)。
【讨论】:
非常彻底的答案。也许其中一些建议作为“急救”很棒,但实际上,我们不希望 Xcode 能够简单地工作而无需经历巨大的麻烦吗? 不幸的是,xcode 6.1 + swift 非常不稳定,因此需要这些“hacks”。苹果应该修复 swift 和 xcode。但是 swift 非常适合编程,所以在短期内这是控制 CPU 使用率的唯一方法。 我做了你提出的所有可能的改变,但不幸的是我的自动完成仍然很糟糕。我怀疑 if 子句的速记也会造成麻烦。有人能承认吗?我的意思是返回 (a == b) ? x : y 好吧,以某种方式编写代码让 IDE 快乐是真正的废话【参考方案3】:自 Xcode 4 以来自动完成功能被破坏。在 Apple 决定修复这个 2 年前的错误之前,不幸的是,唯一的解决方案是在 XCode 的首选项上关闭代码完成功能(下图的第一个选项)。
您可以在需要时通过键入CTRL space
或ESC
继续享受手动完成的乐趣。
这是唯一一个每次都适用于 100% 情况的解决方案。
我最近发现的另一件事是:如果您在 Xcode 上使用插件,请不要。将它们全部删除。它们使问题变得更糟。
【讨论】:
【参考方案4】:您在使用 Spotify 吗? 我在 2009 年中期 (2.66Ghz) 上安装了带有 Xcode 6.1 GM 的 Yosemite GM spotify,现在 Xcode 似乎运行得更好了。
【讨论】:
很有趣,但对我来说,它与 Spotify 无关……但它确实表明这可能只是一个“常见的”性能问题 - 意思是 - 清除更多资源并且它会更好地工作。这很可悲,因为我没有更多的资源可以提供(除了新 Mac 上的钱)。【参考方案5】:我发现这通常发生在你:
在单个语句中包含长表达式(请参阅this answer) 在一个表达式中混合使用多个自定义运算符第二种情况似乎已在最新的 xcode 版本之一中得到修复。示例:我定义了 2 个自定义运算符 和 ,并用于像 a <&&> b <&&> c <||> d
这样的表达式。拆分为多行解决了这个问题:
let r1 = a <&&> b
let r2 = r1 <&&> c
let r3 = r2 <||> d
我希望上述两种情况之一涵盖您的情况...请在任一情况下发表评论
【讨论】:
不幸的是,它也发生在一个全新的干净项目中,其中没有任何内容,并且输入了诸如“var s:Stri ...”之类的简单内容。当我开始输入 St... 时,它会在查找完成建议时变得迟缓。 它绝对是我的操作数。在同一行中有多个操作数会导致它。感谢您的回答。这应该是正确的答案【参考方案6】:即使在 Xcode 6.3 中我也遇到了同样的问题
超慢自动完成 超慢索引 swift 和 SourceKitService 占用大量 CPU SourceKitService 使用大量内存所有这些都发生在相对较小的项目中。我尝试了所有我能找到的修复:
正在删除 ~/Library/Developer/Xcode/DerivedData/* 正在删除 ~/Library/Caches/com.apple.dt.Xcode/* 从代码中删除所有“+”字符串组合 删除了所有可疑的字典声明这些对我的项目都没有实际帮助。
真正解决我问题的是:
将每个类的每一端放在自己的文件中 将每个扩展都放在自己的文件中 (Class+ExtName.swift) 将“类外快速方法”放在自己的文件中现在我的 CPU 使用率接近于零,内存使用率低,完成速度相当快。
【讨论】:
【参考方案7】:一般来说,将缓存文件夹 (DerivedData) 移动到 SSD 驱动器(特别是在我的情况下 - 连接到 Thunderbolt 出口的外部存储)显着提高了我的 Xcode 性能。编译时间和围绕应用程序的一般疑问大约是 10 次更快.. 还将整个 git 文件夹移动到 SSD,这极大地提高了 git 性能。
【讨论】:
实际上,在最初的问题中,我已经用 SSD 驱动器升级了我的 mac,一切都从它运行,包括。操作系统,但仍然存在问题【参考方案8】:在 XCode 7.2 之前一直很痛苦。
Apple 在 XCode 7.3 中修复了它,现在它就像一个魅力。它超级快速且功能更强大,因为它看起来有点像文件的模糊搜索:您不必实际键入方法/属性的确切开头,它就会出现在命题列表中。
【讨论】:
【参考方案9】:折叠所有方法会有所帮助。
command-alt-shift-left 箭头可以解决问题...
折叠/展开当前方法或结构使用:
折叠:command-alt-左箭头
展开:command-alt-右箭头
【讨论】:
【参考方案10】:SourceKitService
在代码中处理 cmets 也有点笨拙,嵌入式 cmets 也会减慢它的速度。
所以,如果您有能力像这样移除大量嵌入式 cmets:
/*
* comment
/*
* embedded comment
*/
*/
这肯定也有帮助。
注意: 我的 Xcode 7.3.1 (7D1014) 在文件中有大约 700 行带有嵌入式 cmets 的注释时,实际上阻止了我输入任何字母。最初我从.swift
文件中删除了那个块,Xcode 又恢复了活力。我尝试通过删除嵌入的 cmets 部分添加我的 cmets,它仍然比平时慢,但如果没有嵌入的 cmets,它显示出明显更好的性能。
【讨论】:
【参考方案11】:我遇到了同样的问题,即在特定类中打字滞后,结果是
/*
Long
multiline
comments
*/
正在减慢打字速度。
【讨论】:
以上是关于带有 Swift 超慢输入和自动完成功能的 Xcode 6的主要内容,如果未能解决你的问题,请参考以下文章