Search code examples
objective-cioscocoa-touchcocoaobjective-c-category

Adding the same category to multiple classes


I have an Objective-C category that I'd like to add to multiple classes without duplicating the code contained in the category. I simply want to add the same methods to multiple classes.

I have existing categories on NSManagedObject subclasses (Book, Chapter, Page) and I would like to add common functionality throughout these subclasses in a clean and maintainable way.

One way would be to add the category to their common superclass (NSManagedObject), but that has the consequence of adding the category's methods to all NSManagedObject subclasses when I want to add the methods to three NSManagedObject subclasses (Book, Chapter, Page).

Another solution would be to subclass NSManagedObject and then have Book, Chapter, and Page inherit from that NSManagedObject subclass. This is the cleanest, most straight forward approach. The big downside with this approach is when the data model changes and Xcode regenerates the subclasses, it will reset them back to inheriting from NSManagedObject instead of SubclassedManagedObject. I'd like to avoid using something like mogenerator/Xmo'd if possible.

Is it possible to add a single category on multiple classes without duplicating code?

Thanks.


Solution

  • I'm still unaware of a clean way to do this in Objective-C, but with Swift 2.0 this can be implemented using Protocol Extensions by adding functions and/or properties to an existing protocol. The protocol can then be adopted by an arbitrary number of classes, structs, and/or enums.

    protocol Numbered {
        func number() -> Int
    }
    
    extension Numbered {
        func number() -> Int {
            return Int(arc4random()) % 10
        }
    }
    
    class Book : Numbered {
    
    }
    
    class Chapter : Numbered {
    
    }
    
    class Page : Numbered {
    
    }
    
    let myBook = Book()
    let myChapter = Chapter()
    let myPage = Page()
    
    print("myBook.number() = \(myBook.number())")
    print("myChapter.number() = \(myChapter.number())")
    print("myPage.number() = \(myPage.number())")
    

    correctly implements number() on all three classes (Book, Chapter, Page):

    myBook.number() = 5
    myChapter.number() = 2
    myPage.number() = 8