سؤال

تم تنفيذ العديد من طرق الكاكاو والكوكواتوش ككتل في الهدف جيم والإغلاق في سويفت.ومع ذلك ، عند تجربة هذه الأشياء في الملعب ، لا يتم استدعاء الإكمال أبدا.على سبيل المثال:

// Playground - noun: a place where people can play

import Cocoa
import XCPlayground

let url = NSURL(string: "http://stackoverflow.com")
let request = NSURLRequest(URL: url)

NSURLConnection.sendAsynchronousRequest(request, queue:NSOperationQueue.currentQueue() {
response, maybeData, error in

    // This block never gets called?
    if let data = maybeData {
        let contents = NSString(data:data, encoding:NSUTF8StringEncoding)
        println(contents)
    } else {
        println(error.localizedDescription)
    }
}

أستطيع أن أرى إخراج وحدة التحكم في الجدول الزمني للملعب الخاص بي ، ولكن println في كتلة الانتهاء الخاصة بي لا تسمى أبدا...

هل كانت مفيدة؟

المحلول

بينما يمكنك تشغيل حلقة تشغيل يدويا (أو ، بالنسبة للرمز غير المتزامن الذي لا يتطلب حلقة تشغيل ، استخدم طرق انتظار أخرى مثل إشارات الإرسال) ، فإن الطريقة "المضمنة" التي نقدمها في الملاعب لانتظار العمل غير المتزامن هي استيراد XCPlayground الإطار والمجموعة XCPlaygroundPage.currentPage.needsIndefiniteExecution = true.إذا تم تعيين هذه الخاصية ، عند انتهاء مصدر ملعب المستوى الأعلى ، فبدلا من إيقاف الملعب هناك ، سنستمر في تدوير حلقة التشغيل الرئيسية ، لذلك فإن الكود غير المتزامن لديه فرصة للتشغيل.سنقوم في النهاية بإنهاء الملعب بعد مهلة يتم تعيينها افتراضيا على 30 ثانية ، ولكن يمكن تهيئتها إذا فتحت محرر المساعد وأظهرت مساعد المخطط الزمني;المهلة في أسفل اليمين.

على سبيل المثال ، في سويفت 3 (باستخدام URLSession بدلا من NSURLConnection):

import UIKit
import PlaygroundSupport

let url = URL(string: "http://stackoverflow.com")!

URLSession.shared.dataTask(with: url) { data, response, error in
    guard let data = data, error == nil else {
        print(error ?? "Unknown error")
        return
    }

    let contents = String(data: data, encoding: .utf8)
    print(contents!)
}.resume()

PlaygroundPage.current.needsIndefiniteExecution = true

أو في سويفت 2:

import UIKit
import XCPlayground

let url = NSURL(string: "http://stackoverflow.com")
let request = NSURLRequest(URL: url!)

NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.currentQueue()) { response, maybeData, error in
    if let data = maybeData {
        let contents = NSString(data:data, encoding:NSUTF8StringEncoding)
        println(contents)
    } else {
        println(error.localizedDescription)
    }
}

XCPlaygroundPage.currentPage.needsIndefiniteExecution = true

نصائح أخرى

تغيرت هذه أبي مرة أخرى في كسكودي 8 وتم نقله إلى PlaygroundSupport:

import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true

تم ذكر هذا التغيير في الجلسة 213 في مؤتمر القمة العالمي للتنمية المستدامة 2016.

اعتبارا من كسكودي 7.1, XCPSetExecutionShouldContinueIndefinitely() تم إهماله.الطريقة الصحيحة للقيام بذلك الآن هي أولا طلب التنفيذ لأجل غير مسمى كخاصية للصفحة الحالية:

import XCPlayground

XCPlaygroundPage.currentPage.needsIndefiniteExecution = true

indicate ثم حدد متى انتهى التنفيذ مع:

XCPlaygroundPage.currentPage.finishExecution()

على سبيل المثال:

import Foundation
import XCPlayground

XCPlaygroundPage.currentPage.needsIndefiniteExecution = true

NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: "http://stackoverflow.com")!) {
    result in
    print("Got result: \(result)")
    XCPlaygroundPage.currentPage.finishExecution()
}.resume()

السبب في عدم استدعاء الاستدعاءات هو أن رونلوب لا يعمل في الملعب (أو في وضع ريبل لهذه المسألة).

وهناك طريقة جانكي إلى حد ما ، ولكنها فعالة ، لجعل عمليات الاسترجاعات تعمل مع العلم ومن ثم تكرار يدويا على رونلوب:

// Playground - noun: a place where people can play

import Cocoa
import XCPlayground

let url = NSURL(string: "http://stackoverflow.com")
let request = NSURLRequest(URL: url)

var waiting = true

NSURLConnection.sendAsynchronousRequest(request, queue:NSOperationQueue.currentQueue() {
response, maybeData, error in
    waiting = false
    if let data = maybeData {
        let contents = NSString(data:data, encoding:NSUTF8StringEncoding)
        println(contents)
    } else {
        println(error.localizedDescription)
    }
}

while(waiting) {
    NSRunLoop.currentRunLoop().runMode(NSDefaultRunLoopMode, beforeDate: NSDate())
    usleep(10)
}

غالبا ما تم استخدام هذا النمط في اختبارات الوحدة التي تحتاج إلى اختبار عمليات الاسترجاعات غير المتزامنة ، على سبيل المثال: نمط لقائمة انتظار اختبار الوحدة غير المتزامنة التي تستدعي قائمة الانتظار الرئيسية عند الانتهاء

واجهات برمجة التطبيقات الجديدة كما ل شكود 8 ، سويفت3 و يوس 10 هي,

// import the module
import PlaygroundSupport
// write this at the beginning
PlaygroundPage.current.needsIndefiniteExecution = true
// To finish execution
PlaygroundPage.current.finishExecution()

سويفت 4 ، كسكودي 9.0

import Foundation
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true

let url = URL(string: "https://jsonplaceholder.typicode.com/posts/1")!

let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
    guard error == nil else {
        print(error?.localizedDescription ?? "")
        return
    }

    if let data = data, let contents = String(data: data, encoding: String.Encoding.utf8) {
        print(contents)
    }
}
task.resume()

سويفت 3 ، كسكودي 8 ، دائرة الرقابة الداخلية 10

الحواشي:

أخبر المترجم أن ملف الملعب يتطلب"تنفيذ غير محدد"

إنهاء التنفيذ يدويا عبر مكالمة إلى PlaygroundSupport.current.completeExecution() ضمن معالج الإكمال الخاص بك.

قد واجهت مشاكل مع دليل ذاكرة التخزين المؤقت ولحل هذا سوف تحتاج إلى إعادة إنشاء إيكاش يدويا.المفرد المشترك.

مثال:

import UIKit
import Foundation
import PlaygroundSupport

// resolve path errors
URLCache.shared = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil)

// identify that the current page requires "indefinite execution"
PlaygroundPage.current.needsIndefiniteExecution = true

// encapsulate execution completion
func completeExecution() {
    PlaygroundPage.current.finishExecution()
}

let url = URL(string: "http://i.imgur.com/aWkpX3W.png")

let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
    var image = UIImage(data: data!)

    // complete execution
    completeExecution()
}

task.resume()
NSURLConnection.sendAsynchronousRequest(...)    
NSRunLoop.currentRunLoop().run()
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top