CAMPAIGN_CONTROLLER_INVESTIGATION_REPORT.md 4.42 KB

CampaignViewController Investigation Report

Issue

"Unknown class CampaignViewController in Interface Builder file" error when using SPM, while XIB files work perfectly.

Investigation Findings

1. Package.swift Analysis

GOOD: CampaignViewController.swift is properly included in SPM target

  • File location: SwiftWarplyFramework/SwiftWarplyFramework/screens/CampaignViewController.swift
  • SPM path: "SwiftWarplyFramework/SwiftWarplyFramework"
  • The file is automatically included since no explicit sources parameter excludes it

2. File Structure Comparison

GOOD: File is in correct location

  • CampaignViewController.swift is in screens/ directory (same as other working controllers)
  • Other working controllers: ProfileViewController, CouponViewController, MyRewardsViewController

3. Class Declaration Analysis

PROBLEM IDENTIFIED: Missing Convenience Initializer

CampaignViewController.swift:

@objc public class CampaignViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler, CLLocationManagerDelegate, WKUIDelegate, UIScrollViewDelegate {
    @IBOutlet weak var webview: WKWebView!

    // NO convenience initializer for storyboard loading
    // NO explicit bundle handling
}

ProfileViewController.swift (WORKING):

@objc public class ProfileViewController: UIViewController {
    @IBOutlet weak var tableView: UITableView!

    // MARK: - Initializers
    public convenience init() {
        self.init(nibName: "ProfileViewController", bundle: Bundle.frameworkBundle)
    }

    public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
}

4. Key Differences

Aspect CampaignViewController ProfileViewController (Working)
Convenience Init ❌ Missing ✅ Present with Bundle.frameworkBundle
Bundle Handling ❌ No explicit bundle ✅ Uses Bundle.frameworkBundle
Storyboard vs XIB 📱 Storyboard-based 📄 XIB-based
Class Declaration ✅ Public ✅ Public
Access Modifiers ✅ Correct ✅ Correct

5. Root Cause Analysis

The issue is NOT with SPM inclusion but with bundle resolution for storyboard-based view controllers.

Why XIB controllers work:

  • XIB controllers have explicit Bundle.frameworkBundle initializers
  • They handle bundle resolution correctly for SPM

Why CampaignViewController fails:

  • Storyboard tries to instantiate the class but can't resolve the correct bundle
  • No convenience initializer to guide bundle resolution
  • SPM creates different bundle structure than CocoaPods

6. Bundle Structure Difference

CocoaPods:

  • Bundle: SwiftWarplyFramework.framework
  • Storyboard can find classes easily

SPM:

  • Bundle: SwiftWarplyFramework_SwiftWarplyFramework.bundle
  • Storyboard needs explicit bundle guidance

Recommended Solutions

Option 1: Add Bundle-Aware Initializers (Recommended)

Add the missing initializers to CampaignViewController.swift:

// MARK: - Initializers
public convenience init() {
    let storyboard = UIStoryboard(name: "Main", bundle: Bundle.frameworkBundle)
    let vc = storyboard.instantiateViewController(withIdentifier: "CampaignViewController")
    // Handle initialization properly
}

public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}

required init?(coder: NSCoder) {
    super.init(coder: coder)
}

Option 2: Convert to XIB-based (Alternative)

Convert CampaignViewController from storyboard to XIB format like other controllers.

Option 3: Update Storyboard Loading Code

Ensure any code that loads the storyboard uses Bundle.frameworkBundle:

let storyboard = UIStoryboard(name: "Main", bundle: Bundle.frameworkBundle)
let vc = storyboard.instantiateViewController(withIdentifier: "CampaignViewController")

Conclusion

The issue is specifically with storyboard bundle resolution in SPM, not with class inclusion or module specifications. The XIB files work because they have proper bundle-aware initializers, while the storyboard-based CampaignViewController lacks this SPM-compatible initialization pattern.