Giter Site home page Giter Site logo

dentelezhkin / dtcollectionviewmanager Goto Github PK

View Code? Open in Web Editor NEW
314.0 12.0 30.0 3.88 MB

Protocol-oriented UICollectionView management, powered by generics and associated types.

License: MIT License

Ruby 0.85% Swift 98.89% Objective-C 0.25%
uicollectionview swift protocol delegate datasource ios

dtcollectionviewmanager's Introduction

Anurag's github stats

dtcollectionviewmanager's People

Contributors

artfeel avatar biow0lf avatar bitdeli-chef avatar dentelezhkin avatar orkenstein avatar readmecritic avatar rengate avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dtcollectionviewmanager's Issues

possible to have multiple model-types for a cell?

I'm wondering if there is a way to use different model-types for a collection-view cell.

I have two types: Book and Movie. Each type has a title, and an associated image.

What I'd like to do is use the same UICollectionViewCell (let's call it GenericCell) and register it so that a different type can be used, besides the one that is defined in the cell's ModelType.

Barring that, maybe a runtime transform?... so I could see "Oh the model is a Book, so transform it to a ImageTitle object". Then the ModelType and update routine would use ImageTitle even though the object from the data-source was actually a Book or Movie or whatever.

Separate classes?

Hello, I really like your extension, it's awesome!
But, do you think about separate controller and UIViewController classes. I think It will be better to encapsulate UICollectionView logic inside a NSObject-controller, and add it's as a property to your UIViewController. Because for example I use separate logic for views and controllers, using MVVM pattern, and this realisation sometimes is painfully for my architecture.
What do you think about this?

collectionview optional?

Hello! Why is collection view in DTCollectionViewManageable optional? It will be better if it is nonoptional value like in DTTableViewManageable

public protocol DTTableViewManageable : class
{
    /// Table view, that will be managed by DTTableViewManager
    var tableView : UITableView! { get }
}
public protocol DTCollectionViewManageable : class
{
    /// Collection view, that will be managed by DTCollectionViewManager
    var collectionView : UICollectionView? { get }
}

Quick start updates

DTCollectionViewManageable doesn't work with outlets like @IBOutlet weak var collectionView: UICollectionView!. Please, updates the Quick start documentation to use the following protocol DTCollectionViewNonOptionalManageable instead of the DTCollectionViewManageable for @outlet. Thanks.

Generic parameter 'T' could not be inferred.

After I updated to the swift 3 version (5.0.0-beta.2), this error shows up:

Generic parameter 'T' could not be inferred.

What I'm trying to do with my collection view is that I want to show a bunch of colors for the user to choose from. Here is the cell class:

class ColorCell: UICollectionViewCell, ModelTransfer {
    typealias ModelType = UIColor

    func update(with model: UIColor) {
        layer.cornerRadius = self.w / 2
        layer.borderWidth = 1.5
        self.backgroundColor = model
    }
}

Then, I wrote a method with this signature:

func selectedColor(_ cell: ColorCell, color: UIColor, indexPath: IndexPath) {

}

So far so good. But the error appears on this line:

manager.didSelect(ColorCell.self, ColorSelectorController.selectedColor)

It says that T cannot be inferred! But obviously T is ColorCell!

Clearer documentation examples

Took me a bit to time to get the order of setup & that I need to perform fetch on my NSFetchedResultsController

Here's my code:

    override func viewDidLoad() {
        super.viewDidLoad()

        let fetchRequest = NSFetchRequest(entityName: "Photograph")
        //fetchRequest.predicate = self.predicate
        fetchRequest.sortDescriptors = [NSSortDescriptor(key: "primaryKey", ascending: true)]

        let ctx = RKObjectManager.sharedManager().managedObjectStore.persistentStoreManagedObjectContext
        let frc = NSFetchedResultsController(fetchRequest: fetchRequest,
                                             managedObjectContext: ctx,
                                             sectionNameKeyPath: nil,
                                             cacheName: nil)

        do {
            try frc.performFetch()
        } catch {
            let fetchError = error as NSError
            print("\(fetchError), \(fetchError.userInfo)")
        }

        self.manager.storage = CoreDataStorage(fetchedResultsController: frc)
        self.manager.startManagingWithDelegate(self)
        self.manager.registerNiblessCellClass(GalleryImageCell)
    }

Function storageDidPerformUpdate Batch update error

Got this little ditty from the compiler as it threw an runtime exception

Invalid update: invalid number of items in section 0. The number of items contained in an existing section after the update (10) must be equal to the number of items contained in that section before the update (10), plus or minus the number of items inserted or deleted from that section (10 inserted, 0 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out).

Now i recall a year or so back running into the same problem when working with UICollectionViews and i did come up with a solution but it escapes me, luckily i believe someone else documented their struggles and solutions on the same problem.

any change of an update or would you like me to make a pull request? I wont be able to do so myself for a few days at least...Work deadlines and such.

Crash with nil header

In your method:

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
           viewForSupplementaryElementOfKind:(NSString *)kind
                                 atIndexPath:(NSIndexPath *)indexPath
{
    UICollectionReusableView <DTModelTransfer> *view = nil;
    id supplementary = nil;
    if ([self.storage respondsToSelector:@selector(supplementaryModelOfKind:forSectionIndex:)])
    {
        supplementary = [self.storage supplementaryModelOfKind:kind forSectionIndex:indexPath.section];
    }

    if (supplementary)
    {
        view = [self.factory supplementaryViewOfKind:kind
                                             forItem:supplementary
                                         atIndexPath:indexPath];
        [view updateWithModel:supplementary];
    }

    return view;
}

If no reusable view was registered, you will return nil. Since IOS7 it's create a crash.

Specifying Different Supplementary Views Per Section

How can I specify that I want a certain supplementary view to show up in a certain section of the collectionView?

Maybe i am missing where in the docs I can do this

e.x
Section 1 = HeaderViewOne
Section 2 = HeaderViewTwo
.
.
.
Section n = HeaderViewN

registerCellClass with no nibs

Currently I'm not using nibs nor storyboard, thus I just call registerCellClass:. When the CollectionView tries to dequeue a cell it raises an exception saying that no cell class has been registered.
The fix is easy, I just need to call collectionView?.registerClass(CellClass.self, forCellWithReuseIdentifier: "<reuse identifier that would be generated with reflection>") from my view controller.
This kind of stuff could go in the library itself, in my opinion. Also because if one day you change identifier, my code breaks.

What do you think?
Before I open a PR, I'd like to know if it would be enough to add the code above to an else clause in the registerCellClass: method or if there's no else clause because that's needed for storyboards compatibility: if no nib exists it means that the view is in the storyboard?

If that's the case, I propose to handle the pure (code only) case in the method registerCellClass: and add a new method registerCellClassWithNoStoryboardNorNib: that has the current implementation (suggestions for method names are appreciated!!).

(I'll obviously update the cousin registerSupplementaryClass: forKind: method)

startManagingWithDelegate crash

class: DTCollectionViewManager.swift
method: open func startManaging(withDelegate delegate : DTCollectionViewManageable)
line 204: guard let collectionView = delegate.collectionView ?? delegate.optionalCollectionView else {
preconditionFailure("Call startManagingWithDelegate: method only when UICollectionView has been created")
}

DTCollectionViewManager/DTCollectionViewManager.swift:204: Fatal error: Call startManagingWithDelegate: method only when UICollectionView has been created
2021-07-04 19:12:51.399824+0200 Doctorate[2073:95370] DTCollectionViewManager/DTCollectionViewManager.swift:204: Fatal error: Call startManagingWithDelegate: method only when UICollectionView has been created

How to establish @IBOutlet collectionView in Swift?

In order to use DTCollectionViewManager i'm trying to implement desired functionality in my DTCollectionViewController sub-class. However, I can not add @IBOutlet for collectionView.
What is best practice?
The following code:
@IBOutlet var collectionView: UICollectionView!

gives me compiler error:

Property 'collectionView' with type 'UICollectionView!' cannot override a property with type           'UICollectionView'
Setter for 'collectionView' with Objective-C selector 'setCollectionView:' conflicts with setter for       'collectionView' from superclass 'DTCollectionViewController' with the same Objective-C selector

How to get cell.indexPath in ModelTransfer#updateWithModel()?

updateWithModel() has an only parameter for the data model. How can I get the indexPath for the cell? UICollectionView#indexPathForCell doesn't work cause it returns nil when the cell is not visible.
DTCollectionViewManager#configureCell() doesn't get called on cell's dequeuing.

Crash when inserting items

CollectionViewManager crashes when it checks if it shouldReloadCollectionViewToPreventInsertFirstItemIssueForUpdate

In particular, I'm asynchronously adding new items to the manager:

private func contentLoaded(resources: [Container]?, error: ErrorType?) {
    print("content loaded")

    if resources != nil {
        manager.memoryStorage.addItems(resources!)
    }
}

The manager then checks:

for indexPath in update.insertedRowIndexPaths {
    if self.collectionView.numberOfItemsInSection(indexPath.section) == 0 {
        shouldReload = true
        break
    }
}

And crashes when calls self.collectionView.numberOfItemsInSection(indexPath.section) (in that moment, there were 0 sections with 0 items).
Removing those lines make the app work correctly.

I run the app on the iOS 9 Simulator.

Exception logged:

*** Assertion failure in -[UICollectionViewData numberOfItemsInSection:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3505.16/UICollectionViewData.m:566
2015-10-02 17:48:42.212 Sales App[82499:1913317] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'request for number of items in section 0 when there are only 0 sections in the collection view'

can you set more than one `configure` block for a cell class?

I was trying to do something where I was calling configure twice on the same cell class.

Looking at the configure code, it calls a routine named appendReaction, which made me think that I could do this. Ordering of the two blocks doesn't matter. But I noticed, while stepping through, that delegateWasReset gets called when the reaction is appended. The end result is that the second configure block is not called.

Anyway, just wondering if 2 configure blocks can be added to the same cell-class, and if so, how? If not, then I just need to know that.

Items get messed up when sections are added

Scrolling and reusing items seems to work fine when there are no sections present, but as soon as I add one, the list get laggy and jumpy. Also, the second section somehow overlaps some of the items.

The code (in a view, inside awakeFromNib):

manager.registerHeader(TimeHeader.self) { $0.condition = .section(0) } manager.registerHeader(TimeSectionHeader.self) { $0.condition = .section(1) } storage.setSectionHeaderModel(TimeHeaderModel(), forSection: 0) storage.setSectionHeaderModel(TimeSectionHeaderModel(timeDay: .monday), forSection: 1)

Then I'm simply adding models to storage as usual.

UICollectionView performBatchUpdates can trigger a crash if the collection view is flagged for layout

There's is a known issue with UICollectionView, that crashes application if reloadData call was sent prior to performBatchUpdates method.

Radar: https://openradar.appspot.com/28167779

Sample: https://github.com/PSPDFKit-labs/radar.apple.com/tree/master/28167779%20-%20CollectionViewBatchingIssue

Known workarounds - in terms of DTCollectionViewManager:

  • Do not call reloadData method manually, use other methods on MemoryStorage or CoreDataStorage
  • Try to group updates into single update block vs calling many blocks all at once - If needed drop to SectionModel level of abstraction.
  • You can implement your own CollectionViewUpdater, that calls reloadData instead of calling performBatchUpdates, however this will cost you animations, that will not be performed.

Any help or ideas how to implement maintainable solution are welcomed!

Crash if header/footer sizes set in Layout

For example layout:

_layout = [UICollectionViewFlowLayout new]; 
        _layout.scrollDirection = UICollectionViewScrollDirectionVertical;
        _layout.minimumLineSpacing = 10.f;
        _layout.minimumInteritemSpacing = 0;
        const CGFloat kHeaderHeight = 25.0f;
        _layout.headerReferenceSize = CGSizeMake(self.collectionView.width, 50.f);

Methods -

- (CGSize)collectionView:(UICollectionView *)collectionView
                 layout:(UICollectionViewFlowLayout *)collectionViewLayout
referenceSizeForHeaderInSection:(NSInteger)sectionNumber
{
    BOOL supplementaryModelNotNil = NO;
    if ([self.storage respondsToSelector:@selector(supplementaryModelOfKind:forSectionIndex:)])
    {
        supplementaryModelNotNil = ([self.storage supplementaryModelOfKind:UICollectionElementKindSectionHeader
                                                           forSectionIndex:sectionNumber]!=nil);
    }
    return supplementaryModelNotNil ? collectionViewLayout.headerReferenceSize : CGSizeZero;
}

- (CGSize)collectionView:(UICollectionView *)collectionView
                 layout:(UICollectionViewFlowLayout *)collectionViewLayout
referenceSizeForFooterInSection:(NSInteger)sectionNumber
{
    BOOL supplementaryModelNotNil = NO;
    if ([self.storage respondsToSelector:@selector(supplementaryModelOfKind:forSectionIndex:)])
    {
        supplementaryModelNotNil = ([self.storage supplementaryModelOfKind:UICollectionElementKindSectionFooter
                                                           forSectionIndex:sectionNumber]!=nil);
    }
    return supplementaryModelNotNil ? collectionViewLayout.footerReferenceSize : CGSizeZero;
}

Will never get called, so trick with CGSizeZero will not help, and app will crash.

Collection view lags

Hi!
I have one image in each cell and while scrolling collection view lags. Scrolling collection view jams loading cells.
Any solution for this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.