Manos Chorianopoulos

version 2.2.10 - code refinement

1 -# CampaignViewController Investigation Report
2 -
3 -## Issue
4 -"Unknown class CampaignViewController in Interface Builder file" error when using SPM, while XIB files work perfectly.
5 -
6 -## Investigation Findings
7 -
8 -### 1. Package.swift Analysis
9 -**GOOD**: `CampaignViewController.swift` is properly included in SPM target
10 -- File location: `SwiftWarplyFramework/SwiftWarplyFramework/screens/CampaignViewController.swift`
11 -- SPM path: `"SwiftWarplyFramework/SwiftWarplyFramework"`
12 -- The file is automatically included since no explicit `sources` parameter excludes it
13 -
14 -### 2. File Structure Comparison
15 -**GOOD**: File is in correct location
16 -- `CampaignViewController.swift` is in `screens/` directory (same as other working controllers)
17 -- Other working controllers: `ProfileViewController`, `CouponViewController`, `MyRewardsViewController`
18 -
19 -### 3. Class Declaration Analysis
20 -
21 -#### ❌ **PROBLEM IDENTIFIED**: Missing Convenience Initializer
22 -
23 -**CampaignViewController.swift:**
24 -```swift
25 -@objc public class CampaignViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler, CLLocationManagerDelegate, WKUIDelegate, UIScrollViewDelegate {
26 - @IBOutlet weak var webview: WKWebView!
27 -
28 - // NO convenience initializer for storyboard loading
29 - // NO explicit bundle handling
30 -}
31 -```
32 -
33 -**ProfileViewController.swift (WORKING):**
34 -```swift
35 -@objc public class ProfileViewController: UIViewController {
36 - @IBOutlet weak var tableView: UITableView!
37 -
38 - // MARK: - Initializers
39 - public convenience init() {
40 - self.init(nibName: "ProfileViewController", bundle: Bundle.frameworkBundle)
41 - }
42 -
43 - public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
44 - super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
45 - }
46 -
47 - required init?(coder: NSCoder) {
48 - super.init(coder: coder)
49 - }
50 -}
51 -```
52 -
53 -### 4. Key Differences
54 -
55 -| Aspect | CampaignViewController | ProfileViewController (Working) |
56 -|--------|----------------------|--------------------------------|
57 -| **Convenience Init** | ❌ Missing | ✅ Present with Bundle.frameworkBundle |
58 -| **Bundle Handling** | ❌ No explicit bundle | ✅ Uses Bundle.frameworkBundle |
59 -| **Storyboard vs XIB** | 📱 Storyboard-based | 📄 XIB-based |
60 -| **Class Declaration** | ✅ Public | ✅ Public |
61 -| **Access Modifiers** | ✅ Correct | ✅ Correct |
62 -
63 -### 5. Root Cause Analysis
64 -
65 -The issue is **NOT** with SPM inclusion but with **bundle resolution for storyboard-based view controllers**.
66 -
67 -**Why XIB controllers work:**
68 -- XIB controllers have explicit `Bundle.frameworkBundle` initializers
69 -- They handle bundle resolution correctly for SPM
70 -
71 -**Why CampaignViewController fails:**
72 -- Storyboard tries to instantiate the class but can't resolve the correct bundle
73 -- No convenience initializer to guide bundle resolution
74 -- SPM creates different bundle structure than CocoaPods
75 -
76 -### 6. Bundle Structure Difference
77 -
78 -**CocoaPods:**
79 -- Bundle: `SwiftWarplyFramework.framework`
80 -- Storyboard can find classes easily
81 -
82 -**SPM:**
83 -- Bundle: `SwiftWarplyFramework_SwiftWarplyFramework.bundle`
84 -- Storyboard needs explicit bundle guidance
85 -
86 -## Recommended Solutions
87 -
88 -### Option 1: Add Bundle-Aware Initializers (Recommended)
89 -Add the missing initializers to `CampaignViewController.swift`:
90 -
91 -```swift
92 -// MARK: - Initializers
93 -public convenience init() {
94 - let storyboard = UIStoryboard(name: "Main", bundle: Bundle.frameworkBundle)
95 - let vc = storyboard.instantiateViewController(withIdentifier: "CampaignViewController")
96 - // Handle initialization properly
97 -}
98 -
99 -public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
100 - super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
101 -}
102 -
103 -required init?(coder: NSCoder) {
104 - super.init(coder: coder)
105 -}
106 -```
107 -
108 -### Option 2: Convert to XIB-based (Alternative)
109 -Convert `CampaignViewController` from storyboard to XIB format like other controllers.
110 -
111 -### Option 3: Update Storyboard Loading Code
112 -Ensure any code that loads the storyboard uses `Bundle.frameworkBundle`:
113 -
114 -```swift
115 -let storyboard = UIStoryboard(name: "Main", bundle: Bundle.frameworkBundle)
116 -let vc = storyboard.instantiateViewController(withIdentifier: "CampaignViewController")
117 -```
118 -
119 -## Conclusion
120 -
121 -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.
1 -# CampaignViewController XIB Conversion - COMPLETION REPORT
2 -
3 -## 🎉 **ALL FIXES SUCCESSFULLY IMPLEMENTED!**
4 -
5 -### ✅ **Fix 1: XIB Initializers Added to CampaignViewController.swift**
6 -**STATUS: COMPLETE**
7 -```swift
8 -// MARK: - Initializers
9 -public convenience init() {
10 - self.init(nibName: "CampaignViewController", bundle: Bundle.frameworkBundle)
11 -}
12 -
13 -public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
14 - super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
15 -}
16 -
17 -required init?(coder: NSCoder) {
18 - super.init(coder: coder)
19 -}
20 -```
21 -
22 -### ✅ **Fix 2: XIB Added to Package.swift Resources**
23 -**STATUS: COMPLETE**
24 -```swift
25 -.process("screens/CampaignViewController/CampaignViewController.xib")
26 -```
27 -Added to SPM resources array - SPM will now properly bundle the XIB file.
28 -
29 -### ✅ **Fix 3: Module Specifications Removed from XIB**
30 -**STATUS: COMPLETE**
31 -```xml
32 -<!-- BEFORE -->
33 -<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="CampaignViewController" customModule="SwiftWarplyFramework" customModuleProvider="target">
34 -
35 -<!-- AFTER -->
36 -<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="CampaignViewController">
37 -```
38 -
39 -### ✅ **Fix 4: Webview Outlet Connected**
40 -**STATUS: COMPLETE** (Done by user)
41 -```xml
42 -<outlet property="webview" destination="RP2-DM-ew4" id="IfP-kr-pPH"/>
43 -```
44 -
45 -## 🏆 **FINAL VERIFICATION:**
46 -
47 -### **MyRewardsViewController Instantiation Code:**
48 -```swift
49 -private func openCampaignViewController(with index: Int) {
50 - let vc = SwiftWarplyFramework.CampaignViewController(nibName: "CampaignViewController", bundle: Bundle.frameworkBundle)
51 - vc.campaignUrl = contestUrls[index]
52 - vc.showHeader = false
53 - self.navigationController?.pushViewController(vc, animated: true)
54 -}
55 -```
56 -**PERFECT** - Uses XIB-based instantiation with proper bundle
57 -
58 -### **CampaignViewController Architecture:**
59 --**XIB-based initialization** - SPM compatible
60 --**Bundle-aware instantiation** - Uses `Bundle.frameworkBundle`
61 --**Proper outlet connections** - webview connected
62 --**SPM resource inclusion** - XIB bundled correctly
63 --**Module-agnostic XIB** - No hardcoded module references
64 -
65 -## 🎯 **RESULT:**
66 -
67 -**CampaignViewController is now fully SPM-compatible and follows the same proven pattern as all other XIB-based controllers in your framework.**
68 -
69 -### **What This Achieves:**
70 -1. **Eliminates "Unknown class" errors** in SPM builds
71 -2. **Consistent architecture** across all view controllers
72 -3. **Proper bundle resolution** for XIB files
73 -4. **Future-proof implementation** for SPM compatibility
74 -
75 -### **Testing Recommendations:**
76 -1. Clean and rebuild your SPM package
77 -2. Test CampaignViewController instantiation in your client app
78 -3. Verify webview loads correctly
79 -4. Confirm navigation works as expected
80 -
81 -**🚀 Your XIB conversion is complete and ready for production!**
1 -# CampaignViewController XIB Conversion Verification Report
2 -
3 -## 📋 **Verification Summary**
4 -
5 -I've thoroughly reviewed your XIB conversion implementation. Here's what I found:
6 -
7 -## ✅ **What's Working Correctly:**
8 -
9 -### 1. **MyRewardsViewController.swift - Perfect Implementation**
10 -```swift
11 -private func openCampaignViewController(with index: Int) {
12 - let vc = SwiftWarplyFramework.CampaignViewController(nibName: "CampaignViewController", bundle: Bundle.frameworkBundle)
13 - vc.campaignUrl = contestUrls[index]
14 - vc.showHeader = false
15 - self.navigationController?.pushViewController(vc, animated: true)
16 -}
17 -```
18 -**EXCELLENT**: You've correctly updated the instantiation to use XIB-based loading with `Bundle.frameworkBundle`
19 -
20 -### 2. **CampaignViewController.xib - Good Structure**
21 -**GOOD**: XIB file exists and has proper structure
22 -**GOOD**: Contains WKWebView with proper constraints
23 -**GOOD**: Has File's Owner connection to view
24 -
25 -### 3. **File Organization**
26 -**GOOD**: Moved to proper directory structure (`screens/CampaignViewController/`)
27 -**GOOD**: Both .swift and .xib files are present
28 -
29 -## ❌ **Critical Issues Found:**
30 -
31 -### 1. **Missing XIB-Based Initializers in CampaignViewController.swift**
32 -**PROBLEM**: The Swift file lacks the essential XIB-compatible initializers that all other controllers have.
33 -
34 -**MISSING CODE**:
35 -```swift
36 -// MARK: - Initializers
37 -public convenience init() {
38 - self.init(nibName: "CampaignViewController", bundle: Bundle.frameworkBundle)
39 -}
40 -
41 -public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
42 - super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
43 -}
44 -
45 -required init?(coder: NSCoder) {
46 - super.init(coder: coder)
47 -}
48 -```
49 -
50 -### 2. **XIB Module Specification Issue**
51 -**PROBLEM**: The XIB still has hardcoded module specifications:
52 -```xml
53 -customClass="CampaignViewController" customModule="SwiftWarplyFramework" customModuleProvider="target"
54 -```
55 -
56 -**SHOULD BE**:
57 -```xml
58 -customClass="CampaignViewController"
59 -```
60 -
61 -### 3. **Missing XIB from Package.swift**
62 -**PROBLEM**: The new XIB file is not included in SPM resources.
63 -
64 -**MISSING LINE** in Package.swift resources:
65 -```swift
66 -.process("screens/CampaignViewController/CampaignViewController.xib")
67 -```
68 -
69 -### 4. **Outlet Connection Issue**
70 -**PROBLEM**: XIB has no `webview` outlet connection, but Swift file expects `@IBOutlet weak var webview: WKWebView!`
71 -
72 -## 🔧 **Required Fixes:**
73 -
74 -### Fix 1: Add XIB Initializers to CampaignViewController.swift
75 -Add these initializers right after the class declaration:
76 -
77 -```swift
78 -@objc public class CampaignViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler, CLLocationManagerDelegate, WKUIDelegate, UIScrollViewDelegate {
79 - @IBOutlet weak var webview: WKWebView!
80 -
81 - // MARK: - Initializers
82 - public convenience init() {
83 - self.init(nibName: "CampaignViewController", bundle: Bundle.frameworkBundle)
84 - }
85 -
86 - public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
87 - super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
88 - }
89 -
90 - required init?(coder: NSCoder) {
91 - super.init(coder: coder)
92 - }
93 -
94 - // ... rest of your code
95 -```
96 -
97 -### Fix 2: Remove Module Specifications from XIB
98 -Remove `customModule="SwiftWarplyFramework" customModuleProvider="target"` from the XIB File's Owner.
99 -
100 -### Fix 3: Add XIB to Package.swift Resources
101 -Add this line to the resources array:
102 -```swift
103 -.process("screens/CampaignViewController/CampaignViewController.xib")
104 -```
105 -
106 -### Fix 4: Connect webview Outlet in XIB
107 -Connect the WKWebView in the XIB to the `webview` outlet in File's Owner.
108 -
109 -## 🎯 **Priority Order:**
110 -1. **CRITICAL**: Add XIB initializers to Swift file
111 -2. **CRITICAL**: Add XIB to Package.swift resources
112 -3. **HIGH**: Remove module specifications from XIB
113 -4. **MEDIUM**: Fix webview outlet connection
114 -
115 -## 📊 **Current Status:**
116 -- ✅ Instantiation code: **PERFECT**
117 -- ❌ Swift initializers: **MISSING**
118 -- ❌ SPM resources: **MISSING**
119 -- ⚠️ XIB module specs: **NEEDS FIX**
120 -- ⚠️ Outlet connections: **NEEDS FIX**
121 -
122 -Once these fixes are applied, your XIB conversion will be complete and SPM-compatible!
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
4 4
5 **Get started with SwiftWarplyFramework in just 5 minutes!** 5 **Get started with SwiftWarplyFramework in just 5 minutes!**
6 6
7 -**Version**: 2.2.9 | **Minimum iOS**: 17.0 | **Swift**: 5.0+ 7 +**Version**: 2.2.10 | **Minimum iOS**: 17.0 | **Swift**: 5.0+
8 8
9 --- 9 ---
10 10
...@@ -53,7 +53,7 @@ Choose your preferred installation method: ...@@ -53,7 +53,7 @@ Choose your preferred installation method:
53 ``` 53 ```
54 https://git.warp.ly/open-source/warply_sdk_framework.git 54 https://git.warp.ly/open-source/warply_sdk_framework.git
55 ``` 55 ```
56 -4. Select **Version**: `2.2.9` or **Up to Next Major** 56 +4. Select **Version**: `2.2.10` or **Up to Next Major**
57 5. Click **Add Package** 57 5. Click **Add Package**
58 6. Select **SwiftWarplyFramework** and click **Add Package** 58 6. Select **SwiftWarplyFramework** and click **Add Package**
59 59
...@@ -62,7 +62,7 @@ Add to your `Package.swift` dependencies: ...@@ -62,7 +62,7 @@ Add to your `Package.swift` dependencies:
62 62
63 ```swift 63 ```swift
64 dependencies: [ 64 dependencies: [
65 - .package(url: "https://git.warp.ly/open-source/warply_sdk_framework.git", from: "2.2.9") 65 + .package(url: "https://git.warp.ly/open-source/warply_sdk_framework.git", from: "2.2.10")
66 ] 66 ]
67 ``` 67 ```
68 68
...@@ -89,7 +89,7 @@ platform :ios, '17.0' ...@@ -89,7 +89,7 @@ platform :ios, '17.0'
89 target 'YourApp' do 89 target 'YourApp' do
90 use_frameworks! 90 use_frameworks!
91 91
92 - pod 'SwiftWarplyFramework', :git => 'https://git@git.warp.ly/open-source/warply_sdk_framework.git', :tag => '2.2.9' 92 + pod 'SwiftWarplyFramework', :git => 'https://git@git.warp.ly/open-source/warply_sdk_framework.git', :tag => '2.2.10'
93 end 93 end
94 ``` 94 ```
95 95
......
1 -# Module Name Analysis - SPM vs XIB Configuration
2 -
3 -## The Configuration Mystery Solved
4 -
5 -After examining the Package.swift file, I can now explain exactly what's happening with the module names.
6 -
7 -## Package.swift Configuration
8 -
9 -```swift
10 -let package = Package(
11 - name: "SwiftWarplyFramework", // Package name
12 - products: [
13 - .library(
14 - name: "SwiftWarplyFramework", // Library name
15 - targets: ["SwiftWarplyFramework"] // Target name
16 - ),
17 - ],
18 - targets: [
19 - .target(
20 - name: "SwiftWarplyFramework", // Target name
21 - path: "SwiftWarplyFramework/SwiftWarplyFramework", // Path to source
22 - // ... resources and dependencies
23 - ),
24 - ]
25 -)
26 -```
27 -
28 -## The Root Cause
29 -
30 -The issue is **NOT** with our Package.swift configuration. Everything is correctly named `SwiftWarplyFramework`. The problem is elsewhere.
31 -
32 -## Evidence Analysis
33 -
34 -### 1. Package Configuration ✅
35 -- **Package name**: `SwiftWarplyFramework`
36 -- **Library name**: `SwiftWarplyFramework`
37 -- **Target name**: `SwiftWarplyFramework`
38 -- **All consistent and correct**
39 -
40 -### 2. XIB Configuration ✅
41 -- **customModule**: `SwiftWarplyFramework`
42 -- **Matches the package/target name perfectly**
43 -
44 -### 3. Runtime Behavior ❌
45 -- **Error shows**: `_TtC41SwiftWarplyFramework_SwiftWarplyFramework40MyRewardsBannerOffersScrollTableViewCell`
46 -- **Bundle path**: `SwiftWarplyFramework_SwiftWarplyFramework.bundle`
47 -
48 -## The Real Issue
49 -
50 -The mangled name `SwiftWarplyFramework_SwiftWarplyFramework` suggests that **SPM is somehow duplicating the module name** during the build process, even though our configuration is correct.
51 -
52 -## Possible Causes
53 -
54 -### 1. SPM Build System Bug
55 -SPM might be generating incorrect module names due to the directory structure:
56 -```
57 -SwiftWarplyFramework/ # Root directory
58 -└── SwiftWarplyFramework/ # Target directory
59 - └── SwiftWarplyFramework/ # Source files
60 -```
61 -
62 -### 2. Client Integration Issue
63 -The way the client app is integrating the SPM package might be causing module name duplication.
64 -
65 -### 3. Xcode/SPM Version Issue
66 -This could be a known issue with certain versions of Xcode or SPM.
67 -
68 -## Debugging Steps
69 -
70 -### 1. Check Client's Package.resolved
71 -The client's `Package.resolved` file might show how SPM is resolving the module name.
72 -
73 -### 2. Check Build Logs
74 -The actual build logs would show what module name SPM is using during compilation.
75 -
76 -### 3. Test with Simplified Structure
77 -We could test if flattening the directory structure resolves the issue.
78 -
79 -## Immediate Solutions to Try
80 -
81 -### Option 1: Update XIB Module Name
82 -Change XIB files to use `SwiftWarplyFramework_SwiftWarplyFramework` as the module name.
83 -
84 -### Option 2: Remove Module Specification
85 -Remove `customModule` and `customModuleProvider` from XIB files entirely.
86 -
87 -### Option 3: Add Explicit Module Name
88 -Add an explicit `swiftSettings` to the target to force the module name.
89 -
90 -## Recommendation
91 -
92 -I recommend trying **Option 2 first** (removing module specification from XIB files) as this is the least invasive and most likely to work across different SPM configurations.
93 -
94 -## Next Steps
95 -
96 -1. Test removing module specification from one XIB file
97 -2. If that works, apply to all XIB files
98 -3. If that doesn't work, try updating to the duplicated module name
99 -4. Document the final solution for future reference
100 -
101 -The key insight is that our Package.swift is correct, but SPM is somehow generating a different module name than expected during the build process.
1 -# @objc Attributes Fix for SPM Class Resolution
2 -
3 -## Problem
4 -XIB files in SPM couldn't find Swift classes due to name mangling differences between CocoaPods and SPM, causing:
5 -```
6 -Unknown class _TtC41SwiftWarplyFramework_SwiftWarplyFramework40MyRewardsBannerOffersScrollTableViewCell in Interface Builder file.
7 -*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UITableViewCell 0x105f2d060> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key collectionView.'
8 -```
9 -
10 -## Solution
11 -Added explicit `@objc(ClassName)` attributes to all cell classes to provide stable, predictable class names for XIB file instantiation.
12 -
13 -## Classes Updated
14 -
15 -### Table View Cells:
16 -1. **MyRewardsBannerOffersScrollTableViewCell** - `@objc(MyRewardsBannerOffersScrollTableViewCell)`
17 -2. **MyRewardsOffersScrollTableViewCell** - `@objc(MyRewardsOffersScrollTableViewCell)`
18 -3. **ProfileCouponFiltersTableViewCell** - `@objc(ProfileCouponFiltersTableViewCell)`
19 -4. **ProfileHeaderTableViewCell** - `@objc(ProfileHeaderTableViewCell)`
20 -5. **ProfileQuestionnaireTableViewCell** - `@objc(ProfileQuestionnaireTableViewCell)`
21 -6. **ProfileCouponTableViewCell** - `@objc(ProfileCouponTableViewCell)`
22 -
23 -### Collection View Cells:
24 -7. **MyRewardsOfferCollectionViewCell** - `@objc(MyRewardsOfferCollectionViewCell)`
25 -8. **MyRewardsBannerOfferCollectionViewCell** - `@objc(MyRewardsBannerOfferCollectionViewCell)`
26 -9. **ProfileFilterCollectionViewCell** - `@objc(ProfileFilterCollectionViewCell)`
27 -
28 -## What This Fix Does
29 -
30 -### Before:
31 -- Swift name mangling in SPM: `_TtC41SwiftWarplyFramework_SwiftWarplyFramework40MyRewardsBannerOffersScrollTableViewCell`
32 -- XIB files couldn't find the class
33 -- Fell back to generic `UITableViewCell`
34 -- Crashed when trying to connect `collectionView` outlet
35 -
36 -### After:
37 -- Explicit Objective-C name: `MyRewardsBannerOffersScrollTableViewCell`
38 -- XIB files can reliably find the class
39 -- Proper class instantiation
40 -- All outlets connect correctly
41 -
42 -## Benefits
43 -
44 -1. **Stable Class Names** - XIB files always find the correct class regardless of Swift name mangling
45 -2. **SPM Compatibility** - Works consistently in SPM environments
46 -3. **CocoaPods Compatibility** - Maintains backward compatibility
47 -4. **No Swift Regression** - All Swift features and improvements remain intact
48 -5. **Industry Standard** - Common practice for Swift frameworks using XIB files
49 -
50 -## Testing
51 -
52 -After this fix, you should see:
53 -- No more "Unknown class" errors
54 -- Successful XIB instantiation
55 -- Proper outlet connections
56 -- No crashes related to key-value coding compliance
57 -
58 -## Files Modified
59 -
60 -1. `SwiftWarplyFramework/SwiftWarplyFramework/cells/MyRewardsBannerOffersScrollTableViewCell/MyRewardsBannerOffersScrollTableViewCell.swift`
61 -2. `SwiftWarplyFramework/SwiftWarplyFramework/cells/MyRewardsOffersScrollTableViewCell/MyRewardsOffersScrollTableViewCell.swift`
62 -3. `SwiftWarplyFramework/SwiftWarplyFramework/cells/ProfileCouponFiltersTableViewCell/ProfileCouponFiltersTableViewCell.swift`
63 -4. `SwiftWarplyFramework/SwiftWarplyFramework/cells/ProfileHeaderTableViewCell/ProfileHeaderTableViewCell.swift`
64 -5. `SwiftWarplyFramework/SwiftWarplyFramework/cells/ProfileQuestionnaireTableViewCell/ProfileQuestionnaireTableViewCell.swift`
65 -6. `SwiftWarplyFramework/SwiftWarplyFramework/cells/ProfileCouponTableViewCell/ProfileCouponTableViewCell.swift`
66 -7. `SwiftWarplyFramework/SwiftWarplyFramework/cells/MyRewardsOfferCollectionViewCell/MyRewardsOfferCollectionViewCell.swift`
67 -8. `SwiftWarplyFramework/SwiftWarplyFramework/cells/MyRewardsBannerOfferCollectionViewCell/MyRewardsBannerOfferCollectionViewCell.swift`
68 -9. `SwiftWarplyFramework/SwiftWarplyFramework/cells/ProfileFilterCollectionViewCell/ProfileFilterCollectionViewCell.swift`
69 -
70 -This fix should resolve the XIB class resolution issue and eliminate the `NSUnknownKeyException` crashes in SPM environments.
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
2 2
3 ## 🚀 Essential Guide for Developers 3 ## 🚀 Essential Guide for Developers
4 4
5 -**Version**: 2.2.9 | **iOS**: 17.0+ | **Swift**: 5.0+ 5 +**Version**: 2.2.10 | **iOS**: 17.0+ | **Swift**: 5.0+
6 6
7 --- 7 ---
8 8
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
10 10
11 ```ruby 11 ```ruby
12 # Podfile 12 # Podfile
13 -pod 'SwiftWarplyFramework', :git => 'https://git@git.warp.ly/open-source/warply_sdk_framework.git', :tag => 2.2.9 13 +pod 'SwiftWarplyFramework', :git => 'https://git@git.warp.ly/open-source/warply_sdk_framework.git', :tag => 2.2.10
14 ``` 14 ```
15 15
16 --- 16 ---
...@@ -323,7 +323,7 @@ func safeAPICall() { ...@@ -323,7 +323,7 @@ func safeAPICall() {
323 ## 🔍 Debug Info 323 ## 🔍 Debug Info
324 324
325 ```swift 325 ```swift
326 -print("SDK Version: 2.2.9") 326 +print("SDK Version: 2.2.10")
327 print("App UUID: \(WarplySDK.shared.appUuid)") 327 print("App UUID: \(WarplySDK.shared.appUuid)")
328 print("Merchant ID: \(WarplySDK.shared.merchantId)") 328 print("Merchant ID: \(WarplySDK.shared.merchantId)")
329 print("Language: \(WarplySDK.shared.applicationLocale)") 329 print("Language: \(WarplySDK.shared.applicationLocale)")
......
This diff is collapsed. Click to expand it.
1 Pod::Spec.new do |spec| 1 Pod::Spec.new do |spec|
2 2
3 spec.name = "SwiftWarplyFramework" 3 spec.name = "SwiftWarplyFramework"
4 - spec.version = "2.2.9" 4 + spec.version = "2.2.10"
5 spec.summary = "A framework used for several functionalities." 5 spec.summary = "A framework used for several functionalities."
6 6
7 spec.description = "This is the Warply framework used for react native or swift apps for analytics, push notifications and the functionality of the app." 7 spec.description = "This is the Warply framework used for react native or swift apps for analytics, push notifications and the functionality of the app."
...@@ -17,7 +17,7 @@ Pod::Spec.new do |spec| ...@@ -17,7 +17,7 @@ Pod::Spec.new do |spec|
17 17
18 spec.platform = :ios, "17.0" 18 spec.platform = :ios, "17.0"
19 19
20 - spec.source = { :git => "https://git.warp.ly/open-source/warply_sdk_framework.git", :tag => "2.2.9" } 20 + spec.source = { :git => "https://git.warp.ly/open-source/warply_sdk_framework.git", :tag => "2.2.10" }
21 # spec.public_header_files = "SwiftWarplyFramework.framework/Headers/*.h" 21 # spec.public_header_files = "SwiftWarplyFramework.framework/Headers/*.h"
22 22
23 # ==> OLD 23 # ==> OLD
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
7 <key>Pods-SwiftWarplyFramework.xcscheme_^#shared#^_</key> 7 <key>Pods-SwiftWarplyFramework.xcscheme_^#shared#^_</key>
8 <dict> 8 <dict>
9 <key>orderHint</key> 9 <key>orderHint</key>
10 - <integer>1</integer> 10 + <integer>0</integer>
11 </dict> 11 </dict>
12 </dict> 12 </dict>
13 </dict> 13 </dict>
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
7 <key>SwiftWarplyFramework.xcscheme_^#shared#^_</key> 7 <key>SwiftWarplyFramework.xcscheme_^#shared#^_</key>
8 <dict> 8 <dict>
9 <key>orderHint</key> 9 <key>orderHint</key>
10 - <integer>0</integer> 10 + <integer>1</integer>
11 </dict> 11 </dict>
12 </dict> 12 </dict>
13 </dict> 13 </dict>
......
...@@ -35,24 +35,6 @@ public class MyEmptyClass { ...@@ -35,24 +35,6 @@ public class MyEmptyClass {
35 #endif 35 #endif
36 } 36 }
37 37
38 - // NEW: Debug method to verify bundle contents
39 - public static func debugBundleContents() {
40 - #if DEBUG
41 - let bundle = Bundle.frameworkBundle
42 - print("🔍 [WarplySDK] Using bundle: \(bundle)")
43 - print("🔍 [WarplySDK] Bundle path: \(bundle.bundlePath)")
44 -
45 - // Check for XIB files
46 - let xibFiles = ["ProfileCouponFiltersTableViewCell", "ProfileHeaderTableViewCell", "ProfileQuestionnaireTableViewCell"]
47 - for xibName in xibFiles {
48 - if let xibPath = bundle.path(forResource: xibName, ofType: "nib") {
49 - print("✅ [WarplySDK] Found XIB: \(xibName) at \(xibPath)")
50 - } else {
51 - print("❌ [WarplySDK] Missing XIB: \(xibName)")
52 - }
53 - }
54 - #endif
55 - }
56 } 38 }
57 39
58 // MARK: - Bundle Extensions for SPM Support 40 // MARK: - Bundle Extensions for SPM Support
...@@ -77,19 +59,4 @@ extension Bundle { ...@@ -77,19 +59,4 @@ extension Bundle {
77 #endif 59 #endif
78 } 60 }
79 61
80 - // NEW: Safe XIB loading with fallback
81 - static func safeLoadNib(named name: String) -> UINib? {
82 - let bundle = Bundle.frameworkBundle
83 -
84 - // First, check if the XIB exists
85 - guard bundle.path(forResource: name, ofType: "nib") != nil else {
86 - print("❌ [WarplySDK] XIB file '\(name).xib' not found in bundle: \(bundle)")
87 - #if DEBUG
88 - MyEmptyClass.debugBundleContents()
89 - #endif
90 - return nil
91 - }
92 -
93 - return UINib(nibName: name, bundle: bundle)
94 - }
95 } 62 }
......
...@@ -7,103 +7,27 @@ ...@@ -7,103 +7,27 @@
7 7
8 import UIKit 8 import UIKit
9 9
10 -public class XIBLoader { 10 +public struct XIBLoader {
11 -
12 - /// Safely load a view controller from XIB with proper bundle resolution
13 - public static func loadViewController<T: UIViewController>(
14 - _ type: T.Type,
15 - nibName: String? = nil
16 - ) -> T? {
17 - let actualNibName = nibName ?? String(describing: type)
18 -
19 - guard Bundle.frameworkBundle.path(forResource: actualNibName, ofType: "nib") != nil else {
20 - print("❌ [WarplySDK] XIB file '\(actualNibName).xib' not found")
21 - return nil
22 - }
23 -
24 - return T(nibName: actualNibName, bundle: Bundle.frameworkBundle)
25 - }
26 -
27 - /// Safely load a table view cell from XIB
28 - public static func loadTableViewCell<T: UITableViewCell>(
29 - _ type: T.Type,
30 - nibName: String? = nil
31 - ) -> T? {
32 - let actualNibName = nibName ?? String(describing: type)
33 -
34 - guard let nib = Bundle.safeLoadNib(named: actualNibName) else {
35 - return nil
36 - }
37 -
38 - let objects = nib.instantiate(withOwner: nil, options: nil)
39 - return objects.first as? T
40 - }
41 -
42 - /// Verify all required XIB files are present
43 - public static func verifyXIBFiles() -> [String: Bool] {
44 - let requiredXIBs = [
45 - "ProfileViewController",
46 - "CouponViewController",
47 - "MyRewardsViewController",
48 - "ProfileCouponFiltersTableViewCell",
49 - "ProfileHeaderTableViewCell",
50 - "ProfileQuestionnaireTableViewCell",
51 - "MyRewardsOffersScrollTableViewCell",
52 - "ProfileCouponTableViewCell",
53 - "ProfileFilterCollectionViewCell",
54 - "MyRewardsOfferCollectionViewCell",
55 - "MyRewardsBannerOfferCollectionViewCell",
56 - "MyRewardsBannerOffersScrollTableViewCell"
57 - ]
58 -
59 - var results: [String: Bool] = [:]
60 - let bundle = Bundle.frameworkBundle
61 -
62 - for xibName in requiredXIBs {
63 - let exists = bundle.path(forResource: xibName, ofType: "nib") != nil
64 - results[xibName] = exists
65 -
66 - if exists {
67 - print("✅ [WarplySDK] XIB found: \(xibName)")
68 - } else {
69 - print("❌ [WarplySDK] XIB missing: \(xibName)")
70 - }
71 - }
72 -
73 - return results
74 - }
75 11
76 /// Safe registration of table view cells with XIB 12 /// Safe registration of table view cells with XIB
77 - public static func registerTableViewCell( 13 + public static func registerTableViewCell<T: UITableViewCell>(
78 _ tableView: UITableView, 14 _ tableView: UITableView,
79 - cellClass: AnyClass, 15 + cellClass: T.Type,
80 nibName: String, 16 nibName: String,
81 identifier: String 17 identifier: String
82 ) { 18 ) {
83 - if let nib = Bundle.safeLoadNib(named: nibName) { 19 + let nib = UINib(nibName: nibName, bundle: Bundle.frameworkBundle)
84 tableView.register(nib, forCellReuseIdentifier: identifier) 20 tableView.register(nib, forCellReuseIdentifier: identifier)
85 - print("✅ [WarplySDK] Registered table view cell: \(nibName)")
86 - } else {
87 - print("❌ [WarplySDK] Failed to register table view cell: \(nibName)")
88 - // Register a basic UITableViewCell as fallback
89 - tableView.register(UITableViewCell.self, forCellReuseIdentifier: identifier)
90 - }
91 } 21 }
92 22
93 /// Safe registration of collection view cells with XIB 23 /// Safe registration of collection view cells with XIB
94 - public static func registerCollectionViewCell( 24 + public static func registerCollectionViewCell<T: UICollectionViewCell>(
95 _ collectionView: UICollectionView, 25 _ collectionView: UICollectionView,
96 - cellClass: AnyClass, 26 + cellClass: T.Type,
97 nibName: String, 27 nibName: String,
98 identifier: String 28 identifier: String
99 ) { 29 ) {
100 - if let nib = Bundle.safeLoadNib(named: nibName) { 30 + let nib = UINib(nibName: nibName, bundle: Bundle.frameworkBundle)
101 collectionView.register(nib, forCellWithReuseIdentifier: identifier) 31 collectionView.register(nib, forCellWithReuseIdentifier: identifier)
102 - print("✅ [WarplySDK] Registered collection view cell: \(nibName)")
103 - } else {
104 - print("❌ [WarplySDK] Failed to register collection view cell: \(nibName)")
105 - // Register basic UICollectionViewCell as fallback
106 - collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: identifier)
107 - }
108 } 32 }
109 } 33 }
......
...@@ -338,11 +338,6 @@ import UIKit ...@@ -338,11 +338,6 @@ import UIKit
338 ) 338 )
339 } 339 }
340 340
341 - // Debug: Verify XIB files are available
342 - #if DEBUG
343 - let _ = XIBLoader.verifyXIBFiles()
344 - MyEmptyClass.debugBundleContents()
345 - #endif
346 } 341 }
347 342
348 public override func viewWillAppear(_ animated: Bool) { 343 public override func viewWillAppear(_ animated: Bool) {
......
...@@ -239,11 +239,6 @@ import UIKit ...@@ -239,11 +239,6 @@ import UIKit
239 ) 239 )
240 } 240 }
241 241
242 - // Debug: Verify XIB files are available
243 - #if DEBUG
244 - let _ = XIBLoader.verifyXIBFiles()
245 - MyEmptyClass.debugBundleContents()
246 - #endif
247 } 242 }
248 243
249 // MARK: Function 244 // MARK: Function
......
1 -# XIB Bundling Fix Summary for SPM
2 -
3 -## Problem
4 -The SwiftWarplyFramework was crashing when used via SPM with the error:
5 -```
6 -*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UITableViewCell 0x101a7a0c0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key collectionView.'
7 -```
8 -
9 -This indicated that XIB files were not being properly loaded from the correct bundle in SPM environments.
10 -
11 -## Root Cause
12 -- XIB files were bundled correctly in Package.swift but the bundle resolution was inconsistent
13 -- The framework was using `Bundle.frameworkBundle` but this wasn't always resolving to the correct bundle for XIB files in SPM
14 -- No error handling or debugging capabilities to identify bundle loading issues
15 -
16 -## Solution Overview
17 -We implemented a comprehensive fix with the following components:
18 -
19 -### 1. Enhanced Bundle Resolution (MyEmptyClass.swift)
20 -- **Added debugging capabilities** with `debugBundleContents()` method
21 -- **Improved Bundle.frameworkBundle** to always use `Bundle.module` for SPM
22 -- **Added safe XIB loading** with `Bundle.safeLoadNib(named:)` method
23 -- **Enhanced error handling** with fallback mechanisms
24 -
25 -### 2. New XIBLoader Utility Class (XIBLoader.swift)
26 -- **Centralized XIB loading** with proper error handling
27 -- **Safe registration methods** for table view and collection view cells
28 -- **XIB verification utilities** to check if all required XIB files are present
29 -- **Fallback mechanisms** when XIB files are missing
30 -
31 -### 3. Updated Package.swift
32 -- **Changed from `.copy` to `.process`** for XIB files to ensure proper bundling
33 -- This ensures XIB files are processed correctly by SPM's build system
34 -
35 -### 4. Updated View Controllers and Cells
36 -Updated the following files to use safe XIB loading:
37 -- `ProfileViewController.swift`
38 -- `MyRewardsViewController.swift`
39 -- `ProfileCouponFiltersTableViewCell.swift`
40 -- `MyRewardsOffersScrollTableViewCell.swift`
41 -
42 -## Key Changes Made
43 -
44 -### 1. MyEmptyClass.swift
45 -```swift
46 -// NEW: Debug method to verify bundle contents
47 -public static func debugBundleContents() {
48 - #if DEBUG
49 - let bundle = Bundle.frameworkBundle
50 - print("🔍 [WarplySDK] Using bundle: \(bundle)")
51 - print("🔍 [WarplySDK] Bundle path: \(bundle.bundlePath)")
52 -
53 - // Check for XIB files
54 - let xibFiles = ["ProfileCouponFiltersTableViewCell", "ProfileHeaderTableViewCell", "ProfileQuestionnaireTableViewCell"]
55 - for xibName in xibFiles {
56 - if let xibPath = bundle.path(forResource: xibName, ofType: "nib") {
57 - print("✅ [WarplySDK] Found XIB: \(xibName) at \(xibPath)")
58 - } else {
59 - print("❌ [WarplySDK] Missing XIB: \(xibName)")
60 - }
61 - }
62 - #endif
63 -}
64 -
65 -// NEW: Safe XIB loading with fallback
66 -static func safeLoadNib(named name: String) -> UINib? {
67 - let bundle = Bundle.frameworkBundle
68 -
69 - // First, check if the XIB exists
70 - guard bundle.path(forResource: name, ofType: "nib") != nil else {
71 - print("❌ [WarplySDK] XIB file '\(name).xib' not found in bundle: \(bundle)")
72 - #if DEBUG
73 - MyEmptyClass.debugBundleContents()
74 - #endif
75 - return nil
76 - }
77 -
78 - return UINib(nibName: name, bundle: bundle)
79 -}
80 -```
81 -
82 -### 2. XIBLoader.swift (New File)
83 -```swift
84 -public class XIBLoader {
85 - /// Safe registration of table view cells with XIB
86 - public static func registerTableViewCell(
87 - _ tableView: UITableView,
88 - cellClass: AnyClass,
89 - nibName: String,
90 - identifier: String
91 - ) {
92 - if let nib = Bundle.safeLoadNib(named: nibName) {
93 - tableView.register(nib, forCellReuseIdentifier: identifier)
94 - print("✅ [WarplySDK] Registered table view cell: \(nibName)")
95 - } else {
96 - print("❌ [WarplySDK] Failed to register table view cell: \(nibName)")
97 - // Register a basic UITableViewCell as fallback
98 - tableView.register(UITableViewCell.self, forCellReuseIdentifier: identifier)
99 - }
100 - }
101 -
102 - /// Safe registration of collection view cells with XIB
103 - public static func registerCollectionViewCell(
104 - _ collectionView: UICollectionView,
105 - cellClass: AnyClass,
106 - nibName: String,
107 - identifier: String
108 - ) {
109 - if let nib = Bundle.safeLoadNib(named: nibName) {
110 - collectionView.register(nib, forCellWithReuseIdentifier: identifier)
111 - print("✅ [WarplySDK] Registered collection view cell: \(nibName)")
112 - } else {
113 - print("❌ [WarplySDK] Failed to register collection view cell: \(nibName)")
114 - // Register basic UICollectionViewCell as fallback
115 - collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: identifier)
116 - }
117 - }
118 -
119 - /// Verify all required XIB files are present
120 - public static func verifyXIBFiles() -> [String: Bool] {
121 - // Implementation checks all XIB files and returns status
122 - }
123 -}
124 -```
125 -
126 -### 3. Package.swift
127 -```swift
128 -resources: [
129 - .process("Media.xcassets"),
130 - .process("fonts"),
131 - .process("Main.storyboard"),
132 - // Change from .copy to .process for XIB files to ensure proper bundling
133 - .process("cells/ProfileCouponFiltersTableViewCell/ProfileCouponFiltersTableViewCell.xib"),
134 - .process("cells/ProfileHeaderTableViewCell/ProfileHeaderTableViewCell.xib"),
135 - .process("cells/ProfileQuestionnaireTableViewCell/ProfileQuestionnaireTableViewCell.xib"),
136 - // ... all other XIB files
137 -]
138 -```
139 -
140 -### 4. View Controller Updates
141 -```swift
142 -// OLD: Direct XIB registration
143 -tableView.register(UINib(nibName: "ProfileHeaderTableViewCell", bundle: Bundle.frameworkBundle), forCellReuseIdentifier: "ProfileHeaderTableViewCell")
144 -
145 -// NEW: Safe XIB registration with error handling
146 -private func registerTableViewCells() {
147 - let cellConfigs = [
148 - ("ProfileHeaderTableViewCell", "ProfileHeaderTableViewCell"),
149 - ("ProfileQuestionnaireTableViewCell", "ProfileQuestionnaireTableViewCell"),
150 - // ... other cells
151 - ]
152 -
153 - for (nibName, identifier) in cellConfigs {
154 - XIBLoader.registerTableViewCell(
155 - tableView,
156 - cellClass: UITableViewCell.self,
157 - nibName: nibName,
158 - identifier: identifier
159 - )
160 - }
161 -
162 - // Debug: Verify XIB files are available
163 - #if DEBUG
164 - let _ = XIBLoader.verifyXIBFiles()
165 - MyEmptyClass.debugBundleContents()
166 - #endif
167 -}
168 -```
169 -
170 -## Benefits of This Solution
171 -
172 -### 1. **Robust Error Handling**
173 -- Graceful fallback when XIB files are missing
174 -- Detailed logging to identify issues
175 -- Prevents crashes with fallback cell registration
176 -
177 -### 2. **Better Debugging**
178 -- Debug output shows exactly which bundle is being used
179 -- Lists all XIB files and their availability
180 -- Easy to identify bundle resolution issues
181 -
182 -### 3. **Consistent Bundle Resolution**
183 -- Always uses the correct bundle for SPM (`Bundle.module`)
184 -- Maintains CocoaPods compatibility
185 -- Centralized bundle logic
186 -
187 -### 4. **Maintainable Code**
188 -- Centralized XIB loading logic in XIBLoader class
189 -- Consistent patterns across all view controllers
190 -- Easy to add new XIB files
191 -
192 -## Testing the Fix
193 -
194 -After implementing these changes:
195 -
196 -1. **Build the framework** to ensure no compilation errors
197 -2. **Test in SPM client** to verify XIB files load correctly
198 -3. **Check debug output** to confirm bundle resolution
199 -4. **Verify UI rendering** to ensure all cells display properly
200 -
201 -## Debug Output to Expect
202 -
203 -When running in debug mode, you should see output like:
204 -```
205 -🔍 [WarplySDK] Using bundle: Bundle.module
206 -🔍 [WarplySDK] Bundle path: /path/to/bundle
207 -✅ [WarplySDK] Found XIB: ProfileCouponFiltersTableViewCell at /path/to/xib
208 -✅ [WarplySDK] Registered table view cell: ProfileHeaderTableViewCell
209 -✅ [WarplySDK] Registered collection view cell: ProfileFilterCollectionViewCell
210 -```
211 -
212 -## Files Modified
213 -
214 -1. **SwiftWarplyFramework/SwiftWarplyFramework/MyEmptyClass.swift** - Enhanced bundle resolution
215 -2. **SwiftWarplyFramework/SwiftWarplyFramework/XIBLoader.swift** - New utility class
216 -3. **Package.swift** - Changed XIB bundling from .copy to .process
217 -4. **SwiftWarplyFramework/SwiftWarplyFramework/screens/ProfileViewController/ProfileViewController.swift** - Safe XIB loading
218 -5. **SwiftWarplyFramework/SwiftWarplyFramework/screens/MyRewardsViewController/MyRewardsViewController.swift** - Safe XIB loading
219 -6. **SwiftWarplyFramework/SwiftWarplyFramework/cells/ProfileCouponFiltersTableViewCell/ProfileCouponFiltersTableViewCell.swift** - Safe XIB loading
220 -7. **SwiftWarplyFramework/SwiftWarplyFramework/cells/MyRewardsOffersScrollTableViewCell/MyRewardsOffersScrollTableViewCell.swift** - Safe XIB loading
221 -
222 -## Build Fix Applied
223 -
224 -**Issue**: Missing UIKit import in MyEmptyClass.swift
225 -- **Error**: `cannot find type 'UINib' in scope`
226 -- **Fix**: Added `import UIKit` to MyEmptyClass.swift since we introduced UIKit dependencies (`UINib`, `UITableView`, `UICollectionView`)
227 -
228 -This comprehensive fix should resolve the `NSUnknownKeyException` crash and ensure XIB files are properly loaded in SPM environments.
1 -# XIB Investigation Report - SPM Class Resolution Issue
2 -
3 -## Investigation Summary
4 -
5 -I have thoroughly investigated the XIB bundling and class resolution issue. Here are my findings:
6 -
7 -## ✅ What's Working Correctly
8 -
9 -### 1. XIB File Configuration
10 -**GOOD NEWS**: The XIB files are configured correctly!
11 -
12 -**MyRewardsBannerOffersScrollTableViewCell.xib**:
13 -```xml
14 -<tableViewCell ... customClass="MyRewardsBannerOffersScrollTableViewCell" customModule="SwiftWarplyFramework" customModuleProvider="target">
15 -```
16 -
17 -**ProfileHeaderTableViewCell.xib**:
18 -```xml
19 -<tableViewCell ... customClass="ProfileHeaderTableViewCell" customModule="SwiftWarplyFramework" customModuleProvider="target">
20 -```
21 -
22 --**Class names are clean** (not mangled)
23 --**Module is correctly set** to "SwiftWarplyFramework"
24 --**Module provider is "target"** (correct for SPM)
25 -
26 -### 2. Swift Class Configuration
27 -**ALSO GOOD**: Our @objc attributes are correctly applied:
28 -
29 -```swift
30 -@objc(MyRewardsBannerOffersScrollTableViewCell)
31 -public class MyRewardsBannerOffersScrollTableViewCell: UITableViewCell {
32 -```
33 -
34 -### 3. XIB Bundling
35 -**WORKING**: Our debug output shows XIB files are found and loaded:
36 -```
37 -✅ [WarplySDK] Found XIB: MyRewardsBannerOffersScrollTableViewCell at .../MyRewardsBannerOffersScrollTableViewCell.nib
38 -```
39 -
40 -## ❌ The Real Problem
41 -
42 -### Root Cause Analysis
43 -The issue is **NOT** with our XIB configuration or @objc attributes. The problem is more fundamental:
44 -
45 -**The error shows the mangled name**: `_TtC41SwiftWarplyFramework_SwiftWarplyFramework40MyRewardsBannerOffersScrollTableViewCell`
46 -
47 -This suggests that **somewhere in the runtime**, the system is still trying to resolve the class using the mangled Swift name instead of our clean @objc name.
48 -
49 -## 🔍 Key Findings
50 -
51 -### 1. XIB Files Are Correctly Configured
52 -- Class names: `MyRewardsBannerOffersScrollTableViewCell` (clean)
53 -- Module: `SwiftWarplyFramework`
54 -- Module provider: `target`
55 -
56 -### 2. Swift Classes Have Correct @objc Attributes
57 -- `@objc(MyRewardsBannerOffersScrollTableViewCell)` is properly applied
58 -
59 -### 3. The Disconnect
60 -- XIB expects: `MyRewardsBannerOffersScrollTableViewCell`
61 -- Runtime is looking for: `_TtC41SwiftWarplyFramework_SwiftWarplyFramework40MyRewardsBannerOffersScrollTableViewCell`
62 -
63 -## 🤔 Possible Causes
64 -
65 -### 1. Module Name Mismatch in SPM
66 -The XIB file specifies `customModule="SwiftWarplyFramework"`, but in SPM, the actual module name might be different (like `SwiftWarplyFramework_SwiftWarplyFramework`).
67 -
68 -### 2. Build System Issue
69 -The @objc attributes might not be taking effect during the SPM build process.
70 -
71 -### 3. Runtime Class Registration
72 -The class might not be properly registered with the Objective-C runtime under the @objc name.
73 -
74 -## 📋 Recommended Next Steps
75 -
76 -### Option 1: Module Name Investigation
77 -Check what the actual module name is in SPM vs what's in the XIB files.
78 -
79 -### Option 2: XIB Module Configuration
80 -Try changing the XIB files to use the actual SPM module name or remove the module specification entirely.
81 -
82 -### Option 3: Alternative @objc Approach
83 -Try using just `@objc` without the explicit name, or use `@objc` with the full module-qualified name.
84 -
85 -### Option 4: Bundle vs Module Issue
86 -The problem might be that we're using `customModuleProvider="target"` when we should be using something else for SPM.
87 -
88 -## 🎯 Immediate Action Items
89 -
90 -1. **Verify the actual module name** being used in SPM
91 -2. **Test XIB without module specification** (remove `customModule` and `customModuleProvider`)
92 -3. **Check if other XIB files have the same issue** or if it's specific to this one
93 -4. **Consider using programmatic cell creation** as a fallback if XIB issues persist
94 -
95 -## Conclusion
96 -
97 -The XIB files and Swift classes are configured correctly. The issue appears to be a deeper SPM module name resolution problem where the runtime is still using mangled names despite our @objc attributes.
...@@ -9,7 +9,7 @@ SwiftWarplyFramework is an iOS SDK that provides loyalty program functionality, ...@@ -9,7 +9,7 @@ SwiftWarplyFramework is an iOS SDK that provides loyalty program functionality,
9 - Minimum iOS Version: 17.0 9 - Minimum iOS Version: 17.0
10 - Swift Version: 5.0+ 10 - Swift Version: 5.0+
11 - Distribution: CocoaPods + Swift Package Manager (SPM) 11 - Distribution: CocoaPods + Swift Package Manager (SPM)
12 -- Framework Version: 2.2.9 12 +- Framework Version: 2.2.10
13 13
14 ### Dependencies 14 ### Dependencies
15 - RSBarcodes_Swift (~> 5.2.0) - Barcode scanning and generation 15 - RSBarcodes_Swift (~> 5.2.0) - Barcode scanning and generation
......
This diff is collapsed. Click to expand it.