缓慢的 while 循环。 Swift
Slow while -loop. Swift
我对下面的代码有一些问题。当线路超过 10000 时,应用程序基本上会崩溃,或者至少不会响应或做任何事情。
label.text可以毫无问题地输出整个文本文件。并且将整个 25000 行文件存储在 textArr -array 中没有问题。
但是当尝试对超过 10000 行的文件执行 while 循环时,它不会响应。
有什么解决办法的建议吗? :-)
let path = NSBundle.mainBundle().pathForResource("thefile", ofType: "log")
var text = String(contentsOfFile: path!, encoding: NSUTF8StringEncoding, error: nil)!
var textArr = text.componentsSeparatedByString("\r\n")
var lines = textArr.count
var user_event=1
var user_state=1
var user_info=1
var user_devcom=1
var user_warning=1
var user_io=1
var user_useract=1
var user_error=1
class ViewController2: UIViewController {
override func viewDidLoad() {
label.font = UIFont(name: label.font.fontName, size: 8)
super.viewDidLoad()
var n=0
while n < lines{
var rad: String = textArr[n]
if user_event == 1{
if rad.lowercaseString.rangeOfString(" event ") != nil{
label.text = "\(label.text!)\(rad)"
label.text! += "\r\r"
}
}
if user_state == 1{
if rad.lowercaseString.rangeOfString(" state ") != nil{
label.text = "\(label.text!)\(rad)"
label.text! += "\r\r"
}
}
if user_info == 1{
if rad.lowercaseString.rangeOfString(" info ") != nil{
label.text = "\(label.text!)\(rad)"
label.text! += "\r\r"
}
}
if user_devcom == 1{
if rad.lowercaseString.rangeOfString(" devcom ") != nil{
label.text = "\(label.text!)\(rad)"
label.text! += "\r\r"
}
}
if user_warning == 1{
if rad.lowercaseString.rangeOfString(" warning ") != nil{
label.text = "\(label.text!)\(rad)"
label.text! += "\r\r"
}
}
if user_io == 1{
if rad.lowercaseString.rangeOfString(" io ") != nil{
label.text = "\(label.text!)\(rad)"
label.text! += "\r\r"
}
}
if user_useract == 1{
if rad.lowercaseString.rangeOfString(" useract") != nil{
label.text = "\(label.text!)\(rad)"
label.text! += "\r\r"
}
}
if user_error == 1{
if rad.lowercaseString.rangeOfString(" error ") != nil{
label.text = "\(label.text!)\(rad)"
label.text! += "\r\r"
}
}
n=n+1
}
}
您的应用没有响应,因为它在主线程上做了很多工作(尤其是您的非最佳字符串处理和 lots 的 属性 访问是可能是主要瓶颈)。你应该尝试offload that into a background thread。请注意,您需要在主线程上分配 UILabel
的 text
属性!因此,在变量中构建字符串,并在完成处理后将其分配给主线程上的 text
属性。
此外,许多自动释放的对象已创建,并且在您从 viewDidLoad
返回后的某个时间才会被释放。您应该添加一个每次迭代都清空的自动释放池,如下所示:
while n < lines {
autoreleasepool {
// Insert your "while" body here.
}
}
最后但同样重要的是,由于 while
中的最后一条语句是 n=n+1
,您应该改用 for
循环:
for n in 0..<lines {
autoreleasepool {
// Insert your former "while" body here.
}
}
使用 NSMutableString 处理流程看起来像这样:
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {
// Background thread. Do NOT access your label here!
let string = NSMutableString()
for n in 0..<lines {
autoreleasepool {
let rad: String = textArr[n]
if user_event == 1 {
if rad.lowercaseString.rangeOfString(" event ") != nil {
string.appendString(rad)
string.appendString("\r\r")
}
}
// ...
}
}
dispatch_async(dispatch_get_main_queue()) {
// Update label on main thread.
label.text = string
}
}
我对下面的代码有一些问题。当线路超过 10000 时,应用程序基本上会崩溃,或者至少不会响应或做任何事情。
label.text可以毫无问题地输出整个文本文件。并且将整个 25000 行文件存储在 textArr -array 中没有问题。
但是当尝试对超过 10000 行的文件执行 while 循环时,它不会响应。
有什么解决办法的建议吗? :-)
let path = NSBundle.mainBundle().pathForResource("thefile", ofType: "log")
var text = String(contentsOfFile: path!, encoding: NSUTF8StringEncoding, error: nil)!
var textArr = text.componentsSeparatedByString("\r\n")
var lines = textArr.count
var user_event=1
var user_state=1
var user_info=1
var user_devcom=1
var user_warning=1
var user_io=1
var user_useract=1
var user_error=1
class ViewController2: UIViewController {
override func viewDidLoad() {
label.font = UIFont(name: label.font.fontName, size: 8)
super.viewDidLoad()
var n=0
while n < lines{
var rad: String = textArr[n]
if user_event == 1{
if rad.lowercaseString.rangeOfString(" event ") != nil{
label.text = "\(label.text!)\(rad)"
label.text! += "\r\r"
}
}
if user_state == 1{
if rad.lowercaseString.rangeOfString(" state ") != nil{
label.text = "\(label.text!)\(rad)"
label.text! += "\r\r"
}
}
if user_info == 1{
if rad.lowercaseString.rangeOfString(" info ") != nil{
label.text = "\(label.text!)\(rad)"
label.text! += "\r\r"
}
}
if user_devcom == 1{
if rad.lowercaseString.rangeOfString(" devcom ") != nil{
label.text = "\(label.text!)\(rad)"
label.text! += "\r\r"
}
}
if user_warning == 1{
if rad.lowercaseString.rangeOfString(" warning ") != nil{
label.text = "\(label.text!)\(rad)"
label.text! += "\r\r"
}
}
if user_io == 1{
if rad.lowercaseString.rangeOfString(" io ") != nil{
label.text = "\(label.text!)\(rad)"
label.text! += "\r\r"
}
}
if user_useract == 1{
if rad.lowercaseString.rangeOfString(" useract") != nil{
label.text = "\(label.text!)\(rad)"
label.text! += "\r\r"
}
}
if user_error == 1{
if rad.lowercaseString.rangeOfString(" error ") != nil{
label.text = "\(label.text!)\(rad)"
label.text! += "\r\r"
}
}
n=n+1
}
}
您的应用没有响应,因为它在主线程上做了很多工作(尤其是您的非最佳字符串处理和 lots 的 属性 访问是可能是主要瓶颈)。你应该尝试offload that into a background thread。请注意,您需要在主线程上分配 UILabel
的 text
属性!因此,在变量中构建字符串,并在完成处理后将其分配给主线程上的 text
属性。
此外,许多自动释放的对象已创建,并且在您从 viewDidLoad
返回后的某个时间才会被释放。您应该添加一个每次迭代都清空的自动释放池,如下所示:
while n < lines {
autoreleasepool {
// Insert your "while" body here.
}
}
最后但同样重要的是,由于 while
中的最后一条语句是 n=n+1
,您应该改用 for
循环:
for n in 0..<lines {
autoreleasepool {
// Insert your former "while" body here.
}
}
使用 NSMutableString 处理流程看起来像这样:
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {
// Background thread. Do NOT access your label here!
let string = NSMutableString()
for n in 0..<lines {
autoreleasepool {
let rad: String = textArr[n]
if user_event == 1 {
if rad.lowercaseString.rangeOfString(" event ") != nil {
string.appendString(rad)
string.appendString("\r\r")
}
}
// ...
}
}
dispatch_async(dispatch_get_main_queue()) {
// Update label on main thread.
label.text = string
}
}