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

iOS 17+非上架iMessage扩展后台发送定时SMS问题求助

iOS后台发送定时SMS方案分析(非App Store提交场景)

核心结论

对于非App Store的越狱/企业签名场景,iOS支持后台线程发送SMS,但需依赖私有API,且不同iOS版本兼容性差异极大;官方公开API(如MFMessageComposeViewController)仅支持前台交互发送,无法实现后台静默执行。

你的CTMessageCenter调用问题排查

你通过NSInvocation调用私有API失败,大概率是以下原因导致:

  1. 方法签名/参数不匹配
    不同iOS版本中CTMessageCenter的方法签名可能变更:部分版本的发送方法是简化版sendSMSWithText:toAddress:,而非你使用的sendSMSWithText:serviceCenter:toAddress:;且serviceCenter参数直接传nil可能不合法,部分版本需要传入有效的服务中心号码(可通过CTMessageCenter的defaultServiceCenter方法获取)。
  2. 权限缺失
    调用私有SMS发送API需要应用拥有com.apple.coretelephony.sms.send权限,需在Entitlements.plist中添加该权限并重新签名。
  3. 线程限制
    部分私有API要求必须在主线程执行,后台线程调用会直接失败,需切换到主线程执行发送逻辑。

修正后的调用示例

void sendSMS(NSObject* receiver, NSString* message, NSString* phoneNumber) {
    // 先尝试简化版方法,适配不同iOS版本
    SEL selector = @selector(sendSMSWithText:toAddress:);
    NSMethodSignature* signature = [receiver methodSignatureForSelector:selector];
    
    // 简化版不存在则 fallback 到带serviceCenter的版本
    if (!signature) {
        selector = @selector(sendSMSWithText:serviceCenter:toAddress:);
        signature = [receiver methodSignatureForSelector:selector];
    }
    
    NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
    [invocation setTarget:receiver];
    [invocation setSelector:selector];
    [invocation setArgument:&message atIndex:2];
    
    if (signature.numberOfArguments == 4) {
        // 处理带serviceCenter参数的版本
        NSString* serviceCenter = [receiver performSelector:@selector(defaultServiceCenter)];
        [invocation setArgument:&serviceCenter atIndex:3];
        [invocation setArgument:&phoneNumber atIndex:4];
    } else {
        // 处理简化版方法
        [invocation setArgument:&phoneNumber atIndex:3];
    }
    
    // 切换到主线程执行发送逻辑
    dispatch_async(dispatch_get_main_queue(), ^{
        printf("Before.\n");
        [invocation invoke];
        printf("After.\n");
    });
}

ChatKit框架方案说明

ChatKit的部分发送API确实仅能在MobileSMS进程内调用,如果你开发的是iMessage扩展,可尝试注入到MobileSMS进程中使用:

  • 获取目标联系人对应的CKConversation实例
  • 调用sendMessage:方法发送文本消息
    但此方案仅适用于越狱环境下的进程注入,且iOS 10+后ChatKit的API变更频繁,兼容性极差。

其他可行方案

  • 使用封装好的私有库:越狱社区维护的libSMS.dylib封装了CTMessageCenter和ChatKit的API,兼容性比直接调用原生私有API更好,可直接调用sms_send函数发送SMS。
  • 后台定时触发:结合UNNotificationRequest(非越狱环境)或launchd定时任务(越狱环境)触发发送逻辑,注意非越狱环境下后台任务最多存活几分钟,越狱环境可突破该限制。

开源项目参考

  • SMSLib:越狱社区维护的开源SMS发送库,封装了多版本iOS的私有发送API,适配性强。
  • iMessageBot:针对iMessage扩展的开源项目,包含后台消息发送逻辑,可参考其私有API调用方式。

内容的提问来源于stack exchange,提问作者Prowtons McBishop

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 13:23:25