Skip to content

Commit a59d6e7

Browse files
authored
Merge pull request #22 from wsu-nyt/master
Added Texture benchmark
2 parents c316e0a + 9fbed75 commit a59d6e7

File tree

6 files changed

+346
-2
lines changed

6 files changed

+346
-2
lines changed

LayoutFrameworkBenchmark.xcodeproj/project.pbxproj

+24
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
24661D0A1F4EFFF5002CB883 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 24661D081F4EFFF5002CB883 /* LaunchScreen.storyboard */; };
2727
639E5A2020DF62D700C6BCEA /* NKFrameLayoutKitView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 639E5A1F20DF62D700C6BCEA /* NKFrameLayoutKitView.swift */; };
2828
BF3DC69820B560A400536177 /* FeedItemNotAutoLayoutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3DC69720B560A400536177 /* FeedItemNotAutoLayoutView.swift */; };
29+
E4A8A14124FE99B1009D872B /* FeedItemTextureNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4A8A14024FE982E009D872B /* FeedItemTextureNode.swift */; };
30+
E4A8A24F24FEDD14009D872B /* TextureCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4A8A24E24FEDD14009D872B /* TextureCollectionViewController.swift */; };
2931
/* End PBXBuildFile section */
3032

3133
/* Begin PBXFileReference section */
@@ -52,6 +54,8 @@
5254
639E5A1F20DF62D700C6BCEA /* NKFrameLayoutKitView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NKFrameLayoutKitView.swift; sourceTree = "<group>"; };
5355
73BD901DE3512A23A7603899 /* Pods-LayoutFrameworkBenchmark.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LayoutFrameworkBenchmark.debug.xcconfig"; path = "Pods/Target Support Files/Pods-LayoutFrameworkBenchmark/Pods-LayoutFrameworkBenchmark.debug.xcconfig"; sourceTree = "<group>"; };
5456
BF3DC69720B560A400536177 /* FeedItemNotAutoLayoutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedItemNotAutoLayoutView.swift; sourceTree = "<group>"; };
57+
E4A8A14024FE982E009D872B /* FeedItemTextureNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedItemTextureNode.swift; sourceTree = "<group>"; };
58+
E4A8A24E24FEDD14009D872B /* TextureCollectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextureCollectionViewController.swift; sourceTree = "<group>"; };
5559
/* End PBXFileReference section */
5660

5761
/* Begin PBXFrameworksBuildPhase section */
@@ -69,6 +73,7 @@
6973
2401BC741F4F017D00788998 /* Benchmarks */ = {
7074
isa = PBXGroup;
7175
children = (
76+
E4A8A13F24FE981F009D872B /* Texture */,
7277
2401BCA21F4F045600788998 /* AutoLayout */,
7378
2401BC921F4F020D00788998 /* FlexLayout */,
7479
2401BC8D1F4F01CC00788998 /* LayoutKit */,
@@ -208,6 +213,15 @@
208213
name = NotAutoLayout;
209214
sourceTree = "<group>";
210215
};
216+
E4A8A13F24FE981F009D872B /* Texture */ = {
217+
isa = PBXGroup;
218+
children = (
219+
E4A8A14024FE982E009D872B /* FeedItemTextureNode.swift */,
220+
E4A8A24E24FEDD14009D872B /* TextureCollectionViewController.swift */,
221+
);
222+
name = Texture;
223+
sourceTree = "<group>";
224+
};
211225
/* End PBXGroup section */
212226

213227
/* Begin PBXNativeTarget section */
@@ -289,17 +303,25 @@
289303
"${BUILT_PRODUCTS_DIR}/LayoutKit/LayoutKit.framework",
290304
"${BUILT_PRODUCTS_DIR}/NKFrameLayoutKit/NKFrameLayoutKit.framework",
291305
"${BUILT_PRODUCTS_DIR}/NotAutoLayout/NotAutoLayout.framework",
306+
"${BUILT_PRODUCTS_DIR}/PINCache/PINCache.framework",
307+
"${BUILT_PRODUCTS_DIR}/PINOperation/PINOperation.framework",
308+
"${BUILT_PRODUCTS_DIR}/PINRemoteImage/PINRemoteImage.framework",
292309
"${BUILT_PRODUCTS_DIR}/PinLayout/PinLayout.framework",
293310
"${PODS_ROOT}/Reveal-SDK/RevealServer/iOS/RevealServer.framework",
311+
"${BUILT_PRODUCTS_DIR}/Texture/AsyncDisplayKit.framework",
294312
);
295313
name = "[CP] Embed Pods Frameworks";
296314
outputPaths = (
297315
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FlexLayout.framework",
298316
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/LayoutKit.framework",
299317
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/NKFrameLayoutKit.framework",
300318
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/NotAutoLayout.framework",
319+
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PINCache.framework",
320+
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PINOperation.framework",
321+
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PINRemoteImage.framework",
301322
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PinLayout.framework",
302323
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RevealServer.framework",
324+
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AsyncDisplayKit.framework",
303325
);
304326
runOnlyForDeploymentPostprocessing = 0;
305327
shellPath = /bin/sh;
@@ -331,6 +353,7 @@
331353
isa = PBXSourcesBuildPhase;
332354
buildActionMask = 2147483647;
333355
files = (
356+
E4A8A24F24FEDD14009D872B /* TextureCollectionViewController.swift in Sources */,
334357
2401BCA11F4F044000788998 /* FeedItemUIStackView.swift in Sources */,
335358
2401BC8B1F4F018C00788998 /* Stopwatch.swift in Sources */,
336359
2401BC8F1F4F01D600788998 /* FeedItemLayoutKitView.swift in Sources */,
@@ -340,6 +363,7 @@
340363
2401BC821F4F018C00788998 /* CollectionViewController.swift in Sources */,
341364
2401BC9E1F4F042700788998 /* FeedItemManualView.swift in Sources */,
342365
2401BC811F4F018C00788998 /* BenchmarkViewController.swift in Sources */,
366+
E4A8A14124FE99B1009D872B /* FeedItemTextureNode.swift in Sources */,
343367
BF3DC69820B560A400536177 /* FeedItemNotAutoLayoutView.swift in Sources */,
344368
639E5A2020DF62D700C6BCEA /* NKFrameLayoutKitView.swift in Sources */,
345369
2401BC9B1F4F03B300788998 /* ProfileCardLayout.swift in Sources */,

LayoutFrameworkBenchmark/Benchmarks/BenchmarkViewController.swift

+5
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ class BenchmarkViewController: UITableViewController {
5454
return CollectionViewControllerFeedItemPinLayoutView(data: data)
5555
}),
5656

57+
ViewControllerData(title: "Texture", factoryBlock: { viewCount in
58+
let data = FeedItemData.generate(count: viewCount)
59+
return TextureCollectionViewController(data: data)
60+
}),
61+
5762
ViewControllerData(title: "UIStackView", factoryBlock: { viewCount in
5863
if #available(iOS 9.0, *) {
5964
let data = FeedItemData.generate(count: viewCount)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
// Copyright 2016 LinkedIn Corp.
2+
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
3+
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
4+
//
5+
// Unless required by applicable law or agreed to in writing,
6+
// software distributed under the License is distributed on an "AS IS" BASIS,
7+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8+
9+
import UIKit
10+
import AsyncDisplayKit
11+
12+
/// A LinkedIn feed item that is implemented with Texture.
13+
class FeedItemTextureNode: ASCellNode {
14+
let topBarView = TopBarNode()
15+
let miniProfileView = MiniProfileNode()
16+
let miniContentView = MiniContentNode()
17+
let socialActionsView = SocialActionsNode()
18+
let commentView = CommentNode()
19+
20+
init(data: FeedItemData) {
21+
topBarView.actionLabel.attributedText = data.actionText.makeAttributedString()
22+
miniProfileView.posterNameLabel.attributedText = data.posterName.makeAttributedString()
23+
miniProfileView.posterHeadlineLabel.attributedText = data.posterHeadline.makeAttributedString()
24+
miniProfileView.posterTimeLabel.attributedText = data.posterTimestamp.makeAttributedString()
25+
miniProfileView.posterCommentLabel.attributedText = data.posterComment.makeAttributedString()
26+
miniContentView.contentTitleLabel.attributedText = data.contentTitle.makeAttributedString()
27+
miniContentView.contentDomainLabel.attributedText = data.contentDomain.makeAttributedString()
28+
commentView.actorCommentLabel.attributedText = data.actorComment.makeAttributedString()
29+
super.init()
30+
[topBarView, miniProfileView, miniContentView, socialActionsView, commentView].forEach { addSubnode($0) }
31+
}
32+
33+
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
34+
let mainStack = ASStackLayoutSpec(direction: .vertical,
35+
spacing: 0.0,
36+
justifyContent: .spaceBetween,
37+
alignItems: .stretch,
38+
children: [topBarView, miniProfileView, miniContentView, socialActionsView, commentView])
39+
return mainStack
40+
}
41+
}
42+
43+
class CommentNode: ASDisplayNode {
44+
let actorImageView: ASImageNode = {
45+
let i = ASImageNode()
46+
i.image = UIImage(named: "50x50.png")
47+
return i
48+
}()
49+
50+
let actorCommentLabel: ASTextNode = ASTextNode()
51+
52+
override init() {
53+
super.init()
54+
[actorImageView, actorCommentLabel].forEach { addSubnode($0) }
55+
}
56+
57+
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
58+
actorCommentLabel.style.flexGrow = 1.0
59+
let mainStack = ASStackLayoutSpec(direction: .horizontal,
60+
spacing: 0.0,
61+
justifyContent: .spaceBetween,
62+
alignItems: .start,
63+
children: [actorImageView, actorCommentLabel])
64+
return mainStack
65+
}
66+
}
67+
68+
class MiniContentNode: ASDisplayNode {
69+
let contentImageView: ASImageNode = {
70+
let i = ASImageNode()
71+
i.image = UIImage(named: "350x200.png")
72+
i.contentMode = .scaleAspectFit
73+
i.backgroundColor = UIColor.orange
74+
return i
75+
}()
76+
77+
let contentTitleLabel: ASTextNode = ASTextNode()
78+
let contentDomainLabel: ASTextNode = ASTextNode()
79+
80+
override init() {
81+
super.init()
82+
[contentImageView, contentTitleLabel, contentDomainLabel].forEach { addSubnode($0) }
83+
}
84+
85+
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
86+
let mainStack = ASStackLayoutSpec(direction: .vertical,
87+
spacing: 0.0,
88+
justifyContent: .spaceBetween,
89+
alignItems: .stretch,
90+
children: [contentImageView, contentTitleLabel, contentDomainLabel])
91+
return mainStack
92+
}
93+
}
94+
95+
class MiniProfileNode: ASDisplayNode {
96+
let posterImageView: ASImageNode = {
97+
let i = ASImageNode()
98+
i.image = UIImage(named: "50x50.png")
99+
i.backgroundColor = UIColor.orange
100+
i.contentMode = .center
101+
return i
102+
}()
103+
104+
let posterNameLabel: ASTextNode = {
105+
let l = ASTextNode()
106+
l.backgroundColor = UIColor.yellow
107+
return l
108+
}()
109+
110+
let posterHeadlineLabel: ASTextNode = {
111+
let l = ASTextNode()
112+
l.maximumNumberOfLines = 3
113+
l.backgroundColor = UIColor.yellow
114+
return l
115+
}()
116+
117+
let posterTimeLabel: ASTextNode = {
118+
let l = ASTextNode()
119+
l.backgroundColor = UIColor.yellow
120+
return l
121+
}()
122+
123+
let posterCommentLabel: ASTextNode = ASTextNode()
124+
125+
override init() {
126+
super.init()
127+
[posterNameLabel, posterHeadlineLabel, posterTimeLabel, posterImageView, posterCommentLabel].forEach { addSubnode($0) }
128+
}
129+
130+
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
131+
let textStack = ASStackLayoutSpec(direction: .vertical, spacing: 1.0, justifyContent: .spaceBetween, alignItems: .stretch, children: [posterNameLabel, posterHeadlineLabel, posterTimeLabel])
132+
textStack.style.flexGrow = 1.0
133+
134+
let imageTextStack = ASStackLayoutSpec(direction: .horizontal,
135+
spacing: 2.0,
136+
justifyContent: .spaceBetween,
137+
alignItems: .start,
138+
children: [posterImageView,
139+
textStack])
140+
141+
let mainStack = ASStackLayoutSpec(direction: .vertical,
142+
spacing: 3.0,
143+
justifyContent: .start,
144+
alignItems: .stretch,
145+
children: [imageTextStack,
146+
posterCommentLabel])
147+
148+
let insetStack = ASInsetLayoutSpec(insets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 4.0),
149+
child: mainStack)
150+
151+
return insetStack
152+
}
153+
}
154+
155+
class SocialActionsNode: ASDisplayNode {
156+
let likeLabel: ASTextNode = {
157+
let l = ASTextNode()
158+
l.attributedText = "Like".makeAttributedString()
159+
l.backgroundColor = .green
160+
return l
161+
}()
162+
163+
let commentLabel: ASTextNode = {
164+
let l = ASTextNode()
165+
l.attributedText = "Comment".makeAttributedString()
166+
l.backgroundColor = .green
167+
return l
168+
}()
169+
170+
let shareLabel: ASTextNode = {
171+
let l = ASTextNode()
172+
l.attributedText = "Share".makeAttributedString()
173+
l.backgroundColor = .green
174+
return l
175+
}()
176+
177+
override init() {
178+
super.init()
179+
[likeLabel, commentLabel, shareLabel].forEach { addSubnode($0) }
180+
}
181+
182+
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
183+
let mainStack = ASStackLayoutSpec(direction: .horizontal,
184+
spacing: 0.0,
185+
justifyContent: .spaceBetween,
186+
alignItems: .start,
187+
children: [likeLabel, commentLabel, shareLabel])
188+
return mainStack
189+
}
190+
}
191+
192+
class TopBarNode: ASDisplayNode {
193+
let actionLabel: ASTextNode = ASTextNode()
194+
195+
let optionsLabel: ASTextNode = {
196+
let l = ASTextNode()
197+
l.attributedText = "...".makeAttributedString()
198+
return l
199+
}()
200+
201+
override init() {
202+
super.init()
203+
[actionLabel, optionsLabel].forEach { addSubnode($0) }
204+
}
205+
206+
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
207+
let mainStack = ASStackLayoutSpec(direction: .horizontal,
208+
spacing: 0.0,
209+
justifyContent: .start,
210+
alignItems: .start,
211+
children: [actionLabel, optionsLabel])
212+
actionLabel.style.flexGrow = 1.0
213+
return mainStack
214+
}
215+
}
216+
217+
private extension String {
218+
func makeAttributedString() -> NSAttributedString {
219+
return NSAttributedString(string: self, attributes: [.font: UIFont.systemFont(ofSize: 17.0)])
220+
}
221+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2016 LinkedIn Corp.
2+
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
3+
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
4+
//
5+
// Unless required by applicable law or agreed to in writing,
6+
// software distributed under the License is distributed on an "AS IS" BASIS,
7+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8+
9+
import AsyncDisplayKit
10+
11+
class TextureCollectionViewController: ASDKViewController<ASCollectionNode>, ASCollectionDataSource, ASCollectionDelegate {
12+
13+
let collectionNode: ASCollectionNode
14+
let reuseIdentifier = "cell"
15+
let data: [FeedItemData]
16+
let flowLayout: UICollectionViewFlowLayout
17+
18+
init(data: [FeedItemData]) {
19+
self.data = data
20+
self.flowLayout = UICollectionViewFlowLayout()
21+
self.collectionNode = ASCollectionNode(collectionViewLayout: self.flowLayout)
22+
super.init(node: collectionNode)
23+
collectionNode.delegate = self
24+
collectionNode.dataSource = self
25+
}
26+
27+
required init?(coder aDecoder: NSCoder) {
28+
fatalError("init(coder:) has not been implemented")
29+
}
30+
31+
override func viewDidLoad() {
32+
super.viewDidLoad()
33+
collectionNode.reloadData()
34+
}
35+
36+
func numberOfSections(in collectionNode: ASCollectionNode) -> Int {
37+
return 1
38+
}
39+
40+
func collectionNode(_ collectionNode: ASCollectionNode, numberOfItemsInSection section: Int) -> Int {
41+
return data.count
42+
}
43+
44+
func collectionNode(_ collectionNode: ASCollectionNode, nodeForItemAt indexPath: IndexPath) -> ASCellNode {
45+
let cell = FeedItemTextureNode(data: data[indexPath.row])
46+
47+
return cell
48+
}
49+
}

Podfile

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ target 'LayoutFrameworkBenchmark' do
1414
pod 'NotAutoLayout'
1515
pod 'NKFrameLayoutKit'
1616
pod 'PinLayout'
17+
pod 'Texture'
1718

1819
pod 'Reveal-SDK'
1920
end
@@ -27,4 +28,4 @@ post_install do |installer|
2728
end
2829
end
2930
end
30-
end
31+
end

0 commit comments

Comments
 (0)