Manos Chorianopoulos

xib bundle issue fix

This diff is collapsed. Click to expand it.
1 -# NIB Loading Fix Summary
2 -
3 -## Problem Identified
4 -Your demo client was crashing with the error:
5 -```
6 -Could not load NIB in bundle: 'NSBundle .../SwiftWarplyFramework.framework' with name 'MyRewardsViewController'
7 -```
8 -
9 -## Root Cause
10 -The issue was that view controllers in the SwiftWarplyFramework were not properly specifying the NIB name and bundle when being instantiated. When your demo client tried to create these view controllers, iOS couldn't find the XIB files because it was looking in the wrong bundle.
11 -
12 -## Solution Applied
13 -Added proper initializers to all XIB-based view controllers in the framework:
14 -
15 -### Fixed View Controllers:
16 -1. **MyRewardsViewController**
17 -2. **ProfileViewController**
18 -3. **CouponViewController**
19 -
20 -### What Was Added:
21 -Each view controller now has these initializers:
22 -
23 -```swift
24 -// MARK: - Initializers
25 -public convenience init() {
26 - self.init(nibName: "ViewControllerName", bundle: Bundle(for: MyEmptyClass.self))
27 -}
28 -
29 -public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
30 - super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
31 -}
32 -
33 -required init?(coder: NSCoder) {
34 - super.init(coder: coder)
35 -}
36 -```
37 -
38 -## How to Use in Your Demo Client
39 -
40 -### ✅ Correct Usage (Now Works):
41 -```swift
42 -// Simple instantiation - uses convenience initializer
43 -let vc = MyRewardsViewController()
44 -navigationController?.pushViewController(vc, animated: true)
45 -
46 -// Or explicit instantiation
47 -let vc = MyRewardsViewController(nibName: "MyRewardsViewController", bundle: Bundle(for: MyEmptyClass.self))
48 -navigationController?.pushViewController(vc, animated: true)
49 -```
50 -
51 -### ❌ Previous Issue:
52 -Before the fix, when you tried to instantiate view controllers without specifying the bundle, iOS couldn't locate the XIB files in the framework bundle.
53 -
54 -## View Controllers That Don't Need This Fix:
55 -- **CampaignViewController** - Uses storyboard instantiation, not XIB files
56 -
57 -## Framework Structure:
58 -```
59 -SwiftWarplyFramework/
60 -├── SwiftWarplyFramework/
61 -│ ├── screens/
62 -│ │ ├── MyRewardsViewController/
63 -│ │ │ ├── MyRewardsViewController.swift ✅ Fixed
64 -│ │ │ └── MyRewardsViewController.xib
65 -│ │ ├── ProfileViewController/
66 -│ │ │ ├── ProfileViewController.swift ✅ Fixed
67 -│ │ │ └── ProfileViewController.xib
68 -│ │ ├── CouponViewController/
69 -│ │ │ ├── CouponViewController.swift ✅ Fixed
70 -│ │ │ └── CouponViewController.xib
71 -│ │ └── CampaignViewController.swift (Storyboard-based)
72 -│ └── Main.storyboard
73 -```
74 -
75 -## Testing Your Demo Client
76 -After updating your framework dependency, your demo client should now be able to:
77 -
78 -1. ✅ Build successfully (previous podspec fix)
79 -2. ✅ Run without crashing (this NIB loading fix)
80 -3. ✅ Instantiate and display all view controllers properly
81 -
82 -## Example Demo Client Code:
83 -```swift
84 -import SwiftWarplyFramework
85 -
86 -class ViewController: UIViewController {
87 -
88 - @IBAction func showMyRewards(_ sender: Any) {
89 - let vc = MyRewardsViewController()
90 - navigationController?.pushViewController(vc, animated: true)
91 - }
92 -
93 - @IBAction func showProfile(_ sender: Any) {
94 - let vc = ProfileViewController()
95 - navigationController?.pushViewController(vc, animated: true)
96 - }
97 -}
98 -```
99 -
100 -## Next Steps:
101 -1. Update your framework dependency to get these fixes
102 -2. Test your demo client to ensure it works properly
103 -3. All view controllers should now load and display correctly
104 -
105 -The framework is now properly configured for CocoaPods distribution with correct bundle references for all XIB-based view controllers.
...@@ -1405,6 +1405,7 @@ public final class WarplySDK { ...@@ -1405,6 +1405,7 @@ public final class WarplySDK {
1405 showDialog(controller, "Δεν υπάρχει σύνδεση", "Αυτή τη στιγμή βρίσκεσαι εκτός σύνδεσης. Παρακαλούμε βεβαιώσου ότι είσαι συνδεδεμένος στο διαδίκτυο και προσπάθησε ξανά.") 1405 showDialog(controller, "Δεν υπάρχει σύνδεση", "Αυτή τη στιγμή βρίσκεσαι εκτός σύνδεσης. Παρακαλούμε βεβαιώσου ότι είσαι συνδεδεμένος στο διαδίκτυο και προσπάθησε ξανά.")
1406 } else { 1406 } else {
1407 let tempCampaign = CampaignItemModel() 1407 let tempCampaign = CampaignItemModel()
1408 + // TODO: For consistency, consider changing to MyEmptyClass.resourceBundle()
1408 let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for: MyEmptyClass.self)) 1409 let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for: MyEmptyClass.self))
1409 let vc = storyboard.instantiateViewController(withIdentifier: "CampaignViewController") as! SwiftWarplyFramework.CampaignViewController 1410 let vc = storyboard.instantiateViewController(withIdentifier: "CampaignViewController") as! SwiftWarplyFramework.CampaignViewController
1410 let url = getMarketPassMapUrl() 1411 let url = getMarketPassMapUrl()
...@@ -1431,6 +1432,7 @@ public final class WarplySDK { ...@@ -1431,6 +1432,7 @@ public final class WarplySDK {
1431 showDialog(controller, "Δεν υπάρχει σύνδεση", "Αυτή τη στιγμή βρίσκεσαι εκτός σύνδεσης. Παρακαλούμε βεβαιώσου ότι είσαι συνδεδεμένος στο διαδίκτυο και προσπάθησε ξανά.") 1432 showDialog(controller, "Δεν υπάρχει σύνδεση", "Αυτή τη στιγμή βρίσκεσαι εκτός σύνδεσης. Παρακαλούμε βεβαιώσου ότι είσαι συνδεδεμένος στο διαδίκτυο και προσπάθησε ξανά.")
1432 } else { 1433 } else {
1433 if let superMarketCampaign = getSupermarketCampaign() { 1434 if let superMarketCampaign = getSupermarketCampaign() {
1435 + // TODO: For consistency, consider changing to MyEmptyClass.resourceBundle()
1434 let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for: MyEmptyClass.self)) 1436 let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for: MyEmptyClass.self))
1435 let vc = storyboard.instantiateViewController(withIdentifier: "CampaignViewController") as! SwiftWarplyFramework.CampaignViewController 1437 let vc = storyboard.instantiateViewController(withIdentifier: "CampaignViewController") as! SwiftWarplyFramework.CampaignViewController
1436 let url = constructCampaignUrl(superMarketCampaign) 1438 let url = constructCampaignUrl(superMarketCampaign)
......
...@@ -45,7 +45,7 @@ protocol MyRewardsBannerOffersScrollTableViewCellDelegate: AnyObject { ...@@ -45,7 +45,7 @@ protocol MyRewardsBannerOffersScrollTableViewCellDelegate: AnyObject {
45 45
46 46
47 // Register XIBs for collection view cells 47 // Register XIBs for collection view cells
48 - collectionView.register(UINib(nibName: "MyRewardsBannerOfferCollectionViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellWithReuseIdentifier: "MyRewardsBannerOfferCollectionViewCell") 48 + collectionView.register(UINib(nibName: "MyRewardsBannerOfferCollectionViewCell", bundle: MyEmptyClass.resourceBundle()), forCellWithReuseIdentifier: "MyRewardsBannerOfferCollectionViewCell")
49 49
50 // Fix background colors 50 // Fix background colors
51 collectionView.backgroundColor = UIColor.clear 51 collectionView.backgroundColor = UIColor.clear
......
...@@ -37,7 +37,7 @@ protocol MyRewardsOffersScrollTableViewCellDelegate: AnyObject { ...@@ -37,7 +37,7 @@ protocol MyRewardsOffersScrollTableViewCellDelegate: AnyObject {
37 allButtonLabel.frame.size.height = allButtonLabel.intrinsicContentSize.height 37 allButtonLabel.frame.size.height = allButtonLabel.intrinsicContentSize.height
38 38
39 // Register XIBs for collection view cells 39 // Register XIBs for collection view cells
40 - collectionView.register(UINib(nibName: "MyRewardsOfferCollectionViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellWithReuseIdentifier: "MyRewardsOfferCollectionViewCell") 40 + collectionView.register(UINib(nibName: "MyRewardsOfferCollectionViewCell", bundle: MyEmptyClass.resourceBundle()), forCellWithReuseIdentifier: "MyRewardsOfferCollectionViewCell")
41 41
42 // Fix background colors 42 // Fix background colors
43 collectionView.backgroundColor = UIColor.clear 43 collectionView.backgroundColor = UIColor.clear
......
...@@ -28,7 +28,7 @@ protocol ProfileCouponFiltersTableViewCellDelegate: AnyObject { ...@@ -28,7 +28,7 @@ protocol ProfileCouponFiltersTableViewCellDelegate: AnyObject {
28 titleLabel.text = "Τα κουπόνια μου" 28 titleLabel.text = "Τα κουπόνια μου"
29 29
30 // Register XIBs for collection view cells 30 // Register XIBs for collection view cells
31 - collectionView.register(UINib(nibName: "ProfileFilterCollectionViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellWithReuseIdentifier: "ProfileFilterCollectionViewCell") 31 + collectionView.register(UINib(nibName: "ProfileFilterCollectionViewCell", bundle: MyEmptyClass.resourceBundle()), forCellWithReuseIdentifier: "ProfileFilterCollectionViewCell")
32 32
33 // Fix background colors 33 // Fix background colors
34 // collectionView.backgroundColor = UIColor.clear 34 // collectionView.backgroundColor = UIColor.clear
......
...@@ -12,7 +12,7 @@ import UIKit ...@@ -12,7 +12,7 @@ import UIKit
12 12
13 // MARK: - Initializers 13 // MARK: - Initializers
14 public convenience init() { 14 public convenience init() {
15 - self.init(nibName: "CouponViewController", bundle: Bundle(for: MyEmptyClass.self)) 15 + self.init(nibName: "CouponViewController", bundle: MyEmptyClass.resourceBundle())
16 } 16 }
17 17
18 public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { 18 public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
......
...@@ -13,7 +13,7 @@ import UIKit ...@@ -13,7 +13,7 @@ import UIKit
13 13
14 // MARK: - Initializers 14 // MARK: - Initializers
15 public convenience init() { 15 public convenience init() {
16 - self.init(nibName: "MyRewardsViewController", bundle: Bundle(for: MyEmptyClass.self)) 16 + self.init(nibName: "MyRewardsViewController", bundle: MyEmptyClass.resourceBundle())
17 } 17 }
18 18
19 public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { 19 public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
...@@ -310,8 +310,8 @@ import UIKit ...@@ -310,8 +310,8 @@ import UIKit
310 // self.navigationController?.setNavigationBarHidden(true, animated: false) 310 // self.navigationController?.setNavigationBarHidden(true, animated: false)
311 311
312 // Register XIBs for table view cells 312 // Register XIBs for table view cells
313 - tableView.register(UINib(nibName: "MyRewardsBannerOffersScrollTableViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellReuseIdentifier: "MyRewardsBannerOffersScrollTableViewCell") 313 + tableView.register(UINib(nibName: "MyRewardsBannerOffersScrollTableViewCell", bundle: MyEmptyClass.resourceBundle()), forCellReuseIdentifier: "MyRewardsBannerOffersScrollTableViewCell")
314 - tableView.register(UINib(nibName: "MyRewardsOffersScrollTableViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellReuseIdentifier: "MyRewardsOffersScrollTableViewCell") 314 + tableView.register(UINib(nibName: "MyRewardsOffersScrollTableViewCell", bundle: MyEmptyClass.resourceBundle()), forCellReuseIdentifier: "MyRewardsOffersScrollTableViewCell")
315 315
316 // Set up table view 316 // Set up table view
317 tableView.delegate = self 317 tableView.delegate = self
...@@ -417,6 +417,7 @@ import UIKit ...@@ -417,6 +417,7 @@ import UIKit
417 417
418 private func openCampaignViewController(with index: Int) { 418 private func openCampaignViewController(with index: Int) {
419 419
420 + // TODO: For consistency, consider changing to MyEmptyClass.resourceBundle()
420 let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for: MyEmptyClass.self)) 421 let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for: MyEmptyClass.self))
421 if let vc = storyboard.instantiateViewController(withIdentifier: "CampaignViewController") as? SwiftWarplyFramework.CampaignViewController { 422 if let vc = storyboard.instantiateViewController(withIdentifier: "CampaignViewController") as? SwiftWarplyFramework.CampaignViewController {
422 // vc.campaignUrl = "https://warply.s3.amazonaws.com/dei/campaigns/DehEasterContest_stage/index.html" 423 // vc.campaignUrl = "https://warply.s3.amazonaws.com/dei/campaigns/DehEasterContest_stage/index.html"
...@@ -428,14 +429,14 @@ import UIKit ...@@ -428,14 +429,14 @@ import UIKit
428 } 429 }
429 430
430 private func openCouponViewController(with offer: OfferModel) { 431 private func openCouponViewController(with offer: OfferModel) {
431 - let vc = SwiftWarplyFramework.CouponViewController(nibName: "CouponViewController", bundle: Bundle(for: MyEmptyClass.self)) 432 + let vc = SwiftWarplyFramework.CouponViewController(nibName: "CouponViewController", bundle: MyEmptyClass.resourceBundle())
432 vc.coupon = offer 433 vc.coupon = offer
433 434
434 self.navigationController?.pushViewController(vc, animated: true) 435 self.navigationController?.pushViewController(vc, animated: true)
435 } 436 }
436 437
437 private func openProfileViewController() { 438 private func openProfileViewController() {
438 - let vc = SwiftWarplyFramework.ProfileViewController(nibName: "ProfileViewController", bundle: Bundle(for: MyEmptyClass.self)) 439 + let vc = SwiftWarplyFramework.ProfileViewController(nibName: "ProfileViewController", bundle: MyEmptyClass.resourceBundle())
439 440
440 self.navigationController?.pushViewController(vc, animated: true) 441 self.navigationController?.pushViewController(vc, animated: true)
441 } 442 }
......
...@@ -12,7 +12,7 @@ import UIKit ...@@ -12,7 +12,7 @@ import UIKit
12 12
13 // MARK: - Initializers 13 // MARK: - Initializers
14 public convenience init() { 14 public convenience init() {
15 - self.init(nibName: "ProfileViewController", bundle: Bundle(for: MyEmptyClass.self)) 15 + self.init(nibName: "ProfileViewController", bundle: MyEmptyClass.resourceBundle())
16 } 16 }
17 17
18 public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { 18 public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
...@@ -208,11 +208,11 @@ import UIKit ...@@ -208,11 +208,11 @@ import UIKit
208 setNavigationTitle("Το προφίλ μου") 208 setNavigationTitle("Το προφίλ μου")
209 209
210 // Register XIBs for table view cells 210 // Register XIBs for table view cells
211 - tableView.register(UINib(nibName: "ProfileHeaderTableViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellReuseIdentifier: "ProfileHeaderTableViewCell") 211 + tableView.register(UINib(nibName: "ProfileHeaderTableViewCell", bundle: MyEmptyClass.resourceBundle()), forCellReuseIdentifier: "ProfileHeaderTableViewCell")
212 - tableView.register(UINib(nibName: "ProfileQuestionnaireTableViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellReuseIdentifier: "ProfileQuestionnaireTableViewCell") 212 + tableView.register(UINib(nibName: "ProfileQuestionnaireTableViewCell", bundle: MyEmptyClass.resourceBundle()), forCellReuseIdentifier: "ProfileQuestionnaireTableViewCell")
213 - tableView.register(UINib(nibName: "MyRewardsOffersScrollTableViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellReuseIdentifier: "MyRewardsOffersScrollTableViewCell") 213 + tableView.register(UINib(nibName: "MyRewardsOffersScrollTableViewCell", bundle: MyEmptyClass.resourceBundle()), forCellReuseIdentifier: "MyRewardsOffersScrollTableViewCell")
214 - tableView.register(UINib(nibName: "ProfileCouponFiltersTableViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellReuseIdentifier: "ProfileCouponFiltersTableViewCell") 214 + tableView.register(UINib(nibName: "ProfileCouponFiltersTableViewCell", bundle: MyEmptyClass.resourceBundle()), forCellReuseIdentifier: "ProfileCouponFiltersTableViewCell")
215 - tableView.register(UINib(nibName: "ProfileCouponTableViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellReuseIdentifier: "ProfileCouponTableViewCell") 215 + tableView.register(UINib(nibName: "ProfileCouponTableViewCell", bundle: MyEmptyClass.resourceBundle()), forCellReuseIdentifier: "ProfileCouponTableViewCell")
216 216
217 // Set up table view 217 // Set up table view
218 tableView.delegate = self 218 tableView.delegate = self
...@@ -264,7 +264,7 @@ import UIKit ...@@ -264,7 +264,7 @@ import UIKit
264 } 264 }
265 265
266 private func openCouponViewController(with offer: OfferModel) { 266 private func openCouponViewController(with offer: OfferModel) {
267 - let vc = SwiftWarplyFramework.CouponViewController(nibName: "CouponViewController", bundle: Bundle(for: MyEmptyClass.self)) 267 + let vc = SwiftWarplyFramework.CouponViewController(nibName: "CouponViewController", bundle: MyEmptyClass.resourceBundle())
268 vc.coupon = offer 268 vc.coupon = offer
269 269
270 self.navigationController?.pushViewController(vc, animated: true) 270 self.navigationController?.pushViewController(vc, animated: true)
......