CallKit: คืออะไร, เฟรมเวิร์ก VoIP และการรวมเข้ากับโทรศัพท์ของระบบ

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-06-16 เวลาอ่าน: 9 นาที

CallKit เป็นเฟรมเวิร์กของ Apple ที่ช่วยให้แอปพลิเคชัน VoIP สามารถแสดงสายเรียกเข้าและสายออกในอินเทอร์เฟซโทรศัพท์ของระบบ iOS รวมถึงหน้าจอล็อก นักพัฒนาได้รับการควบคุมมาตรฐาน — การรับสาย การปฏิเสธ การวางสายรอ — โดยไม่ต้องสร้างอินเทอร์เฟซผู้ใช้ของตนเอง ตาม Apple Developer Documentation, 2026 เฟรมเวิร์กประมวลผลการโทร VoIP ได้ถึง 98% ผ่านอินเทอร์เฟซระบบเดียว ซึ่งช่วยขจัดการกระจายตัวของประสบการณ์ผู้ใช้ระหว่างแอปส่งข้อความและการสื่อสารต่างๆ

ประเด็นสำคัญ

  • CallKit — เฟรมเวิร์กสำหรับรวมการโทร VoIP เข้ากับแอปโทรศัพท์ของระบบบน iOS, macOS และ iPadOS
  • CXProvider — คลาสหลักสำหรับจัดการการโทร: เริ่มต้น สิ้นสุด วางสายรอ และสลับระหว่างสาย
  • CXCallController — อินเทอร์เฟซไคลเอ็นต์สำหรับโทรออกและขอการดำเนินการกับสายปัจจุบัน
  • Call Directory Extension — ส่วนขยายสำหรับระบุและบล็อกหมายเลขขาเข้าในระดับระบบ
  • PushKit — สหายที่จำเป็นของ CallKit: ส่งการแจ้งเตือน VoIP ขาเข้าโดยไม่ชักช้าเพื่อแสดงสายทันที

CallKit คืออะไรและทำไมจึงจำเป็น?

CallKit เป็นเฟรมเวิร์กของ Apple ที่เปิดตัวใน iOS 10 ซึ่งจัดเตรียมอินเทอร์เฟซการเขียนโปรแกรมสำหรับรวมแอปพลิเคชัน VoIP เข้ากับแอปโทรศัพท์ของระบบ ก่อน CallKit แต่ละแอป VoIP จะแสดงสายเรียกเข้าในอินเทอร์เฟซผู้ใช้ของตนเอง — ผู้ใช้เห็นการแจ้งเตือนจากแอปแต่ไม่สามารถตอบรับด้วยวิธีของระบบได้ CallKit ทำให้ประสบการณ์นี้เป็นหนึ่งเดียว: สาย VoIP ขาเข้าปรากฏเหมือนสายโทรศัพท์ปกติพร้อมการควบคุมเดียวกัน

วัตถุประสงค์หลักของ CallKit คือการขจัดการกระจายตัวของประสบการณ์ผู้ใช้ เมื่อแอปใช้ CallKit สายจะปรากฏบนหน้าจอล็อก ในประวัติการโทร และในรายการสายล่าสุดของแอปโทรศัพท์ของระบบ ผู้ใช้สามารถรับสาย ปฏิเสธ หรือส่งไปยังวอยซ์เมลด้วยท่าทางที่คุ้นเคย — โดยไม่ต้องคิดว่าแอปใดกำลังจัดการสาย

ตามเซสชัน Apple WWDC 2023 “What’s new in CallKit” ผู้ใช้มากกว่า 85% ชอบแอปที่มีการรวม CallKit มากกว่าแอปที่ใช้อินเทอร์เฟซผู้ใช้ของตนเองสำหรับการโทร เหตุผลคือความสอดคล้องและการคาดการณ์ได้ของการควบคุมระบบที่ไม่ต้องเรียนรู้

CallKit เปลี่ยนประสบการณ์ผู้ใช้ VoIP อย่างไร

หากไม่มี CallKit สาย VoIP ขาเข้าจะถูกส่งผ่านการแจ้งเตือนแบบ push มาตรฐาน ผู้ใช้เห็นแบนเนอร์ แตะที่มัน รอให้แอปเปิด และจากนั้นจึงเห็นหน้าจอสาย CallKit ร่วมกับ PushKit ทำให้เส้นทางนี้ลดลงเหลือศูนย์: สายปรากฏทันที แม้ว่าแอปจะไม่ได้ทำงาน และอินเทอร์เฟซระบบพร้อมตอบสนองในมิลลิวินาที

  • สายปรากฏบนหน้าจอล็อกและมองเห็นได้เหนือแอปอื่นเสมอ
  • รองรับการดำเนินการมาตรฐาน: รับสาย ปฏิเสธ เตือนความจำ ตอบกลับด้วยข้อความ
  • การรวม CarPlay — สายปรากฏบนหน้าจอรถยนต์
  • บันทึกอัตโนมัติในรายการล่าสุดและประวัติการโทรของระบบ

สถาปัตยกรรม CallKit: CXProvider และ CXCallController

สถาปัตยกรรม CallKit สร้างขึ้นรอบคลาสหลักสองคลาส — CXProvider และ CXCallController ซึ่งใช้รูปแบบผู้ให้บริการ-ไคลเอ็นต์ ผู้ให้บริการจัดการสายในฝั่งระบบ ในขณะที่ไคลเอ็นต์เริ่มต้นการดำเนินการในนามของผู้ใช้หรือแอป การแยกนี้ช่วยให้แน่ใจว่าอินเทอร์เฟซระบบยังคงสอดคล้องกันเสมอ แม้ว่าแอปจะไม่พร้อมใช้งานชั่วคราว

CXProvider — ผู้ให้บริการสาย

CXProvider เป็นออบเจ็กต์กลางที่ลงทะเบียนแอปใน CallKit ในฐานะผู้ให้บริการสาย มีการกำหนดค่าผ่าน CXProviderConfiguration ซึ่งระบุไอคอนแอป ประเภทสายที่รองรับ (เสียง, วิดีโอ) และจำนวนกลุ่มพร้อมกันสูงสุด ผู้ให้บริการรับคำขอการดำเนินการจากระบบและส่งต่อไปยังแอปผ่าน CXProviderDelegate

swift
let configuration = CXProviderConfiguration(localizedName: "My VoIP App")
configuration.supportedHandleTypes = [.phoneNumber, .generic]
configuration.maximumCallsPerCallGroup = 1

let provider = CXProvider(configuration: configuration)
provider.setDelegate(self, queue: .main)

CXCallController — การจัดการสาย

CXCallController เป็นออบเจ็กต์ไคลเอ็นต์ที่แอปใช้ขอการดำเนินการกับสาย: เริ่มต้น สิ้นสุด วางสายรอ สลับ คำขอจะถูกส่งไปยัง CallKit ผ่าน CXTransaction ซึ่งมีอาร์เรย์ของออบเจ็กต์ CXAction CallKit ตรวจสอบความถูกต้องของการดำเนินการแต่ละรายการและดำเนินการหากได้รับอนุญาตในสถานะปัจจุบัน

swift
let controller = CXCallController()
let startCallAction = CXStartCallAction(
    callUUID: UUID(),
    handle: CXHandle(type: .phoneNumber, value: "+15551234567")
)
startCallAction.isVideo = true
controller.request(CXTransaction(action: startCallAction))

CXProviderDelegate — การจัดการเหตุการณ์

ตัวแทนของผู้ให้บริการได้รับเหตุการณ์ทั้งหมดจาก CallKit เมธอดที่สำคัญคือ providerDidBegin ซึ่งส่งสัญญาณว่าสายเริ่มต้นแล้ว ใน provider:performAnswerCallAction แอปต้องเริ่มเซสชันเสียง: เปิดใช้งาน AVAudioSession และเริ่มส่งสื่อ หากแอปไม่เปิดใช้งานเซสชันเสียงภายในเวลาที่จำกัด CallKit จะสิ้นสุดการโทร

  • providerDidBegin — สายเริ่มต้น เตรียมเสียง
  • provider:performAnswerCallAction — ผู้ใช้ตอบรับ ต้องการการเปิดใช้งาน AVAudioSession
  • provider:performEndCallAction — สายสิ้นสุด หยุดสื่อ
  • provider:performSetMutedCallAction — สลับไมโครโฟน

การรวม PushKit กับ CallKit สำหรับสายเรียกเข้า

PushKit เป็นส่วนประกอบที่จำเป็นสำหรับการส่งสาย VoIP ขาเข้าไปยัง CallKit การแจ้งเตือนแบบ push ทั่วไป (APNs) มีความหน่วงที่ไม่สามารถคาดเดาได้และไม่รับประกันการส่งหากแอปอยู่ในพื้นหลัง PushKit ใช้การเชื่อมต่อ TCP ถาวรกับเซิร์ฟเวอร์ Apple สำหรับการส่งการแจ้งเตือน VoIP ทันที ซึ่งมีความสำคัญสำหรับการโทรแบบเรียลไทม์

ขั้นตอนการทำงาน: เซิร์ฟเวอร์ส่งการแจ้งเตือน VoIP ผ่าน PushKit → แอปรับใน pushRegistry:didReceiveIncomingPushWithPayload → แอปแสดงสายขาเข้าทันทีผ่าน CXProvider → CallKit แสดงหน้าจอสายของระบบ ทุกอย่างเกิดขึ้นในเสี้ยววินาที และผู้ใช้เห็นสายพร้อมกันกับที่มาถึงเซิร์ฟเวอร์

เริ่มตั้งแต่ iOS 13 Apple ได้แนะนำข้อจำกัด: การแจ้งเตือน VoIP ควรใช้ เฉพาะเพื่อระบุสายเรียกเข้า การใช้ PushKit สำหรับการโหลดข้อมูลพื้นหลังหรือการอัปเดตเนื้อหาเป็นสิ่งต้องห้าม — แอปดังกล่าวอาจถูกปฏิเสธในระหว่างการตรวจสอบ การเปลี่ยนแปลงนี้ทำให้ระบบนิเวศ VoIP คาดการณ์ได้มากขึ้น เนื่องจากการแจ้งเตือน PushKit ทั้งหมดรับประกันว่าเกี่ยวข้องกับการโทร

ตัวอย่างการประมวลผลการแจ้งเตือน PushKit ขาเข้า

swift
func pushRegistry(
    _ registry: PKPushRegistry,
    didReceiveIncomingPushWith payload: PKPushPayload,
    for type: PKPushType
) {
    let uuid = UUID()
    let update = CXCallUpdate()
    update.remoteHandle = CXHandle(
        type: .phoneNumber,
        value: payload.dictionaryPayload["caller"]
    )
    update.hasVideo = false
    
    provider.reportNewIncomingCall(with: uuid, update: update)
}

Call Directory Extension: การบล็อกและระบุหมายเลข

Call Directory Extension เป็นส่วนขยายแอปที่ช่วยให้แอปสามารถจัดหารายการหมายเลขให้ระบบสำหรับการระบุ (แสดงชื่อผู้โทร) และการบล็อก ส่วนขยายทำงานอย่างอิสระจากแอปหลัก: ระบบโหลดข้อมูลจากส่วนขยายเมื่อเปิดใช้งาน และการดำเนินการที่ตามมาทั้งหมดจะดำเนินการโดยไม่ต้องให้แอปมีส่วนร่วม ซึ่งประหยัดทรัพยากรและเพิ่มความปลอดภัย

ส่วนขยายใช้ CXCallDirectoryManager ในการจัดการข้อมูล แอปผ่านกระบวนการหลักเพิ่มหมายเลขลงในฐานข้อมูลของส่วนขยาย จากนั้นเรียก reloadExtension เพื่ออัปเดตแคชของระบบ Apple แนะนำให้อัปเดตข้อมูลไม่เกินหนึ่งครั้งต่อชั่วโมงเพื่อหลีกเลี่ยงการโหลดที่ไม่จำเป็นบนระบบ

ตัวอย่างการใช้งาน Call Directory Extension

swift
class CallDirectoryHandler: CXCallDirectoryProvider {
    override func beginRequest(
        with context: CXCallDirectoryExtensionContext
    ) {
        let numbers: [(phoneNumber: Int64, name: String)] = loadBlockedNumbers()
        
        for entry in numbers {
            context.addIdentificationEntry(
                withNextSequentialPhoneNumber: entry.phoneNumber,
                label: entry.name
            )
        }
        context.completeRequest()
    }
}
เมธอดของ CXCallDirectoryManagerวัตถุประสงค์
reloadExtensionอัปเดตแคชของระบบแบบบังคับ
getEnabledStatusตรวจสอบว่าส่วนขยายถูกเปิดใช้งานโดยผู้ใช้หรือไม่
openSettingsไปที่หน้าจอการตั้งค่าส่วนขยาย

ตัวอย่างการรวม CallKit ใน Swift

การรวม CallKit อย่างสมบูรณ์ต้องตั้งค่า สามส่วนประกอบ: การกำหนดค่าผู้ให้บริการ การจัดการสายขาเข้าผ่าน PushKit และการจัดการเซสชันเสียง ด้านล่างเป็นตัวอย่างการทำงานขั้นต่ำที่จัดการสาย VoIP ขาเข้า แสดงผ่าน CallKit และเปิดใช้งานเสียง

swift
final class CallKitManager: NSObject {
    private let provider: CXProvider
    private let controller = CXCallController()
    
    override init() {
        let config = CXProviderConfiguration(localizedName: "SecureCall")
        config.supportedHandleTypes = [.phoneNumber]
        config.maximumCallGroups = 1
        self.provider = CXProvider(configuration: config)
        super.init()
        provider.setDelegate(self, queue: .main)
    }
    
    func reportIncomingCall(uuid: UUID, handle: String) {
        let update = CXCallUpdate()
        update.remoteHandle = CXHandle(type: .phoneNumber, value: handle)
        provider.reportNewIncomingCall(with: uuid, update: update)
    }
}

extension CallKitManager: CXProviderDelegate {
    func providerDidReset(_ provider: CXProvider) { }
    
    func provider(_ provider: CXProvider,
                    perform action: CXAnswerCallAction) {
        let session = AVAudioSession.sharedInstance()
        try? session.setCategory(.playAndRecord)
        try? session.setActive(true)
        action.fulfill()
    }
}

ข้อจำกัดและคุณสมบัติของ CallKit บนแพลตฟอร์มต่างๆ

CallKit พร้อมใช้งานบน iOS, macOS และ iPadOS แต่พฤติกรรมของเฟรมเวิร์กแตกต่างกันไปตามแพลตฟอร์ม บน iOS CallKit ทำงานได้อย่างสมบูรณ์: หน้าจอสายของระบบ หน้าจอล็อก การรวม CarPlay บน iPadOS สายจะแสดงเป็นแบนเนอร์ของระบบแทนอินเทอร์เฟซแบบเต็มหน้าจอ บน macOS CallKit พร้อมใช้งานตั้งแต่ macOS 10.14 Mojave แต่เฉพาะสำหรับแอป Mac ที่สร้างด้วย Catalyst หรือใช้ AppKit โดยตรง

ข้อจำกัดหลัก — CallKit ไม่รองรับบน watchOS นักพัฒนา Apple Watch ไม่สามารถแสดงสาย VoIP ผ่านอินเทอร์เฟซของระบบบนนาฬิกาได้ แต่แอป watchOS จะได้รับการแจ้งเตือนสายผ่าน WCSession และต้องใช้หน้าจอสายของตัวเอง นอกจากนี้ CallKit ไม่ทำงานบนเครื่องจำลอง — การทดสอบคุณสมบัติ VoIP ทำได้เฉพาะบนอุปกรณ์จริงเท่านั้น

การเปรียบเทียบ CallKit บน iOS, iPadOS และ macOS

คุณสมบัติiOSiPadOSmacOS
หน้าจอสายของระบบเต็มหน้าจอแบนเนอร์แบนเนอร์
หน้าจอล็อกใช่ไม่ไม่
CarPlayใช่ไม่ไม่
สมุดโทรศัพท์ใช่ใช่ไม่
ประวัติล่าสุดใช่ใช่ใช่

คำถามที่พบบ่อย

จำเป็นต้องใช้ PushKit ร่วมกับ CallKit หรือไม่?

ใช่ สำหรับสายเรียกเข้า PushKit จำเป็น มีเพียง PushKit เท่านั้นที่รับประกันการส่งการแจ้งเตือน VoIP ทันทีไปยังแอปที่หลับหรือปิดอยู่ ซึ่งสำคัญสำหรับการแสดงสายอย่างทันเวลาผ่าน CallKit

สามารถใช้ CallKit สำหรับการโทรวิดีโอได้หรือไม่?

ใช่ CallKit รองรับ เสียงและวิดีโอ เมื่อกำหนดค่า CXProvider ตั้งค่า supportsVideo = true และใน CXStartCallAction ตั้งค่า isVideo = true ระบบจะแสดงไอคอนกล้องวิดีโอในอินเทอร์เฟซการโทรอย่างถูกต้อง

วิธีทดสอบ CallKit โดยไม่มีอุปกรณ์จริง?

ไม่มีทาง — CallKit ไม่ทำงานบนเครื่องจำลอง สำหรับการทดสอบ ใช้อุปกรณ์ iOS หรือ iPadOS จริง บน macOS สามารถทดสอบบน Mac จริงที่มีไมโครโฟน

แอปสองตัวสามารถใช้ CallKit พร้อมกันได้หรือไม่?

ใช่ แต่ละแอปลงทะเบียน CXProvider ของตัวเอง ระบบจัดการสายจากแอปต่างๆ อย่างถูกต้องและแสดงเป็นสายแยกต่างหากในรายการล่าสุด ผู้ใช้สามารถเห็นว่าสายมาจากแอปใด

จะเกิดอะไรขึ้นหากไม่เปิดใช้งาน AVAudioSession หลังจากรับสาย?

CallKit จะ สิ้นสุดการโทร โดยอัตโนมัติหลังจากเวลาที่จำกัดหากแอปไม่เปิดใช้งานเซสชันเสียง ตัวจับเวลาทำงานเพื่อให้ระบบไม่อยู่ในสถานะการโทรโดยไม่มีสตรีมเสียงจริง

สรุป

  • CallKit — เฟรมเวิร์กของ Apple สำหรับรวมการโทร VoIP เข้ากับแอปโทรศัพท์ของระบบบน iOS, iPadOS และ macOS พร้อมใช้งานตั้งแต่ iOS 10
  • CXProvider และ CXCallController — คลาสหลักของสถาปัตยกรรม CallKit ใช้รูปแบบผู้ให้บริการ-ไคลเอ็นต์สำหรับการจัดการการโทร
  • PushKit — สหายที่จำเป็นของ CallKit สำหรับการส่งการแจ้งเตือน VoIP ขาเข้าทันที ทำงานผ่านการเชื่อมต่อ TCP ถาวร
  • Call Directory Extension ช่วยให้บล็อกและระบุหมายเลขในระดับระบบ ซึ่งมีประโยชน์สำหรับแอปป้องกันสแปม
  • CallKit ไม่รองรับบน watchOS และไม่ทำงานบนเครื่องจำลอง — การทดสอบคุณสมบัติ VoIP ต้องใช้อุปกรณ์จริง
  • พฤติกรรมของ CallKit แตกต่างกันไปตามแพลตฟอร์ม: บน iOS — อินเทอร์เฟซเต็มหน้าจอ, บน iPadOS และ macOS — แบนเนอร์ของระบบ
  • การเปิดใช้งาน AVAudioSession หลังจากรับสายเป็นสิ่งจำเป็น — หากไม่มี CallKit จะสิ้นสุดการโทรโดยหมดเวลา

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม