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:
-
Invalid Widget ID
// ❌ Wrong
storifyMeWidget.setWidgetId(widgetId: 0)
// ✅ Correct
storifyMeWidget.setWidgetId(widgetId: YOUR_VALID_WIDGET_ID) -
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-WaitWidgets now automatically wait for SDK initialization. If your widget shows blank, the issue is likely with credentials or network, not timing.
-
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
} -
Network Security Issues
<!-- In Info.plist, add if testing with HTTP -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict> -
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
}
}
Deep Link Issues
Deep links not working
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)")
}
}
}
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:
-
Memory Warnings
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// If stories are not currently visible, release SDK resources
if !isStoriesVisible {
StorifyMeInstance.shared.shutdown()
}
} -
User Logout
func logout() {
// Clean up SDK before logging out
StorifyMeInstance.shared.shutdown {
// Proceed with logout
self.clearUserSession()
}
} -
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
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
- TestFlight: Use TestFlight builds to test in production-like environment
- Debug Builds: Use debug builds with detailed logging
- Network Conditions: Test with poor network conditions
Getting Help
Information to Provide
When reporting issues, include:
- SDK Version: Check your Podfile.lock or Package.resolved
- iOS Version: Device OS version
- Xcode Version: Development environment version
- Device Model: iPhone/iPad model
- Integration Method: CocoaPods, SPM, or manual
- Error Logs: Complete console output
- 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
- Console: View real-time logs
- Instruments: Profile memory and performance
- Network Link Conditioner: Test with poor network
- Accessibility Inspector: Test accessibility features
Best Practices for Debugging
- Always test on physical devices
- Use debug mode during development only
- Test with different iOS versions
- Verify network connectivity
- Check StorifyMe Dashboard configuration
- Use Xcode Instruments for performance debugging
- 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.