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

如何在Objective-C中通过本地通知每日8点调用Web Service并展示数据计数

实现每日8点调用Web Service并展示本地通知的方案

没问题!我来帮你梳理一套完整的实现方案,分通用核心逻辑和主流平台(iOS/Swift、Android/Kotlin)的具体代码示例,你可以按需参考:

通用核心逻辑

不管是iOS还是Android,核心流程都是这三步:

  • 定时触发任务:每天上午8点精准触发任务,必须用系统级的定时机制,避免设备休眠导致任务“躺平”不执行;
  • 拉取数据并计数:调用你的Web Service获取数组数据,计算数组长度(也就是新通知的条数);
  • 展示本地通知:把计数结果拼进通知文案,调用系统API弹出通知,比如“您有10条新通知”。

iOS(Swift)具体实现

1. 先配置权限

在Info.plist里添加通知权限和后台刷新权限,不然系统会限制你的操作:

<key>NSNotificationUsageDescription</key>
<string>需要向您推送新通知提醒</string>
<key>UIBackgroundModes</key>
<array>
    <string>fetch</string>
    <string>remote-notification</string>
</array>

2. 启动时申请通知权限

在AppDelegate或者SceneDelegate里申请用户授权,不然弹不出通知:

import UserNotifications

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
        if granted {
            DispatchQueue.main.async {
                application.registerForRemoteNotifications()
            }
        }
        // 可以在这里处理权限被拒绝的情况
    }
    // 别忘了设置代理,用来更新通知内容
    UNUserNotificationCenter.current().delegate = self
    // 初始化定时任务
    setupDailyNotificationTask()
    return true
}

3. 设置每日8点的定时任务

用UNCalendarNotificationTrigger来实现精准的每日触发,然后在通知即将展示时拉取数据更新内容:

func setupDailyNotificationTask() {
    let content = UNMutableNotificationContent()
    content.title = "新通知提醒"
    content.sound = UNNotificationSound.default
    
    // 设置每天8点整触发
    var dateComponents = DateComponents()
    dateComponents.hour = 8
    dateComponents.minute = 0
    let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
    
    // 创建唯一的通知请求
    let request = UNNotificationRequest(identifier: "DailyNotificationCheck", content: content, trigger: trigger)
    
    // 把任务交给系统
    UNUserNotificationCenter.current().add(request) { error in
        if let error = error {
            print("定时任务添加失败:\(error.localizedDescription)")
        }
    }
}

// 实现代理方法,在通知展示前更新内容
extension AppDelegate: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        // 调用Web Service拉取数据
        fetchNewNotifications { count in
            // 复制原通知内容并更新文案
            let updatedContent = UNMutableNotificationContent(notification.content)
            updatedContent.body = "您有\(count)条新通知"
            
            // 更新通知请求
            let updatedRequest = UNNotificationRequest(identifier: notification.request.identifier, content: updatedContent, trigger: notification.request.trigger)
            center.add(updatedRequest) { _ in
                // 展示通知
                completionHandler([.alert, .sound])
            }
        }
    }
}

// 封装Web Service调用逻辑
func fetchNewNotifications(completion: @escaping (Int) -> Void) {
    guard let url = URL(string: "https://your-web-service-url.com/notifications") else {
        completion(0)
        return
    }
    
    URLSession.shared.dataTask(with: url) { data, response, error in
        guard let data = data, error == nil else {
            completion(0)
            return
        }
        
        do {
            // 替换成你的数据模型
            let notifications = try JSONDecoder().decode([NotificationModel].self, from: data)
            completion(notifications.count)
        } catch {
            print("数据解析失败:\(error)")
            completion(0)
        }
    }.resume()
}

// 定义你的数据模型(根据Web Service返回字段调整)
struct NotificationModel: Codable {
    let id: Int
    let title: String
    // 其他字段...
}

Android(Kotlin)具体实现

1. 配置权限和组件

在AndroidManifest.xml里添加必要的权限和组件,保证任务能正常执行:

<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <!-- 开机自启,避免任务丢失 -->
<uses-permission android:name="android.permission.INTERNET"/>

<application ...>
    <!-- 注册广播接收器(处理开机自启) -->
    <receiver android:name=".DailyNotificationReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
        </intent-filter>
    </receiver>
    <!-- 注册JobService(处理后台任务) -->
    <service android:name=".NotificationJobService" android:permission="android.permission.BIND_JOB_SERVICE"/>
</application>

2. 申请通知权限(Android 13+)

在MainActivity里申请通知权限,不然Android 13及以上版本弹不出通知:

import android.Manifest
import android.content.pm.PackageManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat

class MainActivity : AppCompatActivity() {
    private val POST_NOTIFICATIONS_REQUEST = 1001

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 申请通知权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.POST_NOTIFICATIONS), POST_NOTIFICATIONS_REQUEST)
        }

        // 初始化定时任务
        setupDailyNotificationTask(this)
    }
}

3. 设置每日定时任务(用JobScheduler)

JobScheduler是Android推荐的后台任务调度器,能适配系统的省电策略:

import android.app.job.JobInfo
import android.app.job.JobScheduler
import android.content.ComponentName
import android.content.Context

fun setupDailyNotificationTask(context: Context) {
    val jobScheduler = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler

    // 构建任务信息:每天执行一次,需要网络
    val jobInfo = JobInfo.Builder(1001, ComponentName(context, NotificationJobService::class.java))
        .setPeriodic(24 * 60 * 60 * 1000) // 24小时周期
        .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) // 需要网络才能执行
        .setPersisted(true) // 重启设备后任务保留
        .build()

    // 提交任务
    jobScheduler.schedule(jobInfo)
}

4. 实现JobService处理任务

在NotificationJobService里完成Web Service调用和通知展示:

import android.app.job.JobParameters
import android.app.job.JobService
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.os.Build
import androidx.core.app.NotificationCompat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.json.JSONArray
import java.net.URL

class NotificationJobService : JobService() {
    private val CHANNEL_ID = "DailyNotificationChannel"
    private val NOTIFICATION_ID = 1

    override fun onStartJob(params: JobParameters?): Boolean {
        // 用协程处理网络请求,避免阻塞主线程
        CoroutineScope(Dispatchers.IO).launch {
            val count = fetchNewNotifications()
            showNotification(count)
            // 任务完成,告诉系统不需要重新调度
            jobFinished(params, false)
        }
        return true // 表示任务在后台执行
    }

    override fun onStopJob(params: JobParameters?): Boolean {
        return true // 如果任务被系统中断,重新调度
    }

    // 调用Web Service并计数
    private suspend fun fetchNewNotifications(): Int {
        return try {
            val url = URL("https://your-web-service-url.com/notifications")
            val response = url.readText()
            // 解析JSON数组(根据实际返回格式调整)
            val notifications = JSONArray(response)
            notifications.length()
        } catch (e: Exception) {
            e.printStackTrace()
            0
        }
    }

    // 展示本地通知
    private fun showNotification(count: Int) {
        val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        // Android 8.0+需要创建通知渠道
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                CHANNEL_ID,
                "每日通知提醒",
                NotificationManager.IMPORTANCE_DEFAULT
            )
            notificationManager.createNotificationChannel(channel)
        }

        val notification = NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("新通知提醒")
            .setContentText("您有$count条新通知")
            .setSmallIcon(R.drawable.ic_notification) // 替换成你的通知图标
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .build()

        notificationManager.notify(NOTIFICATION_ID, notification)
    }
}

5. 开机自启广播接收器

保证设备重启后定时任务能重新生效:

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent

class DailyNotificationReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        if (intent?.action == Intent.ACTION_BOOT_COMPLETED) {
            context?.let { setupDailyNotificationTask(it) }
        }
    }
}

一些注意事项

  • 异常处理:网络请求一定要处理失败情况(比如无网络、解析错误),避免任务崩溃,默认可以返回0条;
  • iOS后台限制:如果App被用户强制关闭,定时任务会暂停,这种情况可以结合远程推送来唤醒App;
  • Android省电策略:JobScheduler在Doze模式下可能延迟执行,如果需要更精准的定时,可以考虑AlarmManager配合WakeLock,但要注意控制耗电。

内容的提问来源于stack exchange,提问作者Manju Sreejith

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:13:35