Do I need cocoa pods?

main
8f7efe5docs: use the new Live Activities API (#5)
This post might have stale content, as main is 84 commits ahead.
Avatar of bensadevs
bensadevs
posted

Do I need cocoa pods?

Avatar of anthropic/claude-haiku-4.5
Claude Haiku 4.5
commented

Yes, you need CocoaPods for this project, but it's handled automatically for you. Here's what you need to know:

##CocoaPods Usage

The Voltra library includes a .podspec file (ios/Voltra.podspec) which is a CocoaPods specification. This defines the iOS native dependencies needed for the library:

  • iOS minimum version: 16.2
  • Swift version: 5.9
  • Dependencies: ExpoModulesCore

##How It's Handled

You don't need to manually manage CocoaPods because:

  1. Config Plugin Automation: The project uses an Expo config plugin (app.plugin.js) that automatically sets up the iOS extension targets for you when you run:

    npx expo prebuild --clean
    
  2. Automatic Installation: When you run npx expo prebuild, it will automatically:

    • Generate the iOS native code
    • Handle CocoaPods installation
    • Wire up the necessary extension targets

##Setup Summary

According to the README, to get started you just need to:

  1. Install the npm package: npm install voltra
  2. Add the config plugin to your app.json:
    {
      "expo": {
        "plugins": ["voltra"]
      }
    }
    
  3. Run: npx expo prebuild --clean

The prebuild command takes care of CocoaPods for you — you don't need to run pod install manually or interact with CocoaPods directly.

Avatar of bensadevs
bensadevs
commented

I got this error

Command pod install failed. └─ Cause: CocoaPods could not find compatible versions for pod "VoltraWidget":

Avatar of anthropic/claude-haiku-4.5
Claude Haiku 4.5
commented

Based on my investigation, here's what I found:

##The Issue

The error "CocoaPods could not find compatible versions for pod 'VoltraWidget'" occurs because:

  1. VoltraWidget is a local pod - It's defined in ios/VoltraWidget.podspec in your project, not published to the CocoaPods repository
  2. The config plugin references it - The plugin tries to add it to your extension target via the Podfile with a :path reference

##Likely Causes

  1. Path resolution problem - The path to the VoltraWidget podspec might not be resolving correctly. The plugin uses expo-modules-autolinking to find the module path, which may not be working as expected.

  2. Missing build step - Make sure you've run npm install and built the native modules before running npx expo prebuild --clean

##Solutions to Try

  1. Clean and retry with fresh installation:

    # Remove old builds
    rm -rf node_modules
    rm -rf example/node_modules
    npm install
    npm run build
    npx expo prebuild --clean
    
  2. Check if the Podfile was generated correctly - After running prebuild, check your example/ios/Podfile and look for the widget extension target. The pod reference should look like:

    pod 'VoltraWidget', :path => "path/to/voltra/ios"
    
  3. If CocoaPods cache is stale:

    pod repo update
    pod install --repo-update
    
  4. Check iOS compatibility - Make sure your iOS deployment target in your Xcode project is set to 16.2 or higher (required by Voltra)

If this doesn't resolve it, could you share the full error message and the contents of your Podfile after running prebuild? That would help pinpoint the exact issue.

Avatar of bensadevs
bensadevs
commented

Does this code look ok?

import React from "react"

import { startLiveActivity, stopLiveActivity, updateLiveActivity } from "voltra/client" import { Voltra } from "voltra"

type LivePayload = { halachicTime: string nextZman: string nextZmanTime: string locationLabel?: string }

let currentActivityId: string | null = null

function buildVariants(payload: LivePayload) { const title = payload.locationLabel ? Zmanim • ${payload.locationLabel} : "Zmanim" const secondary = payload.nextZman ? ${payload.nextZman} • ${payload.nextZmanTime} : "" const minimalText = payload.halachicTime.split(" ")[0] || payload.halachicTime

return { lockScreen: ( <Voltra.VStack style={{ padding: 14, borderRadius: 18, backgroundColor: "#101828" }}> <Voltra.Text style={{ color: "#F8FAFC", fontSize: 14, fontWeight: "600" }}>{title}</Voltra.Text> <Voltra.Text style={{ color: "#F8FAFC", fontSize: 26, fontWeight: "800", marginTop: 6 }}> {payload.halachicTime} </Voltra.Text> {secondary ? ( <Voltra.Text style={{ color: "#94A3B8", fontSize: 12, marginTop: 6 }}>{secondary}</Voltra.Text> ) : null} </Voltra.VStack> ), compact: ( <Voltra.VStack style={{ paddingVertical: 4 }}> <Voltra.Text style={{ fontSize: 12, fontWeight: "700" }}>{payload.halachicTime}</Voltra.Text> {payload.nextZmanTime ? <Voltra.Text style={{ fontSize: 10 }}>{payload.nextZmanTime}</Voltra.Text> : null} </Voltra.VStack> ), minimal: <Voltra.Text>{minimalText}</Voltra.Text>, } }

export async function syncHalachicLiveActivity(payload: LivePayload, options: { enabled: boolean }) { if (!options.enabled) { if (currentActivityId) { await stopLiveActivity(currentActivityId, { dismissalPolicy: { after: 10 } }) currentActivityId = null } return }

const variants = buildVariants(payload)

if (!currentActivityId) { currentActivityId = await startLiveActivity(variants, { deepLinkUrl: "zmanim://", dismissalPolicy: { after: 30 }, staleDate: Date.now() + 2 * 60 * 60 * 1000, relevanceScore: 0.8, }) return }

await updateLiveActivity(currentActivityId, variants, { staleDate: Date.now() + 2 * 60 * 60 * 1000, relevanceScore: 0.8, }) }

export async function stopHalachicLiveActivity() { if (currentActivityId) { await stopLiveActivity(currentActivityId, { dismissalPolicy: { after: 10 } }) currentActivityId = null } }

Avatar of anthropic/claude-haiku-4.5
Claude Haiku 4.5
commented

Perfect! Your code looks very good overall. Here's my analysis:

##✅ What's Correct

  1. Function usage is correct - You're using startLiveActivity, updateLiveActivity, and stopLiveActivity correctly with proper signatures
  2. Variants structure is good - Your buildVariants() returns proper LiveActivityVariants with lockScreen, compact, and minimal views
  3. State management is solid - Tracking currentActivityId to manage activity lifecycle is the right approach
  4. Options are appropriate - Your options like deepLinkUrl, dismissalPolicy, staleDate, and relevanceScore are all valid

##⚠️ Minor Observations

  1. activityName recommendation - Consider adding an activityName to your startLiveActivity() call. This allows you to rebind to the same activity if your app is force-closed and reopened:

    currentActivityId = await startLiveActivity(variants, {
      activityName: "halachic-time", // Add this
      deepLinkUrl: "zmanim://",
      // ... rest of options
    })
    
  2. Global state concern - Using a module-level currentActivityId variable works, but be aware that:

    • If your app is killed and restarted, currentActivityId will be null even if an activity is still running
    • The activityName option solves this by letting you query existing activities
  3. Error handling - You might want to add try-catch blocks:

    export async function syncHalachicLiveActivity(payload: LivePayload, options: { enabled: boolean }) {
      try {
        // ... your code
      } catch (error) {
        console.error('Failed to sync halachic live activity:', error)
        // Handle error appropriately
      }
    }
    

##📋 Suggested Improvement

Here's an enhanced version with activityName:

const ACTIVITY_NAME = 'halachic-time'

export async function syncHalachicLiveActivity(payload: LivePayload, options: { enabled: boolean }) {
  if (!options.enabled) {
    if (currentActivityId) {
      await stopLiveActivity(currentActivityId, { dismissalPolicy: { after: 10 } })
      currentActivityId = null
    }
    return
  }

  const variants = buildVariants(payload)

  if (!currentActivityId) {
    currentActivityId = await startLiveActivity(variants, {
      activityName: ACTIVITY_NAME,  // ← Add this
      deepLinkUrl: "zmanim://",
      dismissalPolicy: { after: 30 },
      staleDate: Date.now() + 2 * 60 * 60 * 1000,
      relevanceScore: 0.8,
    })
    return
  }

  await updateLiveActivity(currentActivityId, variants, {
    staleDate: Date.now() + 2 * 60 * 60 * 1000,
    relevanceScore: 0.8,
  })
}

Overall, your implementation matches the Voltra API well and should work correctly! 🎉

Avatar of bensadevs
bensadevs
commented

I got this error

✔ Created native directory ✔ Updated package.json | no changes [Voltra] Generated Info.plist [Voltra] Generated Assets.xcassets [Voltra] ⚠️ Skipping user images: directory does not exist at ./assets/voltra [Voltra] Generated VoltraWidgetInitialStates.swift with 0 pre-rendered widget states [Voltra] Generated VoltraWidgetBundle.swift with 0 home screen widgets [Voltra] Generated nativeLiveActivity.entitlements » ios: scheme: "ios.infoPlist.CFBundleURLTypes" is set in the config. Ignoring abstract property "scheme": zmanim ✔ Finished prebuild ⚠️ Something went wrong running pod install in the ios directory. Command pod install failed. └─ Cause: CocoaPods could not find compatible versions for pod "VoltraWidget": In Podfile: VoltraWidget (from ../../../node_modules/.pnpm/voltra@1.0.0_expo@54.0.31_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/voltra/ios)

Specs satisfying the VoltraWidget (from ../../../node_modules/.pnpm/voltra@1.0.0_expo@54.0.31_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/voltra/ios) dependency were found, but they required a higher minimum deployment target.

pod install --repo-update --ansi exited with non-zero code: 1

Avatar of anthropic/claude-haiku-4.5
Claude Haiku 4.5
commented

##Solution

Voltra requires iOS 16.2 or higher. You need to update your project's iOS deployment target to at least 16.2.

###Steps to Fix:

  1. Open your app.json and update the iOS platform version:

    {
      "expo": {
        "ios": {
          "deploymentTarget": "16.2"
        },
        "plugins": ["voltra"]
      }
    }
    
  2. Clean and rebuild:

    rm -rf ios
    npx expo prebuild --clean
    

If you're using a bare React Native project (not Expo), update the deployment target in Xcode:

  • Open your .xcodeproj file in Xcode
  • Select your main project
  • Go to Build Settings
  • Search for Minimum Deployment Target
  • Set it to 16.2 for both the main target and the widget extension target
  1. Try running pod install again:
    cd ios
    pod install --repo-update
    

That should resolve the CocoaPods error! 🎯

Avatar of bensadevs
bensadevs
commented

I am using Expo

✔ Created native directory ✔ Updated package.json | no changes [Voltra] Generated Info.plist [Voltra] Generated Assets.xcassets [Voltra] ⚠️ Skipping user images: directory does not exist at ./assets/voltra [Voltra] Generated VoltraWidgetInitialStates.swift with 0 pre-rendered widget states [Voltra] Generated VoltraWidgetBundle.swift with 0 home screen widgets [Voltra] Generated nativeLiveActivity.entitlements ✔ Finished prebuild ⚠️ Something went wrong running pod install in the ios directory. Command pod install failed. └─ Cause: CocoaPods could not find compatible versions for pod "VoltraWidget": In Podfile: VoltraWidget (from ../../../node_modules/.pnpm/voltra@1.0.0_expo@54.0.31_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/voltra/ios)

Specs satisfying the VoltraWidget (from ../../../node_modules/.pnpm/voltra@1.0.0_expo@54.0.31_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/voltra/ios) dependency were found, but they required a higher minimum deployment target.

pod install --repo-update --ansi exited with non-zero code: 1

Avatar of anthropic/claude-haiku-4.5
Claude Haiku 4.5
commented

Ah! I see the issue. The example app has deploymentTarget: 17.0 which is fine, but your app likely has a lower deployment target.

Can you share your app.json file? But based on the error, here's what you need to do:

##Fix: Update your app.json

Make sure you have the expo-build-properties plugin configured with at least iOS 16.2:

{
  "expo": {
    "name": "Your App",
    "slug": "your-app-slug",
    "plugins": [
      "voltra",
      [
        "expo-build-properties",
        {
          "ios": {
            "deploymentTarget": "16.2"
          }
        }
      ]
    ]
  }
}

Key points:

  • The expo-build-properties plugin sets the iOS deployment target
  • Set it to at least 16.2 (or higher like 17.0 is fine too)
  • Make sure voltra plugin comes before expo-build-properties in the plugins array

Then try again:

rm -rf ios
npx expo prebuild --clean

If you're still getting the error after this, please share:

  1. Your app.json file
  2. The output of: grep -r "deploymentTarget\|IPHONEOS_DEPLOYMENT_TARGET" ios/ (after prebuild)
Avatar of bensadevs
bensadevs
commented

NO! This is my app.json

{ "expo": { "name": "native", "slug": "native", "version": "1.0.0", "orientation": "portrait", "icon": "./assets/icon.png", "userInterfaceStyle": "light", "newArchEnabled": true, "splash": { "image": "./assets/splash.png", "resizeMode": "contain", "backgroundColor": "#ffffff" }, "updates": { "fallbackToCacheTimeout": 0 }, "assetBundlePatterns": [ "**/*" ], "plugins": [ "expo-router", [ "voltra", { "groupIdentifier": "group.com.zmanim.widget", "deploymentTarget": "26.2", "enablePushNotifications": true } ] ], "ios": { "deploymentTarget": "26.2", "infoPlist": { "CFBundleURLTypes": [ { "CFBundleURLSchemes": [ "zmanim" ] } ], "NSSupportsLiveActivities": true, "NSSupportsLiveActivitiesFrequentUpdates": false, "Voltra_AppGroupIdentifier": "group.com.zmanim.widget" }, "entitlements": { "com.apple.security.application-groups": [ "group.com.zmanim.widget" ] }, "bundleIdentifier": "com.zmanim.native" } } }


END OF POST

Do I need cocoa pods? — callstackincubator/voltra