Ich verwende Completion-Blöcke für jede meiner Funktionen (um zu vermeiden, eine while isDoingSomething-Schleife zu verwenden).Swift 2 OSX Wie verwende ich eine Schleife am Ende einer Reihe von Vervollständigungen, die eine Datenaufgabe enthält?
Ich bekomme das erwartete Array, wenn alle Blöcke abgeschlossen sind. Wenn ich jedoch versuche, dieses letzte Array zu durchlaufen, wird es wie erwartet fortlaufend durchlaufen, ohne jedoch die NSURLSessionDataTask
in Request.sendRequest(..)
für jede Iteration fortzusetzen.
ViewController.swift
import Cocoa
class ViewController: NSViewController {
@IBOutlet weak var runButton: NSButton!
@IBOutlet weak var visitsTextField: NSTextField!
var accessToken = ""
var cookies = [NSHTTPCookie]()
var data = NSData?()
var userIds = [String]()
var usernames = [String]()
var contentsOfURL = NSString()
@IBAction func runButtonAction(sender: AnyObject) {
run({
// if I remove the loop and visit only one profile, it completes OK
for username in self.usernames {
let profileVisitor = ProfileVisitor(profile: username)
profileVisitor.visit({
})
}
})
}
func run(completion:() -> Void) {
let runManager = RunManager(desiredVisits: Int(visitsTextField.stringValue)!)
runManager.parseJSON({
self.usernames = runManager.usernames
completion()
})
}
}
RunManger.swift
import Cocoa
class RunManager: NSObject {
var data = NSData?()
var desiredVisits = Int()
var usernames = [String]()
var userIds = [String]()
init(desiredVisits: Int) {
self.desiredVisits = desiredVisits
}
func parseJSON(completion:() -> Void) {
let jsonLimit = 40
var profileNames = [String]()
let finalVisits = desiredVisits % jsonLimit
let repeats = (desiredVisits/jsonLimit) + 1
let json: [String:NSObject] = [..., "limit":jsonLimit]
let url = "https://www.awebsite.com/1/path1/path2/path3"
let URL = NSURL(string: url)!
let vis = URLVisitor(URL: URL, params: "", method: "POST", jsonParams: json as! [String : NSObject])
vis.execute({
for i in 1..<repeats {
if vis.data != nil {
do {
let data = vis.data!
let json = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
if let _usernames = json["data"] as? [[String: AnyObject]] {
for username in _usernames {
if let username = username["username"] as? String {
self.usernames.append(username)
}
}
}
} catch {
}
}
}
completion()
})
}
}
URLVisitor
import Cocoa
class URLVisitor: NSOperation {
var authorizationHeader = ""
var contentsOfURL = NSString()
var jsonParams = [String: NSObject]()
var isConnected = false
var method = String()
var params = String()
var statusCode = Int()
var cookies = [NSHTTPCookie]()
var URL: NSURL?
var isVisiting = false
var task = NSURLSessionDataTask()
var data = NSData?()
init(URL: NSURL, params: String, method: String, jsonParams: [String:NSObject]) {
self.URL = URL
self.params = params
self.method = method
self.jsonParams = jsonParams
}
func execute(completion:() -> Void) {
let request = Request(URL: URL!, params: params, method: method, jsonParams: jsonParams)
if !self.cookies.isEmpty {
request._setCookies(self.cookies)
}
request._setAuthorizationHeader(self.authorizationHeader)
request.sendRequest ({
self.contentsOfURL = request.contentsOfURL
self.statusCode = request.getStatusCode()
self.data = request.data
completion()
})
}
}
Anfrage
import Cocoa
class Request: NSOperation {
var authorizationHeader = ""
var contentsOfURL = NSString()
var data: NSData?
var jsonParams = [String:NSObject]()
var isConnected = false
var method = String()
var params = String()
var statusCode = NSHTTPURLResponse().statusCode
var session = NSURLSession.sharedSession()
var url = String()
var URL = NSURL()
var cookies = [NSHTTPCookie]()
init(URL: NSURL, params: String, method: String, jsonParams: [String:NSObject]) {
self.jsonParams = jsonParams
self.method = method
self.params = params
self.URL = URL
}
func sendRequest(completion:() -> Void) {
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: URL)
request.HTTPMethod = method
if jsonParams.count != 0 {
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(jsonParams, options: .PrettyPrinted)
request.setValue("aplication/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.HTTPBody = jsonData
} catch {
}
} else {
request.HTTPBody = self.params.dataUsingEncoding(NSUTF8StringEncoding)
}
let task = session.dataTaskWithRequest(request) {
(data, response, error) in
NSHTTPCookieStorage.sharedHTTPCookieStorage().setCookies(self.cookies, forURL: self.URL, mainDocumentURL: nil)
if data != nil {
self.data = data!
print(data)
do {
swiftlet responseHeaders = response as! NSHTTPURLResponse
self.statusCode = responseHeaders.statusCode
switch self.statusCode {
case 200:
print("200: OK. getting contentsOfURL and cookies")
self.contentsOfURL = try NSString(contentsOfURL: self.URL, encoding: NSUTF8StringEncoding)
self.cookies = NSHTTPCookieStorage.sharedHTTPCookieStorage().cookiesForURL(self.URL)!
case 400:
print("400: page not found on web")
case 404:
print("404: page not found on server")
case 407:
print("407: failed authenticate proxy credentials")
default:
print("unable to get statusCode")
}
} catch {
}
} else {
print("\(self.statusCode): unable to get response ")
}
print("completing")
completion() // continue inside request call
}
task.resume()
}
func _setAuthorizationHeader(authorizationHeader: String) {
self.authorizationHeader = authorizationHeader
}
func _setCookies(cookies: [NSHTTPCookie]) {
self.cookies = cookies
}
func getStatusCode() -> Int {
return self.statusCode
}
func getContentsOfURL() -> NSString {
return self.contentsOfURL
}
}