Wednesday, March 30, 2016

Convert ObjC to Swift (3)

In Swift, a class does not need to be based on NSObject, unlike ObjC. However, in order to make Swift class accessible to ObjC codes, a Swift class has to be based on NSObject. I found that if not, I would not see my swift class in [PrjectName]-Swift.h hidden header file. As a result, you would get compile time error about your class name is unknown identity.

NSObject as a Base Class for Swift Class

During the conversion process, I have to make my Swift class based on NSObject. This is quite easy to do.

  1. @objc
  2. class MyClass: NSManagedObject {
  3.  ...
  4. }

After all my ObjC classed converted to Swift, none of Swift classes is referenced by ObjC codes, I think I have to remove the base NSObject inheritance.

CoreData NSManagedObject

Xcode provides interface to generate Swift codes for managed object classes. For example, MyItem entity in Xcode data model, the ObjC files are:


corresponding Swift files are:


For the current Xcode version 7.2 and Swift 2.0, I found that there is one thing missing when you convert ObjC entity class with one to many relations to Swift. For examsle, the following ObjC codes are generated by Xcode long time ago (new Xcode 7.3 generated codes are different but similar):

  1. #import <Foundation/Foundation.h>
  2. #import <CoreData/CoreData.h>
  3. #import "MyItems.h"
  4. @interface MyEntity : NSManagedObject
  5. @property (nonatomic, retain) NSString * name;
  6. @property (nonatomic, retain) NSSet *myItems;
  7. @end
  8. @interface MyEntity (CoreDataGeneratedAccessors)
  9. - (void)addMyItemsObject:(MyItem *)value;
  10. - (void)removeMyItemsObject:(MyItem *)value;
  11. - (void)addMyItems:(NSSet *)values;
  12. - (void)removeMyItems:(NSSet *)values;
  13. @end

However, the auto-generated Swift codes in (Swift file, for example, MyItem+CoreDataProperties.swift) do not contain the corresponding methods.

  1. import Foundation
  2. import CoreData
  3. extension MyItem {
  4.    @NSManaged var name: String?
  5.    @NSManaged var myItems: NSSet?
  6. }

After searching from Internet, I found a solution to manually add those Swift codes. In stead of adding codes to the auto-generated codes, I think that it is better to create a new extension Swift file and to add the missing codes there.

  1. import Foundation
  2. extension MyItemItem {
  3.    // The current Xcode does not add the following methods
  4.    // This is what I manually added
  5.    @NSManaged func addMyItemsObject(value:MyItem)
  6.    @NSManaged func removeMyItemsObject(value:MyItem)
  7.    @NSManaged func addMyItems(value:Set<MyItem>)
  8.    @NSManaged func removeMyItems(value:Set<MyItem>)
  9. }