-2

Is it possible to add the same methods to different classes?

Example:

class FilterableTable: UITableViewController { ... }
class FilterableCollection: UICollectionViewController { ... }

extension FilterableTable, FilterableCollection { // I know this line is wrong
  func filterItems(){ print('filtered!') }
}

How can I add the same Foo method to a UICollectionViewController?

Protocols allow to declare only needed methods signatures, but I need exactly the same method (with body), to avoid copy-paste...

norlin
  • 1,205
  • 11
  • 24
  • https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Inheritance.html – Stefan Feb 08 '16 at 17:25
  • 1
    maybe you should create a category on your _model-layer_ for filtering... not on your _controller-layer_ – otherwise you'd need to copy-and-paste the body everywhere on your _contoller-layer_ when you'd need it. MVC. MVC. MVC. I know it is hard to be learned but it should be. – holex Feb 08 '16 at 17:34
  • @holex it's ok you're thinkin you're very smart. The problem is – I need it not for the model but for the views. To show/update buttons, controls etc depending on model's data. – norlin Feb 09 '16 at 06:13
  • @Stefan which part of this document will help with my question? Please, be specific. – norlin Feb 09 '16 at 06:19
  • @norlin, if you need a generic method for all views, that procedure called _inheritance_ and achieving that you need create a base class and your views are subsets of it and you could use your base-class's methods in every subset... but you can also create a _category_ for outlet arrays for filtering them; or if you still feel being stuck I recommend mastering OOP and MVC, before you start writing any code, kinda educational stuffs. – holex Feb 09 '16 at 09:23
  • @holex: you're completely right, but it's not about my question at all. Please, don't waste your time on this if you haven't read the question itself. – norlin Feb 09 '16 at 09:24
  • @norli, your question screams about you that you are lack of essential knowledge seriously; I guess you should educate yourself before you start wasting _the community's time_ here with your ambiguous question which is mostly based on the improper design patterns you'd intent to use. :( – holex Feb 09 '16 at 09:27
  • @holex I have 8 years programming experience (not with Swift). If you're so smart, please provide the answer with code example. – norlin Feb 09 '16 at 09:28
  • 1
    @norlin, then flush your 8 years' experience in toiler, because it is not Swift specific at all: you must have realised the fact of the common base class is `UIViewController`, and after adding an _extension_ to that base-class makes the method available in its subsets as well like in `UITableViewController` or `UICollectionViewController` (without copying-pasting anything!), and your problem could have been solved before you even had started to type this question... – holex Feb 09 '16 at 09:41
  • @holex Thanks, THAT is the answer. Finally! – norlin Feb 09 '16 at 09:43
  • @holex: and, BTW, the fact that my experience is not Swift specific is exactly the reason why I'm asking anything about Swift. – norlin Feb 09 '16 at 09:45
  • @norlin, the question seemed to me about OOP mostly rather than Swift (or ObjC) as you have known about the _extensions_ already which was the language specific part; finding the common base-class was generic OOP-related issue. :) – holex Feb 09 '16 at 09:54
  • @holex I knew about basic class, just haven't realized that Swift's extensions are affects subclasses as well. – norlin Feb 09 '16 at 09:56
  • @holex you're still wrong... With all your OOP & MVC ;) I've found a proper solution for Swift: just implement delegate. – norlin Feb 10 '16 at 06:36
  • @norlin, you don't need to reassure yourself. :) – holex Feb 10 '16 at 09:08

2 Answers2

3

You can use the Protocol Extensions to do what you need. Extensions are new and allow for a default implementation of the protocol methods. I modified your code just a bit so it would compile.

class FilterableTable: FilterType { 
    init() {}
}
class FilterableCollection: FilterType {  
    init() {}
}

protocol FilterType {
    func filterItems()
}
extension FilterType { // I know this line is wrong
  func filterItems(){ print("filtered!") }
}

let a = FilterableTable()
a.filterItems()

let b = FilterableCollection()
b.filterItems()

Check out the section on Protocol Extensions. Swift Programming Guide

Mr Beardsley
  • 3,743
  • 22
  • 28
  • I've tried this option, but XCode always crashes on such thing for me (not sure why, I have subclass with 2 protocols, including this one)… – norlin Feb 09 '16 at 06:14
  • 1
    The above should run all by itself in a playground. Give that a try and make sure it works for you. You might try to delete your derived data for the project to see if that clears things up. See the answer with the Xcode 7.2 update. http://stackoverflow.com/questions/18933321/deleting-contents-from-xcode-derived-data-folder – Mr Beardsley Feb 09 '16 at 13:56
  • Yes, this version is ok, but for me it crashes when extension has a `mutating` method: https://github.com/norlin/xcode-crash-protocol-extension – norlin Feb 10 '16 at 05:58
1

Actual answer: Use the Delegates, Luke!

class FilterableTable: UITableViewController {
    var filterDelegate: FilterDelegate! 
    func viewDidLoad(){
        filterDelegate = Filter()
    }
}
class FilterableCollection: UICollectionViewController {
    var filterDelegate: FilterDelegate! 
    func viewDidLoad(){
        filterDelegate = Filter()
    }
}

protocol FilterDelegate {
    func filterItems()
}

class Filter: FilterDelegate {
    func filterItems() {
        print("Hooray!")
    }
}
Community
  • 1
  • 1
norlin
  • 1,205
  • 11
  • 24