Showing
12 changed files
with
88 additions
and
9 deletions
No preview for this file type
OBJC_ATTRIBUTES_FIX_SUMMARY.md
0 → 100644
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. |
No preview for this file type
... | @@ -7,7 +7,8 @@ | ... | @@ -7,7 +7,8 @@ |
7 | 7 | ||
8 | import UIKit | 8 | import UIKit |
9 | 9 | ||
10 | -@objc public class MyRewardsBannerOfferCollectionViewCell: UICollectionViewCell { | 10 | +@objc(MyRewardsBannerOfferCollectionViewCell) |
11 | +public class MyRewardsBannerOfferCollectionViewCell: UICollectionViewCell { | ||
11 | @IBOutlet weak var backgroundImage: UIImageView! | 12 | @IBOutlet weak var backgroundImage: UIImageView! |
12 | 13 | ||
13 | public override func awakeFromNib() { | 14 | public override func awakeFromNib() { | ... | ... |
... | @@ -12,7 +12,8 @@ protocol MyRewardsBannerOffersScrollTableViewCellDelegate: AnyObject { | ... | @@ -12,7 +12,8 @@ protocol MyRewardsBannerOffersScrollTableViewCellDelegate: AnyObject { |
12 | func didTapProfileButton() | 12 | func didTapProfileButton() |
13 | } | 13 | } |
14 | 14 | ||
15 | -@objc public class MyRewardsBannerOffersScrollTableViewCell: UITableViewCell { | 15 | +@objc(MyRewardsBannerOffersScrollTableViewCell) |
16 | +public class MyRewardsBannerOffersScrollTableViewCell: UITableViewCell { | ||
16 | @IBOutlet weak var tagView1: UIView! | 17 | @IBOutlet weak var tagView1: UIView! |
17 | @IBOutlet weak var tagLabel1: UILabel! | 18 | @IBOutlet weak var tagLabel1: UILabel! |
18 | @IBOutlet weak var tagView2: UIView! | 19 | @IBOutlet weak var tagView2: UIView! | ... | ... |
... | @@ -7,7 +7,8 @@ | ... | @@ -7,7 +7,8 @@ |
7 | 7 | ||
8 | import UIKit | 8 | import UIKit |
9 | 9 | ||
10 | -@objc public class MyRewardsOfferCollectionViewCell: UICollectionViewCell { | 10 | +@objc(MyRewardsOfferCollectionViewCell) |
11 | +public class MyRewardsOfferCollectionViewCell: UICollectionViewCell { | ||
11 | @IBOutlet weak var parentView: UIView! | 12 | @IBOutlet weak var parentView: UIView! |
12 | @IBOutlet weak var bannerImage: UIImageView! | 13 | @IBOutlet weak var bannerImage: UIImageView! |
13 | @IBOutlet weak var favoriteImage: UIImageView! | 14 | @IBOutlet weak var favoriteImage: UIImageView! | ... | ... |
... | @@ -11,7 +11,8 @@ protocol MyRewardsOffersScrollTableViewCellDelegate: AnyObject { | ... | @@ -11,7 +11,8 @@ protocol MyRewardsOffersScrollTableViewCellDelegate: AnyObject { |
11 | func didSelectOffer(_ offer: OfferModel) | 11 | func didSelectOffer(_ offer: OfferModel) |
12 | } | 12 | } |
13 | 13 | ||
14 | -@objc public class MyRewardsOffersScrollTableViewCell: UITableViewCell { | 14 | +@objc(MyRewardsOffersScrollTableViewCell) |
15 | +public class MyRewardsOffersScrollTableViewCell: UITableViewCell { | ||
15 | @IBOutlet weak var categoryLabel: UILabel! | 16 | @IBOutlet weak var categoryLabel: UILabel! |
16 | @IBOutlet weak var allButtonView: UIView! | 17 | @IBOutlet weak var allButtonView: UIView! |
17 | @IBOutlet weak var allButtonLabel: UILabel! | 18 | @IBOutlet weak var allButtonLabel: UILabel! | ... | ... |
... | @@ -11,7 +11,8 @@ protocol ProfileCouponFiltersTableViewCellDelegate: AnyObject { | ... | @@ -11,7 +11,8 @@ protocol ProfileCouponFiltersTableViewCellDelegate: AnyObject { |
11 | func didSelectFilter(_ filter: CouponFilterModel) | 11 | func didSelectFilter(_ filter: CouponFilterModel) |
12 | } | 12 | } |
13 | 13 | ||
14 | -@objc public class ProfileCouponFiltersTableViewCell: UITableViewCell { | 14 | +@objc(ProfileCouponFiltersTableViewCell) |
15 | +public class ProfileCouponFiltersTableViewCell: UITableViewCell { | ||
15 | @IBOutlet weak var titleLabel: UILabel! | 16 | @IBOutlet weak var titleLabel: UILabel! |
16 | @IBOutlet weak var collectionView: UICollectionView! | 17 | @IBOutlet weak var collectionView: UICollectionView! |
17 | 18 | ... | ... |
... | @@ -7,7 +7,8 @@ | ... | @@ -7,7 +7,8 @@ |
7 | 7 | ||
8 | import UIKit | 8 | import UIKit |
9 | 9 | ||
10 | -@objc public class ProfileCouponTableViewCell: UITableViewCell { | 10 | +@objc(ProfileCouponTableViewCell) |
11 | +public class ProfileCouponTableViewCell: UITableViewCell { | ||
11 | @IBOutlet weak var parentView: UIView! | 12 | @IBOutlet weak var parentView: UIView! |
12 | @IBOutlet weak var bannerImage: UIImageView! | 13 | @IBOutlet weak var bannerImage: UIImageView! |
13 | @IBOutlet weak var favoriteImage: UIImageView! | 14 | @IBOutlet weak var favoriteImage: UIImageView! | ... | ... |
... | @@ -7,7 +7,8 @@ | ... | @@ -7,7 +7,8 @@ |
7 | 7 | ||
8 | import UIKit | 8 | import UIKit |
9 | 9 | ||
10 | -@objc public class ProfileFilterCollectionViewCell: UICollectionViewCell { | 10 | +@objc(ProfileFilterCollectionViewCell) |
11 | +public class ProfileFilterCollectionViewCell: UICollectionViewCell { | ||
11 | @IBOutlet weak var parentView: UIView! | 12 | @IBOutlet weak var parentView: UIView! |
12 | @IBOutlet weak var titleLabel: UILabel! | 13 | @IBOutlet weak var titleLabel: UILabel! |
13 | 14 | ... | ... |
... | @@ -7,7 +7,8 @@ | ... | @@ -7,7 +7,8 @@ |
7 | 7 | ||
8 | import UIKit | 8 | import UIKit |
9 | 9 | ||
10 | -@objc public class ProfileHeaderTableViewCell: UITableViewCell { | 10 | +@objc(ProfileHeaderTableViewCell) |
11 | +public class ProfileHeaderTableViewCell: UITableViewCell { | ||
11 | @IBOutlet weak var tagView1: UIView! | 12 | @IBOutlet weak var tagView1: UIView! |
12 | @IBOutlet weak var tagLabel1: UILabel! | 13 | @IBOutlet weak var tagLabel1: UILabel! |
13 | @IBOutlet weak var tagView2: UIView! | 14 | @IBOutlet weak var tagView2: UIView! | ... | ... |
... | @@ -7,7 +7,8 @@ | ... | @@ -7,7 +7,8 @@ |
7 | 7 | ||
8 | import UIKit | 8 | import UIKit |
9 | 9 | ||
10 | -@objc public class ProfileQuestionnaireTableViewCell: UITableViewCell { | 10 | +@objc(ProfileQuestionnaireTableViewCell) |
11 | +public class ProfileQuestionnaireTableViewCell: UITableViewCell { | ||
11 | @IBOutlet weak var questionnaireBannerImage: UIImageView! | 12 | @IBOutlet weak var questionnaireBannerImage: UIImageView! |
12 | 13 | ||
13 | public override func awakeFromNib() { | 14 | public override func awakeFromNib() { | ... | ... |
-
Please register or login to post a comment