malcommac / Owl

A declarative type-safe framework for building fast and flexible lists with UITableViews & UICollectionViews
MIT License
432 stars 31 forks source link

Cannot convert value of type 'Entity.Type' to expected argument type '[ElementRepresentable]' #43

Open tanstaafl856 opened 4 years ago

tanstaafl856 commented 4 years ago

Backing up and starting mostly over led me here...

EntityListSectionedTableVC [no loner REALLY a TavleViewController I guess] will sit beside and act as a selector for EntityDetailSectionedTableVC. I had that much working fine with JUST the default tableViews. Editing textFields in EntityDetailSectionedTableVC started retain cycle nightmares.

No Stroyboard. So no clear example found to indicate what I might be missing. .fromClass is as much as I have found to address it specifically. Guessing the HOW-TO section is missing some details or steps for the Storyboard free since going Storyboardless means handling a few things that normally just work? Or maybe something about the struct is causing problems? Any insights would be most appreciated. Thnx

// EntityListSectionedTableVC.swift

import UIKit
import GRDB
import OwlKit

class EntityListSectionedTableVC: UIViewController { //, UISearchBarDelegate, UISearchResultsUpdating

    private var entityListDirector: TableDirector?
    private var EntityObserver: TransactionObserver?

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
            // Start observing the database
        loadFromDB()
        }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
                // Stop observing the database
        EntityObserver = nil
        }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
        }

    override func viewDidLoad() {
        super.viewDidLoad()
        let EntityListViewAdapter = TableCellAdapter<Entity, EntityListViewCell>()
            // instead of load cell from storyboard it will be loaded by
            // reading the root view inside the xib with the same name of the class
        EntityListViewAdapter.reusableViewLoadSource = .fromClass
            // optionally you can also set a custom id
        EntityListViewAdapter.reusableViewIdentifier = "EntityListViewCell"
            // configure...
        EntityListViewAdapter.events.dequeue = { ctx in
            ctx.cell?.entity = ctx.element
            }
        entityListDirector?.registerCellAdapter(EntityListViewAdapter)
        entityListDirector?.rowHeight = .explicit(44.0)

    //        Cannot convert value of type 'Entity.Type' to expected argument type '[ElementRepresentable]'
    //        let newTableSection = TableSection(id: "sectionId", elements: Entity, header: "\(Entity.count) Entities", footer: nil)
        }

    func loadFromDB() {
        EntityObserver = TableChangeObserver()
        EntityObserver?.observes(eventsOfKind: .delete(tableName: "Entity"))
        EntityObserver?.observes(eventsOfKind: .insert(tableName: "Entity"))
        var namesInTable = [Entity]()
        do{
            try dbQueue.write { db in
                  // adding an observer fires 2 delegate methods
                    // 1st - databaseWillCommit() throws .........
                    // 2nd - databaseDidCommit(_ db: Database) ...
                db.add(transactionObserver: EntityObserver!, extent: .observerLifetime)
                db.afterNextTransactionCommit { _ in
                    print("db.afterNextTransactionCommit")
                    do {
                        try namesInTable = Entity.fetchAll(db, sql: "SELECT * FROM Entity")
                        } catch {
                            print("ERROR ---------- db.afterNextTransactionCommit -> try Entity.fetchOne(db, sql: 'SELECT * FROM Entity')")
                            }
                        }
                    }
                } catch {
                    print("ERROR ---------- try Entity.fetchOne(db, sql: 'SELECT * FROM Entity')")
                    }
        print(" ---\tnamesInTable\t\(namesInTable)")
        }
}

// Entity.swift

import GRDB
import OwlKit

struct Entity {
    // Prefer Int64 for auto-incremented database ids
    var id: Int64?
    var noteID: Int64?
    var contactID: Int64?
    var entityType: Int64?
    var name: String
    var created: Double
    var modified: Double
    }

// MARK: - Persistence
// Turn Entity into a Codable Record.
// See https://github.com/groue/GRDB.swift/blob/master/README.md#records
extension Entity:  Codable, FetchableRecord, PersistableRecord, MutablePersistableRecord {
    private enum Columns {
        static let id = Column(CodingKeys.id)
        static let noteID = Column(CodingKeys.noteID)
        static let contactID = Column(CodingKeys.contactID)
        static let entityType = Column(CodingKeys.entityType)
        static let name = Column(CodingKeys.name)
        static let created = Column(CodingKeys.created)
        static let modified = Column(CodingKeys.modified)
        }

    // Update a Entity id after it has been inserted in the database.
    mutating func didInsert(with rowID: Int64, for column: String?) {
        id = rowID
        }
}

/// https://github.com/malcommac/Owl#3.1
extension Entity: Equatable, ElementRepresentable { //ElementRepresentable
    var differenceIdentifier: String {
        return "\(self.name)_\(String(describing: self.id))"
        }

    func isContentEqual(to other: Differentiable) -> Bool {
        guard let other = other as? Entity else { return false }
        return other == self
        }

    func ==(lhs: Entity, rhs: Entity) -> Bool {
          // add more compare para,eters if && when needed...id should suffice
        return lhs.id == rhs.id
        }
}

// EntityListViewCell.swift

import GRDB
import OwlKit

/// https://github.com/malcommac/Owl#3.2
public class EntityListViewCell: UITableViewCell { // ElementRepresentable
    public var differenceIdentifier: String {
        return "EntityListViewCell"
        }

    // Define a property you set on adapter's dequeue event
    var entity: Entity? {
        didSet {
           // setup your UI according with instance data
            }
        }
}
tanstaafl856 commented 4 years ago

just noticed that the variable used in the how-to was explicitly defined above as []. making a corresponding change had no effect on the error msg