Manos Chorianopoulos

xib bundle issue fix

This diff is collapsed. Click to expand it.
# NIB Loading Fix Summary
## Problem Identified
Your demo client was crashing with the error:
```
Could not load NIB in bundle: 'NSBundle .../SwiftWarplyFramework.framework' with name 'MyRewardsViewController'
```
## Root Cause
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.
## Solution Applied
Added proper initializers to all XIB-based view controllers in the framework:
### Fixed View Controllers:
1. **MyRewardsViewController**
2. **ProfileViewController**
3. **CouponViewController**
### What Was Added:
Each view controller now has these initializers:
```swift
// MARK: - Initializers
public convenience init() {
self.init(nibName: "ViewControllerName", bundle: Bundle(for: MyEmptyClass.self))
}
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
```
## How to Use in Your Demo Client
### ✅ Correct Usage (Now Works):
```swift
// Simple instantiation - uses convenience initializer
let vc = MyRewardsViewController()
navigationController?.pushViewController(vc, animated: true)
// Or explicit instantiation
let vc = MyRewardsViewController(nibName: "MyRewardsViewController", bundle: Bundle(for: MyEmptyClass.self))
navigationController?.pushViewController(vc, animated: true)
```
### ❌ Previous Issue:
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.
## View Controllers That Don't Need This Fix:
- **CampaignViewController** - Uses storyboard instantiation, not XIB files
## Framework Structure:
```
SwiftWarplyFramework/
├── SwiftWarplyFramework/
│ ├── screens/
│ │ ├── MyRewardsViewController/
│ │ │ ├── MyRewardsViewController.swift ✅ Fixed
│ │ │ └── MyRewardsViewController.xib
│ │ ├── ProfileViewController/
│ │ │ ├── ProfileViewController.swift ✅ Fixed
│ │ │ └── ProfileViewController.xib
│ │ ├── CouponViewController/
│ │ │ ├── CouponViewController.swift ✅ Fixed
│ │ │ └── CouponViewController.xib
│ │ └── CampaignViewController.swift (Storyboard-based)
│ └── Main.storyboard
```
## Testing Your Demo Client
After updating your framework dependency, your demo client should now be able to:
1. ✅ Build successfully (previous podspec fix)
2. ✅ Run without crashing (this NIB loading fix)
3. ✅ Instantiate and display all view controllers properly
## Example Demo Client Code:
```swift
import SwiftWarplyFramework
class ViewController: UIViewController {
@IBAction func showMyRewards(_ sender: Any) {
let vc = MyRewardsViewController()
navigationController?.pushViewController(vc, animated: true)
}
@IBAction func showProfile(_ sender: Any) {
let vc = ProfileViewController()
navigationController?.pushViewController(vc, animated: true)
}
}
```
## Next Steps:
1. Update your framework dependency to get these fixes
2. Test your demo client to ensure it works properly
3. All view controllers should now load and display correctly
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 {
showDialog(controller, "Δεν υπάρχει σύνδεση", "Αυτή τη στιγμή βρίσκεσαι εκτός σύνδεσης. Παρακαλούμε βεβαιώσου ότι είσαι συνδεδεμένος στο διαδίκτυο και προσπάθησε ξανά.")
} else {
let tempCampaign = CampaignItemModel()
// TODO: For consistency, consider changing to MyEmptyClass.resourceBundle()
let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for: MyEmptyClass.self))
let vc = storyboard.instantiateViewController(withIdentifier: "CampaignViewController") as! SwiftWarplyFramework.CampaignViewController
let url = getMarketPassMapUrl()
......@@ -1431,6 +1432,7 @@ public final class WarplySDK {
showDialog(controller, "Δεν υπάρχει σύνδεση", "Αυτή τη στιγμή βρίσκεσαι εκτός σύνδεσης. Παρακαλούμε βεβαιώσου ότι είσαι συνδεδεμένος στο διαδίκτυο και προσπάθησε ξανά.")
} else {
if let superMarketCampaign = getSupermarketCampaign() {
// TODO: For consistency, consider changing to MyEmptyClass.resourceBundle()
let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for: MyEmptyClass.self))
let vc = storyboard.instantiateViewController(withIdentifier: "CampaignViewController") as! SwiftWarplyFramework.CampaignViewController
let url = constructCampaignUrl(superMarketCampaign)
......
......@@ -45,7 +45,7 @@ protocol MyRewardsBannerOffersScrollTableViewCellDelegate: AnyObject {
// Register XIBs for collection view cells
collectionView.register(UINib(nibName: "MyRewardsBannerOfferCollectionViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellWithReuseIdentifier: "MyRewardsBannerOfferCollectionViewCell")
collectionView.register(UINib(nibName: "MyRewardsBannerOfferCollectionViewCell", bundle: MyEmptyClass.resourceBundle()), forCellWithReuseIdentifier: "MyRewardsBannerOfferCollectionViewCell")
// Fix background colors
collectionView.backgroundColor = UIColor.clear
......
......@@ -37,7 +37,7 @@ protocol MyRewardsOffersScrollTableViewCellDelegate: AnyObject {
allButtonLabel.frame.size.height = allButtonLabel.intrinsicContentSize.height
// Register XIBs for collection view cells
collectionView.register(UINib(nibName: "MyRewardsOfferCollectionViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellWithReuseIdentifier: "MyRewardsOfferCollectionViewCell")
collectionView.register(UINib(nibName: "MyRewardsOfferCollectionViewCell", bundle: MyEmptyClass.resourceBundle()), forCellWithReuseIdentifier: "MyRewardsOfferCollectionViewCell")
// Fix background colors
collectionView.backgroundColor = UIColor.clear
......
......@@ -28,7 +28,7 @@ protocol ProfileCouponFiltersTableViewCellDelegate: AnyObject {
titleLabel.text = "Τα κουπόνια μου"
// Register XIBs for collection view cells
collectionView.register(UINib(nibName: "ProfileFilterCollectionViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellWithReuseIdentifier: "ProfileFilterCollectionViewCell")
collectionView.register(UINib(nibName: "ProfileFilterCollectionViewCell", bundle: MyEmptyClass.resourceBundle()), forCellWithReuseIdentifier: "ProfileFilterCollectionViewCell")
// Fix background colors
// collectionView.backgroundColor = UIColor.clear
......
......@@ -12,7 +12,7 @@ import UIKit
// MARK: - Initializers
public convenience init() {
self.init(nibName: "CouponViewController", bundle: Bundle(for: MyEmptyClass.self))
self.init(nibName: "CouponViewController", bundle: MyEmptyClass.resourceBundle())
}
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
......
......@@ -13,7 +13,7 @@ import UIKit
// MARK: - Initializers
public convenience init() {
self.init(nibName: "MyRewardsViewController", bundle: Bundle(for: MyEmptyClass.self))
self.init(nibName: "MyRewardsViewController", bundle: MyEmptyClass.resourceBundle())
}
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
......@@ -310,8 +310,8 @@ import UIKit
// self.navigationController?.setNavigationBarHidden(true, animated: false)
// Register XIBs for table view cells
tableView.register(UINib(nibName: "MyRewardsBannerOffersScrollTableViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellReuseIdentifier: "MyRewardsBannerOffersScrollTableViewCell")
tableView.register(UINib(nibName: "MyRewardsOffersScrollTableViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellReuseIdentifier: "MyRewardsOffersScrollTableViewCell")
tableView.register(UINib(nibName: "MyRewardsBannerOffersScrollTableViewCell", bundle: MyEmptyClass.resourceBundle()), forCellReuseIdentifier: "MyRewardsBannerOffersScrollTableViewCell")
tableView.register(UINib(nibName: "MyRewardsOffersScrollTableViewCell", bundle: MyEmptyClass.resourceBundle()), forCellReuseIdentifier: "MyRewardsOffersScrollTableViewCell")
// Set up table view
tableView.delegate = self
......@@ -417,6 +417,7 @@ import UIKit
private func openCampaignViewController(with index: Int) {
// TODO: For consistency, consider changing to MyEmptyClass.resourceBundle()
let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for: MyEmptyClass.self))
if let vc = storyboard.instantiateViewController(withIdentifier: "CampaignViewController") as? SwiftWarplyFramework.CampaignViewController {
// vc.campaignUrl = "https://warply.s3.amazonaws.com/dei/campaigns/DehEasterContest_stage/index.html"
......@@ -428,14 +429,14 @@ import UIKit
}
private func openCouponViewController(with offer: OfferModel) {
let vc = SwiftWarplyFramework.CouponViewController(nibName: "CouponViewController", bundle: Bundle(for: MyEmptyClass.self))
let vc = SwiftWarplyFramework.CouponViewController(nibName: "CouponViewController", bundle: MyEmptyClass.resourceBundle())
vc.coupon = offer
self.navigationController?.pushViewController(vc, animated: true)
}
private func openProfileViewController() {
let vc = SwiftWarplyFramework.ProfileViewController(nibName: "ProfileViewController", bundle: Bundle(for: MyEmptyClass.self))
let vc = SwiftWarplyFramework.ProfileViewController(nibName: "ProfileViewController", bundle: MyEmptyClass.resourceBundle())
self.navigationController?.pushViewController(vc, animated: true)
}
......
......@@ -12,7 +12,7 @@ import UIKit
// MARK: - Initializers
public convenience init() {
self.init(nibName: "ProfileViewController", bundle: Bundle(for: MyEmptyClass.self))
self.init(nibName: "ProfileViewController", bundle: MyEmptyClass.resourceBundle())
}
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
......@@ -208,11 +208,11 @@ import UIKit
setNavigationTitle("Το προφίλ μου")
// Register XIBs for table view cells
tableView.register(UINib(nibName: "ProfileHeaderTableViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellReuseIdentifier: "ProfileHeaderTableViewCell")
tableView.register(UINib(nibName: "ProfileQuestionnaireTableViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellReuseIdentifier: "ProfileQuestionnaireTableViewCell")
tableView.register(UINib(nibName: "MyRewardsOffersScrollTableViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellReuseIdentifier: "MyRewardsOffersScrollTableViewCell")
tableView.register(UINib(nibName: "ProfileCouponFiltersTableViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellReuseIdentifier: "ProfileCouponFiltersTableViewCell")
tableView.register(UINib(nibName: "ProfileCouponTableViewCell", bundle: Bundle(for: MyEmptyClass.self)), forCellReuseIdentifier: "ProfileCouponTableViewCell")
tableView.register(UINib(nibName: "ProfileHeaderTableViewCell", bundle: MyEmptyClass.resourceBundle()), forCellReuseIdentifier: "ProfileHeaderTableViewCell")
tableView.register(UINib(nibName: "ProfileQuestionnaireTableViewCell", bundle: MyEmptyClass.resourceBundle()), forCellReuseIdentifier: "ProfileQuestionnaireTableViewCell")
tableView.register(UINib(nibName: "MyRewardsOffersScrollTableViewCell", bundle: MyEmptyClass.resourceBundle()), forCellReuseIdentifier: "MyRewardsOffersScrollTableViewCell")
tableView.register(UINib(nibName: "ProfileCouponFiltersTableViewCell", bundle: MyEmptyClass.resourceBundle()), forCellReuseIdentifier: "ProfileCouponFiltersTableViewCell")
tableView.register(UINib(nibName: "ProfileCouponTableViewCell", bundle: MyEmptyClass.resourceBundle()), forCellReuseIdentifier: "ProfileCouponTableViewCell")
// Set up table view
tableView.delegate = self
......@@ -264,7 +264,7 @@ import UIKit
}
private func openCouponViewController(with offer: OfferModel) {
let vc = SwiftWarplyFramework.CouponViewController(nibName: "CouponViewController", bundle: Bundle(for: MyEmptyClass.self))
let vc = SwiftWarplyFramework.CouponViewController(nibName: "CouponViewController", bundle: MyEmptyClass.resourceBundle())
vc.coupon = offer
self.navigationController?.pushViewController(vc, animated: true)
......