How to make below code generic?

I have the below code which I am trying to make it generic.
The goals is

  1. getVM should always return FolderFileListViewModel instance where listener can only interested state event enum. ex. FolderFileListModelStates
    func getVM<T: FolderFileListModelStates>(listener: StateListListener) -> FolderFileListViewModel {
        return FolderFileListViewModelHandler<FolderFileListModelStates >(listener: listener)
    }
  1. Is there a way I can pass StateEvents Enum which I am interested in. like below.
extension MyController: StateListListener {
    func moved(to state: FolderFileListModelStates) {
        
    }
}

Existing code looks something like this.

protocol StateEvents {}

enum FolderFileListModelStates: StateEvents {
    case initiated, loading , listAvailable
}

protocol StateListViewModel {
    var listener: StateListListener {get}
    init(listener: StateListListener)
}

protocol StateListListener {
    func moved(to state: StateEvents)
}

protocol FolderFileListViewModel:StateListViewModel {
    func getFileList(for folderName:String, subFolderName:String)
}

class FolderFileListViewModelHandler: FolderFileListViewModel {
    private(set) var listener: StateListListener
    
    required init(listener: StateListListener) {
        self.listener = listener
    }
    
    func getFileList(for folderName: String, subFolderName: String) {
        
    }
}

class ViewModelHandlerFactory {
    private init() {}
    static let shared = ViewModelHandlerFactory()
    
    func getVM(listener: StateListListener) -> FolderFileListViewModel {
        return FolderFileListViewModelHandler(listener: listener)
    }
}

class MyController: UIViewController {
    func createViewModel()  {
        let handler = ViewModelHandlerFactory.shared.getVM(listener: self)

    }
}

extension MyController: StateListListener {
    func moved(to state: StateEvents) {
        
    }
}

I'm not sure I completely understand your structure, but from what I do understand, you might look into using phantom types. It could take some rethinking of how you've architected things so far, though.

protocol FolderFileListState {}

enum FolderFileListInitiated: FolderFileListState {}
enum FolderFileListLoading: FolderFileListState {}
enum FolderFileListAvailable: FolderFileListState {}

class FolderFileListViewModel<State: FolderFileListState> {
  //...
}

extension FolderFileListViewModel where State == FolderFileListInitiated {
  // methods/etc only possible when state is 'Initiated'
}

Adjust this as you see fit. It has its own upsides and downsides. It may not fit your use case at all. But just throwing the idea out there in case it's helpful!

Thanks @JuneBash .
What I am trying to achieve here is ViewModelHandlerFactory should return FolderFileListViewModel for FolderFileListModelStates.

Later on StateListViewModel could be used for a different ViewModel ex: SubFolderListViewModel. And in that case StateListListener should be constrained by implementing class I,e SubFolderListViewModelHandler to the SubFolderFileListModelStates.
Note: SubFolderFileListModelStates and FolderFileListModelStates are both types of StateEvents.

MyController should not know the underlying implementing class, this will be hidden by ViewModelHandlerFactory getVM Method.

So fo SubFolderVM it should be like this.

func getSubFolderVM(listener: StateListListener) -> SubFolderListViewModel {
        return SubFolderListViewModelHandler(listener: listener)
    }
Terms of Service

Privacy Policy

Cookie Policy