parent
4225a3b3cb
commit
749d4fbaf0
@ -0,0 +1,63 @@ |
|||||||
|
// |
||||||
|
// Array+UITableDataSource.swift |
||||||
|
// TournamentStats |
||||||
|
// |
||||||
|
// Created by Laurent Morvillier on 05/08/2019. |
||||||
|
// Copyright © 2019 Stax River. All rights reserved. |
||||||
|
// |
||||||
|
|
||||||
|
import Foundation |
||||||
|
import UIKit |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class DataSourceWrapper<T : ColumnRepresentable> : NSObject, UITableViewDataSource, UITableViewDelegate { |
||||||
|
|
||||||
|
var columnRepresentables: [T] |
||||||
|
|
||||||
|
init(array: [T]) { |
||||||
|
self.columnRepresentables = array |
||||||
|
} |
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { |
||||||
|
print("numberOfRowsInSection = \(self.columnRepresentables.count)") |
||||||
|
return self.columnRepresentables.count + 1 // + 1 for header |
||||||
|
} |
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { |
||||||
|
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! StackTableCell |
||||||
|
|
||||||
|
var columns: [String] |
||||||
|
var font: UIFont |
||||||
|
switch indexPath.row { |
||||||
|
case 0: |
||||||
|
columns = T.headers() |
||||||
|
font = UIFont.boldSystemFont(ofSize: 16.0) |
||||||
|
default: |
||||||
|
let cr = self.columnRepresentables[indexPath.row - 1] |
||||||
|
columns = cr.colums() |
||||||
|
font = UIFont.systemFont(ofSize: 16.0) |
||||||
|
} |
||||||
|
|
||||||
|
columns.forEach { value in |
||||||
|
let label: UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: 50, height: 30)) |
||||||
|
label.textColor = UIColor.black |
||||||
|
label.backgroundColor = UIColor.white |
||||||
|
label.text = value |
||||||
|
label.font = font |
||||||
|
cell.stackView.addArrangedSubview(label) |
||||||
|
} |
||||||
|
|
||||||
|
return cell |
||||||
|
} |
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { |
||||||
|
return 32.0 |
||||||
|
} |
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { |
||||||
|
return 0.1 |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,21 @@ |
|||||||
|
// |
||||||
|
// StackTableCell.swift |
||||||
|
// TournamentStats |
||||||
|
// |
||||||
|
// Created by Laurent Morvillier on 05/08/2019. |
||||||
|
// Copyright © 2019 Stax River. All rights reserved. |
||||||
|
// |
||||||
|
|
||||||
|
import Foundation |
||||||
|
import UIKit |
||||||
|
|
||||||
|
class StackTableCell: UITableViewCell { |
||||||
|
|
||||||
|
@IBOutlet weak var stackView: UIStackView! |
||||||
|
|
||||||
|
override func awakeFromNib() { |
||||||
|
self.backgroundColor = UIColor.clear |
||||||
|
self.stackView.distribution = .fillEqually |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,38 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> |
||||||
|
<device id="retina6_1" orientation="portrait"> |
||||||
|
<adaptation id="fullscreen"/> |
||||||
|
</device> |
||||||
|
<dependencies> |
||||||
|
<deployment identifier="iOS"/> |
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/> |
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> |
||||||
|
</dependencies> |
||||||
|
<objects> |
||||||
|
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/> |
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> |
||||||
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="aT2-pS-Iqw" customClass="StackTableCell" customModule="TournamentStats" customModuleProvider="target"> |
||||||
|
<rect key="frame" x="0.0" y="0.0" width="414" height="44"/> |
||||||
|
<autoresizingMask key="autoresizingMask"/> |
||||||
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="aT2-pS-Iqw" id="n6c-N8-BIo"> |
||||||
|
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/> |
||||||
|
<autoresizingMask key="autoresizingMask"/> |
||||||
|
<subviews> |
||||||
|
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="zyP-u3-Lbn"> |
||||||
|
<rect key="frame" x="8" y="0.0" width="398" height="43.5"/> |
||||||
|
</stackView> |
||||||
|
</subviews> |
||||||
|
<constraints> |
||||||
|
<constraint firstItem="zyP-u3-Lbn" firstAttribute="leading" secondItem="n6c-N8-BIo" secondAttribute="leading" constant="8" id="36S-42-88h"/> |
||||||
|
<constraint firstAttribute="bottom" secondItem="zyP-u3-Lbn" secondAttribute="bottom" id="9Fi-3O-haC"/> |
||||||
|
<constraint firstAttribute="trailing" secondItem="zyP-u3-Lbn" secondAttribute="trailing" constant="8" id="Aja-gu-ofx"/> |
||||||
|
<constraint firstItem="zyP-u3-Lbn" firstAttribute="top" secondItem="n6c-N8-BIo" secondAttribute="top" id="nko-dF-Ksc"/> |
||||||
|
</constraints> |
||||||
|
</tableViewCellContentView> |
||||||
|
<connections> |
||||||
|
<outlet property="stackView" destination="zyP-u3-Lbn" id="Odj-c0-t9N"/> |
||||||
|
</connections> |
||||||
|
<point key="canvasLocation" x="-57" y="102"/> |
||||||
|
</tableViewCell> |
||||||
|
</objects> |
||||||
|
</document> |
||||||
@ -0,0 +1,99 @@ |
|||||||
|
// |
||||||
|
// UIView+Extensions.swift |
||||||
|
// TournamentStats |
||||||
|
// |
||||||
|
// Created by Laurent Morvillier on 05/08/2019. |
||||||
|
// Copyright © 2019 Stax River. All rights reserved. |
||||||
|
// |
||||||
|
|
||||||
|
import Foundation |
||||||
|
import UIKit |
||||||
|
|
||||||
|
extension UIView { |
||||||
|
|
||||||
|
func toImage() -> UIImage? { |
||||||
|
UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0.0) |
||||||
|
if let context = UIGraphicsGetCurrentContext() { |
||||||
|
self.layer.render(in: context) |
||||||
|
if let image = UIGraphicsGetImageFromCurrentImageContext() { |
||||||
|
UIGraphicsEndImageContext() |
||||||
|
return image |
||||||
|
} |
||||||
|
} |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// MARK: - Constraints |
||||||
|
|
||||||
|
@objc public func addMaxConstraints(view: UIView) { |
||||||
|
|
||||||
|
view.translatesAutoresizingMaskIntoConstraints = false |
||||||
|
|
||||||
|
view.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true |
||||||
|
view.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true |
||||||
|
if #available(iOS 11.0, *) { |
||||||
|
view.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor).isActive = true |
||||||
|
} else { |
||||||
|
view.topAnchor.constraint(equalTo: self.topAnchor).isActive = true |
||||||
|
} |
||||||
|
if #available(iOS 11.0, *) { |
||||||
|
view.bottomAnchor.constraint(equalTo: self.safeAreaLayoutGuide.bottomAnchor).isActive = true |
||||||
|
} else { |
||||||
|
view.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@objc public func addCenterConstraints(view: UIView) { |
||||||
|
|
||||||
|
view.translatesAutoresizingMaskIntoConstraints = false |
||||||
|
|
||||||
|
view.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true |
||||||
|
view.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true |
||||||
|
view.heightAnchor.constraint(equalToConstant: view.frame.size.height).isActive = true |
||||||
|
view.widthAnchor.constraint(equalToConstant: view.frame.size.width).isActive = true |
||||||
|
} |
||||||
|
|
||||||
|
@objc public func addTopStickyConstraintsWithHeight(_ height: CGFloat, view: UIView) { |
||||||
|
|
||||||
|
view.translatesAutoresizingMaskIntoConstraints = false |
||||||
|
|
||||||
|
view.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true |
||||||
|
view.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true |
||||||
|
if #available(iOS 11.0, *) { |
||||||
|
view.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor).isActive = true |
||||||
|
} else { |
||||||
|
view.topAnchor.constraint(equalTo: self.topAnchor).isActive = true |
||||||
|
} |
||||||
|
view.heightAnchor.constraint(equalToConstant: height).isActive = true |
||||||
|
} |
||||||
|
|
||||||
|
@objc public func addBottomStickyConstraintsWithHeight(_ height: CGFloat, view: UIView) { |
||||||
|
|
||||||
|
view.translatesAutoresizingMaskIntoConstraints = false |
||||||
|
|
||||||
|
view.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true |
||||||
|
view.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true |
||||||
|
if #available(iOS 11.0, *) { |
||||||
|
view.bottomAnchor.constraint(equalTo: self.safeAreaLayoutGuide.bottomAnchor).isActive = true |
||||||
|
} else { |
||||||
|
view.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true |
||||||
|
} |
||||||
|
view.heightAnchor.constraint(equalToConstant: height).isActive = true |
||||||
|
} |
||||||
|
|
||||||
|
@objc public func addMaxConstraintsToTopView(_ topView: UIView, forView view: UIView) { |
||||||
|
|
||||||
|
view.translatesAutoresizingMaskIntoConstraints = false |
||||||
|
|
||||||
|
view.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true |
||||||
|
view.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true |
||||||
|
view.topAnchor.constraint(equalTo: topView.bottomAnchor).isActive = true |
||||||
|
if #available(iOS 11.0, *) { |
||||||
|
view.bottomAnchor.constraint(equalTo: self.safeAreaLayoutGuide.bottomAnchor).isActive = true |
||||||
|
} else { |
||||||
|
view.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
Loading…
Reference in new issue