Hi everybody. I have an application written in Objective-C. Until recently, I continued to maintain it and write new features in Objective-C. It was decided to switch to Swift and implement all new features on Swift. As a result, I made a bridge between Objective-C and Swift. Added new classes in swift and imported them via bridge header. One of the tasks required adding functionality to an existing Objective-C class, but I decided to implement this by extending the Objective-C class in a swift file.
Example Objective-C class
Settings.h
#import <Foundation/Foundation.h>
@interface Settings : NSObject
- (instancetype)initWithDictionary:(NSDictionary *)dictionary;
- (BOOL)boolForKey:(NSString *)key;
@end
Settings.m
#import "Settings.h"
@implementation Settings {
NSDictionary *_dictionary;
}
- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
self = [super init];
if (self) {
_dictionary = dictionary;
}
return self;
}
- (BOOL)boolForKey:(NSString *)key {
return [[_dictionary objectForKey:key] boolValue];
}
@end
Swift extension
Settings+extension.swift
import Foundation
extension Settings {
@objc public func isFirstProperty() -> Bool {
return self.bool(forKey: "isFirstProperty")
}
@objc public func isSecondProperty() -> Bool {
return self.bool(forKey: "isSecondProperty")
}
}
Call example inside UICollectionViewController sub class
@implementation CollectionViewController {
Settings* _settings;
}
-(void)viewDidLoad {
[super viewDidLoad];
_settings = [[Settings alloc] initWithDictionary:someDictionary];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"reuseIdentifier" forIndexPath:indexPath];
if ([_settings isFirstProperty]) {
//Do something with cell according to firstProperty
} else if ([_settings isSecondProperty]) {
//Do something with cell according to secondProperty
}
return cell;
}
@end
I tested the app, everything worked great. I uploaded the app to the App Store. Almost from the beginning of the use of the new application by users, I began to receive crash reports.
Crash report
I could not understand what was the matter. But after I removed the Swift extensions and implemented them directly in the Objective-C class, the crashes stopped.
After removing Settings+extension.swift and implementing inside Settings.m/h
Example Objective-C class
Settings.h
#import <Foundation/Foundation.h>
@interface Settings : NSObject
- (instancetype)initWithDictionary:(NSDictionary *)dictionary;
- (BOOL)boolForKey:(NSString *)key;
- (BOOL)isFirstProperty;
- (BOOL)isSecondProperty;
@end
Settings.m
#import "Settings.h"
@implementation Settings {
NSDictionary *_dictionary;
}
- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
self = [super init];
if (self) {
_dictionary = dictionary;
}
return self;
}
- (BOOL)isFirstProperty {
return [[_dictionary objectForKey:key] boolValue];
}
- (BOOL)isSecondProperty {
return [[_dictionary objectForKey:key] boolValue];
}
@end
1. Can somebody explain, why I had crashes?
2. Is it ok to extend Objective-C classes like that?
3. What kind of issues I can expect during migration to swift ?from Objective-C? (Any literature that explore this topic?)
Thanks in advance!