Skip to content

Commit

Permalink
Update tvOS example
Browse files Browse the repository at this point in the history
  • Loading branch information
ra1028 committed May 2, 2019
1 parent 255b0f4 commit 1fd5738
Show file tree
Hide file tree
Showing 13 changed files with 365 additions and 454 deletions.
50 changes: 33 additions & 17 deletions Examples/Example-tvOS/Example-tvOS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@
/* Begin PBXBuildFile section */
6B2DF96C210F1A0D004D2D40 /* DifferenceKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6B2DF95C210F185E004D2D40 /* DifferenceKit.framework */; };
6B2DF96D210F1A0D004D2D40 /* DifferenceKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 6B2DF95C210F185E004D2D40 /* DifferenceKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
6B956B952110B4AA00DE3D29 /* HeaderFooterSectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B956B8E2110B4AA00DE3D29 /* HeaderFooterSectionViewController.swift */; };
6B956B962110B4AA00DE3D29 /* ShuffleEmoticonViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B956B8F2110B4AA00DE3D29 /* ShuffleEmoticonViewController.swift */; };
6B956B962110B4AA00DE3D29 /* EmojiViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B956B8F2110B4AA00DE3D29 /* EmojiViewController.swift */; };
6B956B972110B4AA00DE3D29 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6B956B902110B4AA00DE3D29 /* Assets.xcassets */; };
6B956B982110B4AA00DE3D29 /* String+Differentiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B956B912110B4AA00DE3D29 /* String+Differentiable.swift */; };
6B956B992110B4AA00DE3D29 /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B956B922110B4AA00DE3D29 /* HomeViewController.swift */; };
6B956B9A2110B4AA00DE3D29 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B956B932110B4AA00DE3D29 /* AppDelegate.swift */; };
6BAE8186227854C20060866E /* Reusable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BAE8182227854C20060866E /* Reusable.swift */; };
6BAE8187227854C20060866E /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BAE8183227854C20060866E /* StringExtensions.swift */; };
6BAE8188227854C20060866E /* ReusableViewExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BAE8184227854C20060866E /* ReusableViewExtensions.swift */; };
6BAE8189227854C20060866E /* NibLoadable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BAE8185227854C20060866E /* NibLoadable.swift */; };
6BAE818F2278550C0060866E /* EmojiCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BAE818C2278550C0060866E /* EmojiCell.swift */; };
6BAE8195227855E90060866E /* EmojiViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6BAE8194227855E90060866E /* EmojiViewController.xib */; };
6BAE8197227858440060866E /* EmojiCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6BAE8196227858440060866E /* EmojiCell.xib */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -58,13 +62,17 @@
/* Begin PBXFileReference section */
6B2DF943210F184A004D2D40 /* Example-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Example-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
6B2DF955210F185E004D2D40 /* DifferenceKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = DifferenceKit.xcodeproj; path = ../../DifferenceKit.xcodeproj; sourceTree = "<group>"; };
6B956B8E2110B4AA00DE3D29 /* HeaderFooterSectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeaderFooterSectionViewController.swift; sourceTree = "<group>"; };
6B956B8F2110B4AA00DE3D29 /* ShuffleEmoticonViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShuffleEmoticonViewController.swift; sourceTree = "<group>"; };
6B956B8F2110B4AA00DE3D29 /* EmojiViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmojiViewController.swift; sourceTree = "<group>"; };
6B956B902110B4AA00DE3D29 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
6B956B912110B4AA00DE3D29 /* String+Differentiable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Differentiable.swift"; sourceTree = "<group>"; };
6B956B922110B4AA00DE3D29 /* HomeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeViewController.swift; sourceTree = "<group>"; };
6B956B932110B4AA00DE3D29 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
6B956B942110B4AA00DE3D29 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6BAE8182227854C20060866E /* Reusable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Reusable.swift; sourceTree = "<group>"; };
6BAE8183227854C20060866E /* StringExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtensions.swift; sourceTree = "<group>"; };
6BAE8184227854C20060866E /* ReusableViewExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReusableViewExtensions.swift; sourceTree = "<group>"; };
6BAE8185227854C20060866E /* NibLoadable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NibLoadable.swift; sourceTree = "<group>"; };
6BAE818C2278550C0060866E /* EmojiCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmojiCell.swift; sourceTree = "<group>"; };
6BAE8194227855E90060866E /* EmojiViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = EmojiViewController.xib; sourceTree = "<group>"; };
6BAE8196227858440060866E /* EmojiCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = EmojiCell.xib; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -108,12 +116,16 @@
6B956B8D2110B4AA00DE3D29 /* Sources */ = {
isa = PBXGroup;
children = (
6B956B8E2110B4AA00DE3D29 /* HeaderFooterSectionViewController.swift */,
6B956B8F2110B4AA00DE3D29 /* ShuffleEmoticonViewController.swift */,
6B956B902110B4AA00DE3D29 /* Assets.xcassets */,
6B956B912110B4AA00DE3D29 /* String+Differentiable.swift */,
6B956B922110B4AA00DE3D29 /* HomeViewController.swift */,
6B956B8F2110B4AA00DE3D29 /* EmojiViewController.swift */,
6BAE8194227855E90060866E /* EmojiViewController.xib */,
6BAE818C2278550C0060866E /* EmojiCell.swift */,
6BAE8196227858440060866E /* EmojiCell.xib */,
6BAE8182227854C20060866E /* Reusable.swift */,
6BAE8183227854C20060866E /* StringExtensions.swift */,
6BAE8184227854C20060866E /* ReusableViewExtensions.swift */,
6BAE8185227854C20060866E /* NibLoadable.swift */,
6B956B932110B4AA00DE3D29 /* AppDelegate.swift */,
6B956B902110B4AA00DE3D29 /* Assets.xcassets */,
6B956B942110B4AA00DE3D29 /* Info.plist */,
);
path = Sources;
Expand Down Expand Up @@ -204,6 +216,8 @@
buildActionMask = 2147483647;
files = (
6B956B972110B4AA00DE3D29 /* Assets.xcassets in Resources */,
6BAE8195227855E90060866E /* EmojiViewController.xib in Resources */,
6BAE8197227858440060866E /* EmojiCell.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -214,11 +228,13 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6B956B962110B4AA00DE3D29 /* ShuffleEmoticonViewController.swift in Sources */,
6B956B982110B4AA00DE3D29 /* String+Differentiable.swift in Sources */,
6B956B952110B4AA00DE3D29 /* HeaderFooterSectionViewController.swift in Sources */,
6BAE8186227854C20060866E /* Reusable.swift in Sources */,
6BAE818F2278550C0060866E /* EmojiCell.swift in Sources */,
6B956B962110B4AA00DE3D29 /* EmojiViewController.swift in Sources */,
6BAE8189227854C20060866E /* NibLoadable.swift in Sources */,
6BAE8187227854C20060866E /* StringExtensions.swift in Sources */,
6B956B9A2110B4AA00DE3D29 /* AppDelegate.swift in Sources */,
6B956B992110B4AA00DE3D29 /* HomeViewController.swift in Sources */,
6BAE8188227854C20060866E /* ReusableViewExtensions.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
2 changes: 1 addition & 1 deletion Examples/Example-tvOS/Sources/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let window = UIWindow()
let navigationController = UINavigationController(rootViewController: HomeViewController())
let navigationController = UINavigationController(rootViewController: EmojiViewController())
window.rootViewController = navigationController
window.makeKeyAndVisible()
self.window = window
Expand Down
26 changes: 26 additions & 0 deletions Examples/Example-tvOS/Sources/EmojiCell.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import UIKit

final class EmojiCell: UICollectionViewCell, NibReusable {
@IBOutlet weak var label: UILabel!

override func awakeFromNib() {
super.awakeFromNib()

contentView.backgroundColor = UIColor(white: 0.95, alpha: 1)
contentView.layer.cornerRadius = 8
contentView.layer.shadowOffset = CGSize(width: 0, height: 7)
}

override var isHighlighted: Bool {
didSet { alpha = isHidden ? 0.2 : 1 }
}

override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
coordinator.addCoordinatedAnimations({ [weak self] in
guard let self = self else { return }
self.contentView.layer.shadowOpacity = self.isFocused ? 0.3 : 0
self.contentView.layer.transform = self.isFocused ? CATransform3DMakeScale(1.1, 1.1, 1) : CATransform3DIdentity
self.layer.zPosition = self.isFocused ? 1 : 0
})
}
}
45 changes: 45 additions & 0 deletions Examples/Example-tvOS/Sources/EmojiCell.xib
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder.AppleTV.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="AppleTV" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="appleTV" orientation="landscape">
<adaptation id="light"/>
</device>
<dependencies>
<deployment identifier="tvOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<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"/>
<collectionViewCell opaque="NO" multipleTouchEnabled="YES" contentMode="center" id="Zg6-US-FcK" customClass="EmojiCell" customModule="Example_tvOS" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="150" height="90"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
<rect key="frame" x="0.0" y="0.0" width="150" height="90"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="😁" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Xh8-3R-aih">
<rect key="frame" x="0.0" y="0.0" width="150" height="90"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</view>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="Xh8-3R-aih" firstAttribute="leading" secondItem="Zg6-US-FcK" secondAttribute="leading" id="Lf3-dv-Js4"/>
<constraint firstAttribute="bottom" secondItem="Xh8-3R-aih" secondAttribute="bottom" id="Q6r-1B-mOJ"/>
<constraint firstItem="Xh8-3R-aih" firstAttribute="top" secondItem="Zg6-US-FcK" secondAttribute="top" id="Qew-Zz-RZi"/>
<constraint firstAttribute="trailing" secondItem="Xh8-3R-aih" secondAttribute="trailing" id="nxP-jf-QMm"/>
</constraints>
<viewLayoutGuide key="safeArea" id="1K2-3x-ulA"/>
<connections>
<outlet property="label" destination="Xh8-3R-aih" id="ert-4A-vyJ"/>
</connections>
<point key="canvasLocation" x="67" y="-8"/>
</collectionViewCell>
</objects>
</document>
89 changes: 89 additions & 0 deletions Examples/Example-tvOS/Sources/EmojiViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import UIKit
import DifferenceKit

final class EmojiViewController: UIViewController {
enum SectionID: Differentiable, CaseIterable {
case first, second, third
}

typealias Section = ArraySection<SectionID, String>

@IBOutlet private weak var collectionView: UICollectionView!

private var data = [Section]()
private var dataInput: [Section] {
get { return data }
set {
let changeset = StagedChangeset(source: data, target: newValue)
collectionView.reload(using: changeset) { data in
self.data = data
}
}
}

override func viewDidLoad() {
super.viewDidLoad()

title = "Emoji"
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .refresh, target: self, action: #selector(refresh))

collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(cellType: EmojiCell.self)

refresh()
}

@IBAction func refresh() {
let ids = SectionID.allCases
let Emojis = (0x1F600...0x1F647).compactMap { UnicodeScalar($0).map(String.init) }
let splitedCount = Int((Double(Emojis.count) / Double(ids.count)).rounded(.up))

dataInput = ids.enumerated().map { offset, model in
let start = offset * splitedCount
let end = min(start + splitedCount, Emojis.endIndex)
let Emojis = Emojis[start..<end]
return Section(model: model, elements: Emojis)
}
}

@IBAction func shuffleAllEmojis() {
var flattenEmojis = ArraySlice(dataInput.flatMap { $0.elements })
flattenEmojis.shuffle()

dataInput = dataInput.map { section in
var section = section
section.elements = Array(flattenEmojis.prefix(section.elements.count))
flattenEmojis.removeFirst(section.elements.count)
return section
}
}

@IBAction func shuffleSections() {
dataInput.shuffle()
}

func remove(at indexPath: IndexPath) {
dataInput[indexPath.section].elements.remove(at: indexPath.item)
}
}

extension EmojiViewController: UICollectionViewDataSource, UICollectionViewDelegate {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return data.count
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data[section].elements.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell: EmojiCell = collectionView.dequeueReusableCell(for: indexPath)
cell.label.text = data[indexPath.section].elements[indexPath.item]
return cell
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
remove(at: indexPath)
}
}
Loading

0 comments on commit 1fd5738

Please sign in to comment.