คลอเชอร์ที่หลุดออกนอกขอบเขต
จัดเก็บคลอเชอร์ที่มีอายุยืนกว่าฟังก์ชันของตน
คลอเชอร์ที่หลุดออกนอกขอบเขต เป็นบทเรียน Swift Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Swift Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน
Escaping เทียบกับ Non-Escaping
โดยค่าเริ่มต้น พารามิเตอร์ closure จะเป็นแบบ non-escaping ซึ่งหมายความว่าต้องเรียกใช้ก่อนฟังก์ชันคืนค่า ให้ระบุ @escaping หาก closure อาจถูกเก็บไว้และเรียกใช้ภายหลัง
Closure แบบ Non-Escaping
closure นี้ทำงานแบบพร้อมกันและจะหายไปเมื่อฟังก์ชันคืนค่า:
func run(_ work: () -> Void) {
work()
}
run { print("done now") } // "done now"เหตุใดจึงต้องใช้ @escaping
การเก็บ closure ไว้ใช้ภายหลังจำเป็นต้องใช้ @escaping:
var handlers: [() -> Void] = []
func register(_ handler: @escaping () -> Void) {
handlers.append(handler) // escapes the function
}
register { print("later") }
handlers[0]() // "later"Escaping กับงานแบบไม่พร้อมกัน
completion handlers จะหลุดออกนอกขอบเขต เพราะทำงานหลังจากฟังก์ชันคืนค่าแล้ว:
func load(then completion: @escaping (String) -> Void) {
// imagine async work
completion("data")
}
load { result in print(result) } // "data"ต้องระบุ self อย่างชัดเจน
ภายใน closure แบบ escaping คุณต้องเขียน self. อย่างชัดเจนเมื่อเข้าถึงสมาชิกของ instance — เพื่อเตือนว่า closure อาจเก็บ self ไว้
การระบุ self อย่างชัดเจนใน Escaping
คอมไพเลอร์กำหนดให้ต้องมีการอ้างอิงอย่างชัดเจน:
class Loader {
var name = "L"
func start(_ done: @escaping () -> Void) {
let cb = { print(self.name); done() }
cb()
}
}
Loader().start { print("finished") } // "L" then "finished"การเก็บ Callback หลายรายการ
closures แบบ escaping ช่วยให้คุณสร้างรายการผู้สังเกตการณ์ได้:
class Emitter {
private var listeners: [(Int) -> Void] = []
func on(_ l: @escaping (Int) -> Void) { listeners.append(l) }
func fire(_ v: Int) { listeners.forEach { $0(v) } }
}
let e = Emitter()
e.on { print("got \($0)") }
e.fire(7) // "got 7"การคืนค่า Closure ที่เก็บไว้
closures ที่เก็บไว้ใน property จะเป็นแบบ escaping:
class Button {
var action: (() -> Void)?
func setAction(_ a: @escaping () -> Void) { action = a }
}
let b = Button()
b.setAction { print("tapped") }
b.action?() // "tapped"Closure ทางเลือกเป็น Escaping
พารามิเตอร์ closure แบบทางเลือกจะเป็น escaping โดยปริยาย (เพราะถูกห่ออยู่ใน Optional) จึงสามารถจัดเก็บไว้ได้:
func maybe(_ f: (() -> Void)?) {
f?()
}
maybe { print("ran") } // "ran"การส่ง Escaping เข้าอาร์เรย์ของงาน
คิวของงานที่เลื่อนเวลาไว้เป็นกรณีใช้งานแบบ escaping ที่พบได้ทั่วไป — closure แต่ละตัวจะถูกเก็บไว้ แล้วจึงเรียกใช้ภายหลัง:
var tasks: [() -> Int] = []
func schedule(_ task: @escaping () -> Int) {
tasks.append(task)
}
schedule { 1 + 1 }
schedule { 10 * 2 }
print(tasks.map { $0() }) // [2, 20]หมายเหตุด้านประสิทธิภาพ
closures แบบ non-escaping สามารถปรับประสิทธิภาพได้มากกว่า (ไม่จำเป็นต้องจัดสรรหน่วยความจำบน heap) ให้ closures เป็นแบบ non-escaping เมื่อทำได้ และใช้ escaping เฉพาะเมื่อคุณเก็บหรือเลื่อนเวลาไว้จริง ๆ
func sum(_ xs: [Int], _ f: (Int) -> Int) -> Int {
xs.reduce(0) { $0 + f($1) } // non-escaping, fast
}
print(sum([1, 2, 3]) { $0 * $0 }) // 14ตรวจสอบอย่างรวดเร็ว
เมื่อใดจึงต้องระบุพารามิเตอร์ closure ด้วย @escaping
สรุป
คุณได้เรียนรู้เกี่ยวกับ closures แบบ escaping:
- แบบ non-escaping เป็นค่าเริ่มต้น โดย closures จะทำงานก่อนฟังก์ชันคืนค่า
- ต้องใช้
@escapingเพื่อจัดเก็บหรือเลื่อนเวลา closure - closures แบบ escaping ต้องเข้าถึง
self.อย่างชัดเจน - พารามิเตอร์ closure แบบทางเลือกจะเป็น escaping โดยปริยาย ควรเลือกแบบ non-escaping เพื่อความเร็ว
ถัดไป: รายการจับและ weak self
เรียนรู้ Swift ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 122
- บทเรียน
- 409
คำถามที่พบบ่อย
บทเรียน “คลอเชอร์ที่หลุดออกนอกขอบเขต” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “คลอเชอร์ที่หลุดออกนอกขอบเขต” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Swift Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “คลอเชอร์ที่หลุดออกนอกขอบเขต”
จัดเก็บคลอเชอร์ที่มีอายุยืนกว่าฟังก์ชันของตน คุณปฏิบัติ Swift Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Swift Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Swift Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “คลอเชอร์ที่หลุดออกนอกขอบเขต” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Swift Academy นี้ได้ไหม
ได้ บทเรียน Swift Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การจับค่าด้วยการอ้างอิง
- คลอเชอร์ที่หลุดออกนอกขอบเขต
- รายการจับค่าและ weak self
- Autoclosures