In meinem Projekt für OS X Befehlszeilentool mit Swift 3.0 (Beta 2) muss ich HTML-Daten in String aus mehreren URLs konvertieren. Es gibt ein Problem bei der Verwendung einer solchen Funktion mit vielen Hintergrundaufgaben (es funktioniert nicht, außer dem Hauptthread, also gibt es vielleicht elegantere Möglichkeiten, den Abschluss aller Aufgaben zu kontrollieren und HTML-Daten in einem solchen Tool mit oder ohne Parser zu lesen, die ich brauche Swift 3 und Mac OS X (Linux in naher Zukunft)):URLSession im Befehlszeilentool: mehrere Aufgaben steuern und HTML in Text konvertieren
func html2text (html: String, usedEncoding: String.Encoding) -> String {
let data = html.data(using: usedEncoding)!
if let htmlString = AttributedString(html: data, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: usedEncoding.rawValue], documentAttributes: nil)?.string {
return htmlString
} else {
return ""
}
}
Also lese ich Daten zunächst in ein Array warten, wenn alle DataTasks fertig und dann im Hauptthread zu konvertieren. Verwendung auch globale Variable (Set von Urls) Abschluss jeder Aufgabe zu steuern:
import Foundation
import WebKit
var urlArr = [String]()
var urlSet = Set<String>()
var htmlTup : [(url : String, html : String, encoding : String.Encoding)] = []
let session = URLSession.shared
For-in-Schleife mit mehreren URLSession DataTasks
for myurl in urlArr {
if urlSet.insert(myurl).inserted {
print ("Loading \(myurl)...")
let inputURL = URL(string: myurl)!
let task = session.dataTask(with: inputURL, completionHandler: {mydata, response, error in
lesen Kodierung von HTML Erste
var usedEncoding = String.Encoding.utf8
if let encodingName = response!.textEncodingName {
let encoding = CFStringConvertIANACharSetNameToEncoding(encodingName)
if encoding != kCFStringEncodingInvalidId {
usedEncoding = String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(encoding))
}
}
Arbeiten Sie mit HTML String und lesen Sie Daten in ein Array
if let myString = String(data: mydata!, encoding: usedEncoding) {
htmlTup += [(url: myurl,html: myString, encoding: usedEncoding)]
}
// The end of task removing URL from Set
urlSet.remove(myurl)
})
//Run Task
task.resume()
}
}
}
Warten auf Aufgaben HTML zu vervollständigen und konvertieren
while !urlSet.isEmpty {
// Do nothing
}
for (url,html,encoding) in htmlTup {
print ("Writing data from \(url)...")
print (html2text(html: html, usedEncoding: encoding))
}
Update 1 in Text: Runloop im Hauptthread von this Ein solcher Code zu überprüfen, wenn jede Aufgabe beendet:
var taskArr = [Bool]()
let task = session.dataTask(with: request) { (data, response, error) in
}
taskArr.removeLast()
}
taskArr.append(true)
task.resume()
// Waiting for tasks to complete
let theRL = RunLoop.current
while !taskArr.isEmpty && theRL.run(mode: .defaultRunLoopMode, before: .distantFuture) { }
Vielen Dank, ich brauche mehr Verständnis dafür, wie die Dinge funktionieren –