Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting Swift project into an easy-to-use framework for Cocoapods

So I need a bit of help since I can't really figure it out and have spent a lot of time on it already without any results. Most of the things I find on the internet are on how to convert a swift project into a framework, but my issue isn't the project itself or cocoapods, it's about how and what I should make accessible to developers.

So I built a Swift framework which you can find here, it's built with a UICollectionView with a custom flowlayout and side swiping functionality.

The problem is that I don't know how I can make this easy to use for developers, I'd like to make it behave like a UICollectionView where you'd need to implement a custom delegate and datasource without having to use the default UICollectionViewDelegate and UICollectionViewDatasource, so I can filter out things that would cause unexpected behaviour or just keep things simple.

So what would be a good approach here? I'm thinking about possibly subclassing the UICollectionView so people don't have to use a UICollectionView (because that might get confusing) but a VerticalCardSwiperView instead which has the same behaviour, but a bit more limited. I just don't know if that's the correct approach here.

Any tips, insights or good examples would be deeply appreciated!


edit 1: I updated the project so it already has the framework structure, I just need to figure out how I'm going to give access to the custom parts to developers.

edit 2: I have gotten one answer but I think the question might be easily misunderstood. The goal is to make it act and behave like a UICollectionView (with delegates, datasource, ...) but more limited, and I'm wondering how I can accomplish that, if it's even possible.

edit 3: Alright, I have most of it working, I'll leave a link to the Github online here so people who need something similar can check it out for themselves. Essentially, what I've done is made a custom VerticalCardSwiperDelegate and VerticalCardSwiperDatasource like this:

/// This datasource is used for providing data to the `VerticalCardSwiper`.
public protocol VerticalCardSwiperDatasource: class {

    /**
     Sets the number of cards for the `UICollectionView` inside the VerticalCardSwiperController.
     - parameter verticalCardSwiperView: The `VerticalCardSwiperView` where we set the amount of cards.
     - returns: an `Int` with the amount of cards we want to show.
     */
    func numberOfCards(verticalCardSwiperView: VerticalCardSwiperView) -> Int

    /**
     Asks your data source object for the cell that corresponds to the specified item in the `VerticalCardSwiper`.
     Your implementation of this method is responsible for creating, configuring, and returning the appropriate `CardCell` for the given item.
     - parameter verticalCardSwiperView: The `VerticalCardSwiperView` that will display the `CardCell`.
     - parameter index: The that the `CardCell` should be shown at.
     - returns: A CardCell object. The default value is an empty CardCell object.
    */
    func cardForItemAt(verticalCardSwiperView: VerticalCardSwiperView, cardForItemAt index: Int) -> CardCell
}

and then I've hooked those up inside the VerticalCardSwiper class:

public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

    return datasource?.numberOfCards(verticalCardSwiperView: verticalCardSwiperView) ?? 0
}

public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    return (datasource?.cardForItemAt(verticalCardSwiperView: verticalCardSwiperView, cardForItemAt: indexPath.row))!
}

And lastly, I've just subclassed the UICollectionView to a VerticalCardSwiperView and passed that as a paramater (since it's basically a subclass of the UICollectionView it does the same things, just has a different name, which is easier to understand for developers) for the delegate/datasource functions. Hope this helps someone else. Also, if you have a better approach, please let me know.

like image 302
JoniVR Avatar asked May 14 '18 13:05

JoniVR


1 Answers

It looks great!

I'd say that if you want to expose UICollectionView then follow the UITableView and it's approach with the UIScrollView subclassed delegates.

protocol VerticalCardSwiperDelegate: UICollectionViewDelegate {
  // ...

You can also subclass UICollectionViewDelegate and UICollectionViewDataSource in VerticalCardSwiperDelegate and VerticalCardSwiperDataSource delegates, respectively, for the same effect. (If you think it makes sense to do so.)

protocol VerticalCardSwiperDelegate: UICollectionViewDelegate {
  // ...

That said, your component is quite specific and maybe exposing the underlying UICollectionView could cause problems. Here, I'd lock all the implementation details away and make it VerticalCardSwiper all the way. This affords you the flexibility to complete change the underlying architecture.

For example, in your delegates, you would pass back VerticalCardSwiper rather than the underlying component..

func cardForItemAt(verticalCardSwiper: VerticalCardSwiper, cardForItemAt index: Int) -> CardCell {
  // ...

Generally, you want to keep the exposed interface as small as possible. This is to help guide the developers (there is less to learn) and less for you to maintain and field questions.

Some comments on the public interfaces would be helpful. I'm happy when I can command-alt-click to get some hints. You've already done this.

like image 66
Scott McKenzie Avatar answered Nov 13 '22 14:11

Scott McKenzie