Skip to main content

Troubleshooting

This guide helps you diagnose and resolve common issues when integrating the StorifyMe iOS SDK.

Widget Not Loading

Widget shows blank/empty space

Symptoms:

  • StorifyMeWidget is visible but shows no content
  • No stories appear even after calling load()

Common Causes & Solutions:

  1. Invalid Widget ID

    // ❌ Wrong
    storifyMeWidget.setWidgetId(widgetId: 0)

    // ✅ Correct
    storifyMeWidget.setWidgetId(widgetId: YOUR_VALID_WIDGET_ID)
  2. SDK Not Ready

    Check if the SDK has finished initializing:

    // Check SDK state
    print("SDK State: \(StorifyMeInstance.shared.state)")
    print("SDK isReady: \(StorifyMeInstance.shared.isReady)")

    // Use initialization callback to ensure SDK is ready
    StorifyMeInstance.shared.initialize(
    accountId: "your-account-id",
    apiKey: "your-api-key"
    ) { result in
    switch result {
    case .success:
    print("SDK ready - widgets will load now")
    case .failure(let error):
    print("SDK failed: \(error.message)")
    }
    }
    Widget Auto-Wait

    Widgets now automatically wait for SDK initialization. If your widget shows blank, the issue is likely with credentials or network, not timing.

  3. Missing SDK Initialization

    // ✅ Ensure initialization in AppDelegate or SceneDelegate
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    StorifyMeInstance.shared.initialize(
    accountId: "your-account-id",
    apiKey: "your-api-key"
    )
    return true
    }
  4. Network Security Issues

    <!-- In Info.plist, add if testing with HTTP -->
    <key>NSAppTransportSecurity</key>
    <dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    </dict>
  5. Widget Not Published

    • Check StorifyMe Dashboard to ensure widget is published
    • Verify widget contains published stories

Widget fails to load with error

Implement Event Handler:

extension ViewController: StorifyMeStoryEventProtocol {
func onFail(error: StorifyMeError) {
print("StorifyMe Error: \(error.message)")
// Common errors:
// - "Widget not found" - Invalid widget ID
// - "Network error" - Connectivity issues
// - "Unauthorized" - Invalid API key/account ID
}
}

Build Issues

CocoaPods Integration Problems

Pod Installation Issues:

# Clear CocoaPods cache
pod cache clean --all
pod deintegrate
pod install --repo-update

# If using Xcode 15+, you might need:
pod install --verbose

Podfile Configuration:

platform :ios, '12.0'
use_frameworks!

target 'YourApp' do
pod 'StorifyMe', '~> <latest-version>'

# If you encounter issues, try:
# pod 'StorifyMe', :git => 'https://github.com/StorifyMe/sdk-ios.git'
end

# Add this if you have module issues
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
end
end
end

Swift Package Manager Issues

Package Resolution Problems:

// In Package.swift or Xcode Package Manager
.package(url: "https://github.com/StorifyMe/sdk-ios.git", from: "<latest-version>")

Common SPM Errors:

  • Clear derived data: Product > Clean Build Folder
  • Reset package caches: File > Packages > Reset Package Caches
  • Update to latest: File > Packages > Update to Latest Package Versions

Compilation Errors

Missing Frameworks:

// Ensure these frameworks are linked
// UIKit, Foundation, AVFoundation, WebKit
// Usually handled automatically by CocoaPods/SPM

Bitcode Issues (Legacy):

# In Build Settings, set Enable Bitcode to NO if encountering issues
# (Note: Bitcode deprecated in Xcode 14+)

Runtime Issues

App Crashes

StorifyMe Initialization Crash:

// ❌ Wrong - calling before initialization
StorifyMeInstance.shared.openStoryByHandle(handle: "test")

// ✅ Correct - initialize first
StorifyMeInstance.shared.initialize(accountId: "id", apiKey: "key")
StorifyMeInstance.shared.openStoryByHandle(handle: "test")

Memory Crashes:

// Implement proper memory management
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
// Clear resources if widget provides cleanup method
storifyMeWidget.cleanup() // If available
}

Thread Safety Issues:

// Always call SDK methods on main thread
DispatchQueue.main.async {
self.storifyMeWidget.load()
}

Performance Issues

Slow Loading

Add Custom Logging:

// For development builds only
#if DEBUG
extension ViewController: StorifyMeStoryEventProtocol {
func onLoad(widgetId: Int, stories: [StorifyMeStoryModel]) {
print("✅ StorifyMe: Widget \(widgetId) loaded with \(stories.count) stories")
}

func onFail(error: StorifyMeError) {
print("❌ StorifyMe: Widget failed - \(error.message)")
}
}
#endif

Monitor Loading Performance:

extension ViewController: StorifyMeStoryEventProtocol {
func onLoad(widgetId: Int, stories: [StorifyMeStoryModel]) {
let loadTime = Date().timeIntervalSince(startTime)
print("Widget loaded in \(loadTime) seconds")
}
}

Optimize for Performance:

// Disable resource-intensive features if needed
storifyMeWidget.setGifPosterEnabled(false)
storifyMeWidget.setVideoPosterEnabled(false)

Memory Issues

High Memory Usage:

// Monitor memory in development
// Use Xcode Instruments to profile memory usage

// Optimize poster settings
storifyMeWidget.setGifPosterEnabled(false) // Reduces memory
storifyMeWidget.setVideoPosterEnabled(false) // Reduces memory

Story Opening Issues

Stories not opening when tapped

Check Event Handler Implementation:

class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()

// ❌ Missing event handler assignment
storifyMeWidget.setWidgetId(widgetId: WIDGET_ID)

// ✅ Correct - assign event handler
storifyMeWidget.eventHandler = self
storifyMeWidget.setWidgetId(widgetId: WIDGET_ID)
}
}

extension ViewController: StorifyMeStoryEventProtocol {
func onStoryOpen(widgetId: Int, storyId: Int, storyHandle: String) {
print("Story opened: \(storyHandle)")
}
}

View Controller Hierarchy Issues:

// Ensure widget is added to view hierarchy properly
override func viewDidLoad() {
super.viewDidLoad()

view.addSubview(storifyMeWidget)
storifyMeWidget.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
storifyMeWidget.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
storifyMeWidget.leadingAnchor.constraint(equalTo: view.leadingAnchor),
storifyMeWidget.trailingAnchor.constraint(equalTo: view.trailingAnchor),
storifyMeWidget.heightAnchor.constraint(equalToConstant: 120)
])
}

openStoryByHandle not working

Common Issues:

// ❌ Wrong - not initialized
StorifyMeInstance.shared.openStoryByHandle(handle: "test")

// ✅ Correct - ensure initialization
StorifyMeInstance.shared.initialize(accountId: "id", apiKey: "key")
StorifyMeInstance.shared.openStoryByHandle(handle: "test")

// ❌ Wrong - invalid handle
StorifyMeInstance.shared.openStoryByHandle(handle: "")

// ✅ Correct - valid handle
StorifyMeInstance.shared.openStoryByHandle(handle: "valid-story-handle")

Configuration Issues

Stories not playing audio

Check Audio Configuration:

storifyMeWidget.setWidgetAudioOptions(
options: StorifyMeStoryAudioOptions(
behaviour: .applyLastUserChangeForAllFutureStories,
defaultState: .unmuted // Check this setting
)
)

iOS Audio Session Issues:

// In some cases, you might need to configure audio session
import AVFoundation

override func viewDidLoad() {
super.viewDidLoad()

do {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
print("Audio session error: \(error)")
}
}

Wrong layout or appearance

Auto Layout Issues:

// Ensure proper constraints
storifyMeWidget.translatesAutoresizingMaskIntoConstraints = false

// Common constraint issues
NSLayoutConstraint.activate([
storifyMeWidget.heightAnchor.constraint(equalToConstant: 120), // Set explicit height
storifyMeWidget.widthAnchor.constraint(equalTo: view.widthAnchor)
])

Dark Mode Issues:

// Test in both light and dark mode
// Override if needed:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)

if traitCollection.userInterfaceStyle != previousTraitCollection?.userInterfaceStyle {
// Handle appearance changes if needed
storifyMeWidget.refreshAppearance() // If available
}
}

Associated Domains Configuration:

<!-- In YourApp.entitlements -->
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:yourdomain.com</string>
<!-- Make sure domain matches exactly -->
</array>

URL Handling Issues:

// SceneDelegate
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL else {
return
}

print("Received URL: \(url)") // Add logging
handleDeepLink(url: url)
}

// AppDelegate (if not using SceneDelegate)
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
print("Received URL: \(userActivity.webpageURL)") // Add logging
// Handle URL
return true
}

SwiftUI Issues

Widget not displaying in SwiftUI

Use the native StorifyMeWidgetView wrapper instead of manual UIViewRepresentable:

import SwiftUI
import StorifyMe

struct ContentView: View {
@State private var widgetHeight: CGFloat = 150

var body: some View {
StorifyMeWidgetView(widgetId: 54, height: $widgetHeight)
.frame(height: widgetHeight)
.onError { error in
print("Widget error: \(error.message)")
}
}
}
tip

See the SwiftUI Integration Guide for complete documentation.

Memory not releasing on navigation

Problem: GIF memory is not released when navigating away from a screen with widgets.

Solution: Clear GIF cache in onDisappear:

struct StoriesScreen: View {
var body: some View {
StorifyMeWidgetView(widgetId: 54)
.frame(height: 200)
.onDisappear {
StorifyMeWidgetView.clearGifCache()
}
}
}

Height not updating in ScrollView

Problem: Widget height doesn't update dynamically in ScrollView.

Solution: Use the height binding parameter:

struct ScrollViewExample: View {
@State private var widgetHeight: CGFloat = 150

var body: some View {
ScrollView {
StorifyMeWidgetView(widgetId: 54, height: $widgetHeight)
.frame(height: widgetHeight) // Important: Apply frame with binding
}
}
}

iOS 17+ dismantleUIView not called

Problem: In iOS 17+, dismantleUIView may not be called reliably (Apple bug FB11979117).

Solution: The SDK implements fallback cleanup in Coordinator's deinit, but always use explicit cleanup:

.onDisappear {
StorifyMeWidgetView.clearGifCache()
}

Widget not loading in Xcode Preview

Problem: Widget shows blank in Xcode Preview.

Solution: Xcode Previews don't support full SDK initialization. Use conditional compilation:

struct ContentView: View {
var body: some View {
#if DEBUG
if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" {
// Show placeholder in preview
Rectangle()
.fill(Color.gray.opacity(0.3))
.frame(height: 200)
.overlay(Text("StorifyMe Widget"))
} else {
StorifyMeWidgetView(widgetId: 54)
.frame(height: 200)
}
#else
StorifyMeWidgetView(widgetId: 54)
.frame(height: 200)
#endif
}
}

SDK State Debugging

Check SDK Initialization State

When debugging issues, start by checking the SDK state:

func debugSDKState() {
let instance = StorifyMeInstance.shared

print("=== StorifyMe SDK Debug Info ===")
print("State: \(instance.state)")
print("isReady: \(instance.isReady)")

switch instance.state {
case .inactive:
print("⚠️ SDK has not been initialized or was shut down")
case .initializing:
print("⏳ SDK is currently initializing...")
case .ready:
print("✅ SDK is ready to use")
case .failed(let error):
print("❌ SDK failed to initialize:")
print(" Error Type: \(error.type)")
print(" Message: \(error.message)")
}
print("================================")
}

Monitor SDK Lifecycle Events

Use notifications to track SDK state changes throughout your app:

class SDKStateMonitor {
init() {
NotificationCenter.default.addObserver(
self,
selector: #selector(sdkDidBecomeReady),
name: .storifyMeSDKDidBecomeReady,
object: nil
)

NotificationCenter.default.addObserver(
self,
selector: #selector(sdkDidFail(_:)),
name: .storifyMeSDKDidFailToInitialize,
object: nil
)

NotificationCenter.default.addObserver(
self,
selector: #selector(sdkDidShutdown),
name: .storifyMeSDKDidShutdown,
object: nil
)
}

@objc private func sdkDidBecomeReady() {
print("📗 SDK became ready at \(Date())")
}

@objc private func sdkDidFail(_ notification: Notification) {
if let error = notification.userInfo?[StorifyMeSDKErrorKey] as? StorifyMeError {
print("📕 SDK failed at \(Date()): \(error.message)")
}
}

@objc private func sdkDidShutdown() {
print("📙 SDK was shut down at \(Date())")
}
}

Resolve Memory Issues with shutdown

If you're experiencing memory issues or need to reset the SDK:

// Clean up SDK resources when no longer needed
StorifyMeInstance.shared.shutdown {
print("SDK resources released")

// Optionally re-initialize if needed
// StorifyMeInstance.shared.initialize(...)
}

Common scenarios for using shutdown:

  1. Memory Warnings

    override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()

    // If stories are not currently visible, release SDK resources
    if !isStoriesVisible {
    StorifyMeInstance.shared.shutdown()
    }
    }
  2. User Logout

    func logout() {
    // Clean up SDK before logging out
    StorifyMeInstance.shared.shutdown {
    // Proceed with logout
    self.clearUserSession()
    }
    }
  3. Account Switching

    func switchToAccount(_ accountId: String, apiKey: String) {
    StorifyMeInstance.shared.shutdown { [weak self] in
    StorifyMeInstance.shared.initialize(
    accountId: accountId,
    apiKey: apiKey
    ) { result in
    // Handle result
    }
    }
    }

Debug Tools

Enable SDK Debug Logging

The fastest way to debug issues is to enable SDK logging:

// Enable verbose logging for maximum detail
StorifyMeInstance.shared.logLevel = .verbose

// Or debug level for standard debugging
StorifyMeInstance.shared.logLevel = .debug

View logs in:

  • Xcode Console: Real-time during debugging
  • Console.app: Filter by subsystem com.storifyme.sdk

Log output format:

[StorifyMe] [DEBUG] [Widget] Loading widget configuration
[StorifyMe] [ERROR] [Network] Request failed: timeout
tip

Set logLevel before calling initialize() to capture initialization logs. See the Logging section for more details.

Add Comprehensive Logging

#if DEBUG
extension ViewController: StorifyMeStoryEventProtocol {
func onLoad(widgetId: Int, stories: [StorifyMeStoryModel]) {
print("✅ StorifyMe-Debug: Widget \(widgetId) loaded with \(stories.count) stories")
}

func onFail(error: StorifyMeError) {
print("❌ StorifyMe-Debug: Widget failed - \(error.message)")
}

func onStoryOpened(story: StorifyMeStoryModel?, index: Int) {
print("📖 StorifyMe-Debug: Story opened at index \(index)")
}

func onStoryClose(story: StorifyMeStoryModel?) {
print("📕 StorifyMe-Debug: Story closed")
}
}
#endif

Console Logging

// Add comprehensive logging
extension ViewController: StorifyMeStoryEventProtocol {
func onLoad(widgetId: Int, stories: [StorifyMeStoryModel]) {
print("✅ Loaded \(stories.count) stories for widget \(widgetId)")
}

func onFail(error: StorifyMeError) {
print("❌ Failed to load widget: \(error.message)")
}

func onStoryOpened(story: StorifyMeStoryModel?, index: Int) {
print("📖 Story opened at index \(index)")
}

func onStoryClose(story: StorifyMeStoryModel?) {
print("📕 Story closed")
}
}

Network Debugging

// Monitor network requests (if SDK provides callback)
// Use Xcode Network debugging or Charles Proxy to monitor requests

Testing Tools

Simulator Testing

# Test deep links in simulator
xcrun simctl openurl booted "https://yourdomain.com/story-handle"

Device Testing

  1. TestFlight: Use TestFlight builds to test in production-like environment
  2. Debug Builds: Use debug builds with detailed logging
  3. Network Conditions: Test with poor network conditions

Getting Help

Information to Provide

When reporting issues, include:

  1. SDK Version: Check your Podfile.lock or Package.resolved
  2. iOS Version: Device OS version
  3. Xcode Version: Development environment version
  4. Device Model: iPhone/iPad model
  5. Integration Method: CocoaPods, SPM, or manual
  6. Error Logs: Complete console output
  7. Configuration Code: Your widget setup code

Useful Debug Commands

# Check CocoaPods setup
pod --version
pod outdated

# Check Xcode build settings
xcodebuild -showBuildSettings -target YourApp

# Test deep links
xcrun simctl openurl booted "https://yourdomain.com/test-handle"

Xcode Debugging Tools

  1. Console: View real-time logs
  2. Instruments: Profile memory and performance
  3. Network Link Conditioner: Test with poor network
  4. Accessibility Inspector: Test accessibility features

Best Practices for Debugging

  1. Always test on physical devices
  2. Use debug mode during development only
  3. Test with different iOS versions
  4. Verify network connectivity
  5. Check StorifyMe Dashboard configuration
  6. Use Xcode Instruments for performance debugging
  7. Test in both light and dark mode

Performance Monitoring

// Monitor key metrics
class PerformanceMonitor: StorifyMeStoryEventProtocol {
private var loadStartTime: Date?

func startMonitoring() {
loadStartTime = Date()
}

func onLoad(widgetId: Int, stories: [StorifyMeStoryModel]) {
if let startTime = loadStartTime {
let duration = Date().timeIntervalSince(startTime)
print("Load time: \(duration)s for \(stories.count) stories")
}
}
}

For additional support, refer to the StorifyMe Documentation or contact the support team with the debug information listed above.