PowerKit is a generic way to implement UICollectionViewCompositionalLayout & UICollectionViewDiffableDataSource with more feature to save you're time, its use some of libraries to keep you'r work More Power , and you can using with WebService & Static List of data
• SkeletonView Used For Download content Style
• Moya Used as network layer
• SnapKit Used For setup UI Constraint
- iOS 14.0+ / Mac OS Catalyst M1+
- Xcode 13.0+
- Swift 5.0+
- If you found a bug, open an issue
- If you have a feature request, open an issue
- Use adelbios11@gmail.com to send email
Swift Package Manager is a tool for managing the distribution of Swift code. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies.
Xcode 11+ is required to build PowerKit using Swift Package Manager.
To integrate PowerKit into your Xcode project using Swift Package Manager, add it to the dependencies value of your Package.swift
:
dependencies: [
.package(url: "https://github.com/adelbios/PowerKit.git", .upToNextMajor(from: "1.0.15"))
]
This PowerKit divided into 4 paices of code to dealing with it
import PowerKit
Create struct or class model that implement Codable
& Hashable
protocols, Because we mentioned we use UICollectionViewDiffableDataSource
struct DemoModel: Codable, Hashable {
let title: String
let message: String
}
Create UICollectionViewCell
that inherit from PowerCollectionCell
and implement PowerCellDelegate
to pass data from viewModel into cell
import UIKit
import PowerKit
class DemoCell: PowerCollectionCell {
//MARK: - LifeCycle
override func setupViews() {
/*
Called what did you want here, don't forget add UI Component into contentView** rather than self,
becuase SekeletonView Layer works only with contentView
*/
//Call this function to enable SkeletonView animation layer for loading content
enableSkeletoneFor([self, stackView, titleLabel, messageLabel, ...etc])
}
}
//MARK: - PowerCellDelegate
extension DemoCell: PowerCellDelegate {
func configure(data: DemoModel) {
titleLabel.text = data.title
messageLabel.text = data.message
}
}
Create new ViewModel
that inherit from PowerViewModel
but set data type to it, this new viewModel
can be work with static data and webservice
import UIKit
import PowerKit
class DemoViewModel: PowerViewModel<DemoModel> {
//MARK: - Variables
private enum Cells {
typealias main = PowerModel<DemoCell, DemoModel>
}
//MARK: - Fetch Data from Internal
override func fetchStaticData() {
super.fetchStaticData()
self.addNew(items: [
Cells.main(item: .init(title: "Title A", message: "Message A")),
Cells.main(item: .init(title: "Title B", message: "Message B")),
Cells.main(item: .init(title: "Title C", message: "Message C")),
], forSection: 0)
}
override func configureViewModelSettings() {
settings()
}
override func handlePowerCellAction() {
handleCellsAction()
}
}
//MARK: - Helper
extension DemoViewModel {
func handleCellsAction() {
action.on(.didSelect) { (model: Cells.main, cell, indexPath) in
guard let model = model.item as? DemoModel else { return }
//You can push, present || dismiss using self.viewController, becase each viewMode have viewController
log(type: .success, model.title)
}
}
func settings() {
self.add(settings: [
.init(
section: 0,
layout: .vertical,
registeredCells: [.init(cell: DemoCell.self, skeletonCount: 10)]
)
])
}
}
just override these functions and call it in parent viewController
And take a look at the Moya to figure out how you can create target for web service
//If you want run request in background or not , default value is false
override var isLoadingInBackground: Bool {
return true
}
//MARK: - Make Https request
override func makeHTTPRequest() {
super.makeHTTPRequest()
//network.request(target: TargetType)
}
//MARK: - Post Request
override func postRequestAt(_ view: UIView) {
super.postRequestAt(view)
//network.request(target: TargetType, at: view, printOutResult: true, withProgress: true)
}
//MARK: - Fetch Next paging
override func fetchNextPaging() {
super.fetchNextPaging()
//guard let page = increaseCurrentPage(forSection: 0) else { return }
//network.request(DocumentsTarget.dummyAPI(page: page))
}
//MARK: - DidFetch Data Success
override func didFetchModels(_ model: DemoModel) {
//let cells = model.map({ Cells.main(item: $0) })
//self.updateLoadMore(forSection: 1 lastPage: 100)
//self.addNew(items: [cells], forSection: 0)
}
The Master of PowerKit
to be working just make yo're ViewController
inherit of PowerViewController and pass the Model
and ViewModel
to it
import UIKit
import PowerKit
class DemoViewController: PowerViewController<DemoModel, DemoViewModel> {
//MARK: - LifeCycle
override func viewDidLoad() {
super.viewDidLoad()
settings()
setupUI()
viewModel.fetchStaticData()
}
override func settingConfigure() {
powerSettings.isPullToRefreshUsed = true
powerSettings.loadContentType = .skeleton
}
override func showAlertForNoInternetConnection(title: String, message: String) {
}
}
//MARK: - Settings
extension DemoViewController {
func settings() {
collectionView.setInsit(.zero)
setBackground(color: .white)
collectionView.emptyView.configure(
viewType: .empty,
layoutPosition: .middle,
message: "Empty Data message"
)
}
func setupUI() {
setupCollectionViewConstraint(padding: .zero)
}
}
MIT License
Copyright (c) 2017 Juanpe Catalán
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.