You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS自定义来电/去电界面替换系统原生界面的实现方案咨询

Custom Call Screen Implementation on iOS: Feasibility & Step-by-Step Guide

First off, yes—it is possible to replace or overlay the default incoming/outgoing call screen on iOS, but the approach varies a lot depending on the iOS version you're targeting, and there are strict platform rules you can't ignore. Let's break this down clearly:

Key Feasibility Notes

  • For iOS 14 and later: Apple introduced official, App Store-friendly APIs via CallKit—this is the only supported way to build a custom call interface without risking rejection.
  • For iOS versions before 14: You could hack together a floating overlay using UIWindow tricks, but this was unreliable, broke easily with OS updates, and was likely to get your app rejected. We'll focus on the supported iOS 14+ approach here.

Step-by-Step Implementation (iOS 14+)

1. Add the CallKit Framework

First, add the CallKit framework to your Xcode project. This is the core tool that lets your app interact with the system's call handling.

2. Implement the CXProviderDelegate

You'll need to conform to CXProviderDelegate to handle call events and trigger your custom UI:

import CallKit

class CallManager: NSObject, CXProviderDelegate {
    private let provider: CXProvider
    
    override init() {
        let config = CXProviderConfiguration(localizedName: "Your App Name")
        config.supportsVideo = true // Toggle based on your app's call type
        config.maximumCallGroups = 1
        config.maximumCallsPerCallGroup = 1
        
        provider = CXProvider(configuration: config)
        super.init()
        provider.setDelegate(self, queue: nil)
    }
    
    // MARK: - CXProviderDelegate Methods
    func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
        // Handle outgoing call initialization logic here
        action.fulfill()
    }
    
    func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
        // Handle incoming call answer logic here
        action.fulfill()
    }
    
    func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
        // Configure audio routing (speaker/earpiece) for the call
    }
    
    func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
        // Clean up audio session resources after the call ends
    }
}

3. Trigger Calls & Custom UI

Use CXCallController to tell the system to initiate or receive a call, which will trigger your custom interface:

For Outgoing Calls:

let callController = CXCallController()
let recipientHandle = CXHandle(type: .generic, value: "Recipient Name/Number")
let startCallAction = CXStartCallAction(call: UUID(), handle: recipientHandle)
startCallAction.isVideo = false // Adjust for video calls

let transaction = CXTransaction(action: startCallAction)
callController.request(transaction) { error in
    if let error = error {
        print("Failed to start call: \(error.localizedDescription)")
    } else {
        // Your custom UI will be triggered next
    }
}

For Incoming Calls:

let callUpdate = CXCallUpdate()
callUpdate.remoteHandle = CXHandle(type: .generic, value: "Caller Name/Number")
callUpdate.hasVideo = false
callUpdate.supportsDTMF = true
callUpdate.supportsHolding = true

provider.reportNewIncomingCall(with: UUID(), update: callUpdate, completion: { error in
    if let error = error {
        print("Failed to report incoming call: \(error.localizedDescription)")
    } else {
        // System will prompt your custom call UI
    }
})

4. Build & Present Your Custom Call UI

Create a UIViewController for your custom call screen, then present it when the call starts using this delegate method:

func provider(_ provider: CXProvider, didBegin call: CXCall) {
    guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return }
    let customCallVC = CustomCallViewController() // Your custom call screen VC
    customCallVC.modalPresentationStyle = .fullScreen
    
    windowScene.windows.first?.rootViewController?.present(customCallVC, animated: true)
}

Critical Limitations to Keep in Mind

  • App Store Rules: You can only use CallKit for actual voice/video calls (VoIP, SIP, etc.). Using it for fake calls or non-call features will get your app rejected.
  • System Overrides: iOS will still show lock-screen call notifications and let users answer/reject calls from there—you can't fully disable system-level call controls.
  • Background Handling: For incoming calls when the app is closed or in the background, you'll need to set up VoIP push notifications to trigger the custom UI.

内容的提问来源于stack exchange,提问作者Wasim Mirza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:21:24