@@ -71,106 +71,10 @@ extension TweetModel {
7171
7272}
7373
74- //class TableViewController: UIViewController {
75- //
76- // fileprivate lazy var tableView: UITableView = {
77- // let tableView = UITableView(frame: CGRect(), style: .plain)
78- //
79- // tableView.delegate = self
80- // tableView.dataSource = self
81- // tableView.separatorStyle = .none
82- // return tableView
83- // }()
84- //
85- // fileprivate var nodeModels: [(TweetModel, RootNode)] = []
86- // private var referenceWidth: CGFloat = 0
87- //
88- // override func viewDidLoad() {
89- // super.viewDidLoad()
90- //
91- // title = "Table Demo"
92- // view.addSubview(tableView)
93- //
94- // nodeModels = TweetModel.stubData().map { ($0, RootNode())}
95- // }
96- //
97- // override func viewDidLayoutSubviews() {
98- // super.viewDidLayoutSubviews()
99- // tableView.lx.fill()
100- //
101- // let width = tableView.frame.width
102- //
103- // if width != referenceWidth {
104- // referenceWidth = width
105- //
106- // let dateStart = Date()
107- // let models = nodeModels.map { $0.0 }
108- // DispatchQueue.global(qos: .background).async {
109- // models.parallelMap(striding: 2, filler: (TweetModel(), RootNode()), f: {
110- // ($0, TweetCell.buildRootNode($0, width: width))
111- // }) {[weak self] in
112- // print("did cache in \(Date().timeIntervalSince(dateStart))s")
113- // self?.didLoad(nodeModels: $0, width: width)
114- // }
115- // }
116- // }
117- // }
118- //
119- // private func didLoad(nodeModels: [(TweetModel, RootNode)], width: CGFloat) {
120- //
121- // if width == referenceWidth {
122- // self.nodeModels = nodeModels
123- // }
124- // }
125- //}
126- //
127- //extension TableViewController: UITableViewDelegate, UITableViewDataSource {
128- //
129- // func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
130- // return nodeModels.count
131- // }
132- //
133- // func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
134- // let cellId = "CellId"
135- // let cell = (tableView.dequeueReusableCell(withIdentifier: cellId) as? TweetCell) ?? TweetCell(style: .default, reuseIdentifier: cellId)
136- // return cell
137- // }
138- //
139- // func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
140- // tableView.deselectRow(at: indexPath, animated: true)
141- // }
142- //
143- // func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
144- // (cell as? TweetCell)?.rootNode = nodeModels[indexPath.row].1
145- // }
146- //
147- // func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
148- // return 100
149- // }
150- //
151- // func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
152- //
153- // let (model, rootNode) = nodeModels[indexPath.row]
154- //
155- // if rootNode.frame.width != tableView.frame.width {
156- // let newRootNode = TweetCell.buildRootNode(model, width: tableView.frame.width)
157- // nodeModels[indexPath.row] = (model, newRootNode)
158- //
159- // if let cell = tableView.cellForRow(at: indexPath) {
160- // if let cell = cell as? TweetCell {
161- // cell.rootNode = newRootNode
162- // }
163- // }
164- // }
165- //
166- // return nodeModels[indexPath.row].1.frame.height
167- // }
168- //}
169-
17074class TableViewController : UIViewController {
17175
17276 fileprivate lazy var tableView : UITableView = {
173- let tableView = UITableView ( frame: CGRect ( ) , style: . plain )
77+ let tableView = UITableView ( frame: CGRect ( ) , style: . grouped )
17478
17579 tableView. delegate = self
17680 tableView. dataSource = self
@@ -179,6 +83,7 @@ class TableViewController: UIViewController {
17983 } ( )
18084
18185 fileprivate var tweets : [ TweetModel ] = TweetModel . stubData ( )
86+ fileprivate var nodeModels : [ ( TweetModel , RootNode ) ] ?
18287
18388 private var referenceWidth : CGFloat = 0
18489
@@ -187,52 +92,104 @@ class TableViewController: UIViewController {
18792
18893 title = " Table Demo "
18994 view. addSubview ( tableView)
95+
96+ navigationItem. rightBarButtonItem = editButtonItem
97+
98+ nodeModels = tweets. map { ( $0, RootNode ( ) ) }
99+ }
100+
101+ override func setEditing( _ editing: Bool , animated: Bool ) {
102+ super. setEditing ( editing, animated: animated)
103+ tableView. setEditing ( editing, animated: animated)
190104 }
191105
192106 override func viewDidLayoutSubviews( ) {
193107 super. viewDidLayoutSubviews ( )
108+
109+
110+ let width = view. frame. width
111+
112+ if width != referenceWidth {
113+ nodeModels = nil
114+ referenceWidth = width
115+
116+ let dateStart = Date ( )
117+ let models = tweets
118+ DispatchQueue . global ( qos: . background) . async {
119+ models. parallelMap ( striding: 2 , filler: ( TweetModel ( ) , RootNode ( ) ) , f: {
120+ let node = TweetCell . buildRootNode ( $0, estimated: false )
121+ _ = node. calculate ( for: CGSize ( width: width, height: 0 ) )
122+ return ( $0, node)
123+ } ) { [ weak self] in
124+ print ( " did cache in \( Date ( ) . timeIntervalSince ( dateStart) ) s " )
125+ self ? . didLoad ( nodeModels: $0, width: width)
126+ }
127+ }
128+ }
129+
194130 tableView. lx. fill ( )
195131 }
196132
197- fileprivate lazy var adapter : TableViewNodesDisplayAdapter = { [ unowned self] in
198- return TableViewNodesDisplayAdapter ( headerNodeForSection: { index, estimated in
199- return TweetCell . headerRootNode ( title: " Cras justo odio, dapibus ac facilisis in, egestas eget quam. Lorem ipsum dolor sit amet, consectetur adipiscing elit. " , estimated: estimated)
133+ private func didLoad( nodeModels: [ ( TweetModel , RootNode ) ] , width: CGFloat ) {
134+
135+ if width == referenceWidth {
136+ self . nodeModels = nodeModels
137+ }
138+ }
139+
140+ fileprivate lazy var adapter : TableViewPresentationAdapter = { [ unowned self] in
141+ return TableViewPresentationAdapter ( headerNodeForSection: { index, estimated in
142+ return NodeTableHeaderFooter ( model: TweetCell . headerRootNode ( title: " Cras justo odio, dapibus ac facilisis in, egestas eget quam. Lorem ipsum dolor sit amet, consectetur adipiscing elit. " , estimated: estimated) )
200143 } , cellNodeForIndexPath: { indexPath, estimated in
201- return TweetCell . buildRootNode ( self . tweets [ indexPath. row] , estimated: estimated)
144+ if indexPath. section == 0 {
145+ return TableRow < ClassicCell > ( model: ClassicModel ( title: " Hello Classic Cell " ) {
146+ print ( " action! " )
147+ } )
148+ } else {
149+ if let nodeModel = self . nodeModels ? [ indexPath. row] {
150+ return NodeTableRow ( model: nodeModel. 1 )
151+ } else {
152+ return NodeTableRow ( model: TweetCell . buildRootNode ( self . tweets [ indexPath. row] , estimated: estimated) )
153+ }
154+ }
202155 } )
203156 } ( )
204157}
205158
206159extension TableViewController : UITableViewDelegate , UITableViewDataSource {
207160
161+ func numberOfSections( in tableView: UITableView ) -> Int {
162+ return 2
163+ }
208164
209165 func tableView( _ tableView: UITableView , numberOfRowsInSection section: Int ) -> Int {
210- return tweets. count
166+ if section == 0 {
167+ return 3
168+ } else {
169+ return tweets. count
170+ }
211171 }
212172
213173 func tableView( _ tableView: UITableView , didSelectRowAt indexPath: IndexPath ) {
214174 tableView. deselectRow ( at: indexPath, animated: true )
215175 }
216176
217177 //adapted
218-
219178
220179 func tableView( _ tableView: UITableView , cellForRowAt indexPath: IndexPath ) -> UITableViewCell {
221- let id = " cellId "
222- return tableView. dequeueReusableCell ( withIdentifier: id) ?? NodeTableViewCell ( style: . default, reuseIdentifier: id)
180+ return adapter. tableView ( tableView, cellForRowAt: indexPath)
223181 }
224182
225183 func tableView( _ tableView: UITableView , viewForHeaderInSection section: Int ) -> UIView ? {
226- let id = " headerId "
227- return tableView. dequeueReusableHeaderFooterView ( withIdentifier: id) ?? NodeTableHeaderFooterView ( reuseIdentifier: id)
184+ return adapter. tableView ( tableView, viewForHeaderInSection: section)
228185 }
229186
230187 func tableView( _ tableView: UITableView , viewForFooterInSection section: Int ) -> UIView ? {
231- let id = " footerId "
232- return tableView. dequeueReusableHeaderFooterView ( withIdentifier: id) ?? NodeTableHeaderFooterView ( reuseIdentifier: id)
188+ return adapter. tableView ( tableView, viewForFooterInSection: section)
233189 }
234190
235191 //rows
192+
236193 func tableView( _ tableView: UITableView , estimatedHeightForRowAt indexPath: IndexPath ) -> CGFloat {
237194 return adapter. tableView ( tableView, estimatedHeightForRowAt: indexPath)
238195 }
@@ -241,11 +198,6 @@ extension TableViewController: UITableViewDelegate, UITableViewDataSource {
241198 return adapter. tableView ( tableView, heightForRowAt: indexPath)
242199 }
243200
244- func tableView( _ tableView: UITableView , willDisplay cell: UITableViewCell , forRowAt indexPath: IndexPath ) {
245- adapter. tableView ( tableView, willDisplay: cell, forRowAt: indexPath)
246- }
247-
248-
249201 //footers
250202 func tableView( _ tableView: UITableView , estimatedHeightForFooterInSection section: Int ) -> CGFloat {
251203 return adapter. tableView ( tableView, estimatedHeightForFooterInSection: section)
@@ -254,10 +206,6 @@ extension TableViewController: UITableViewDelegate, UITableViewDataSource {
254206 return adapter. tableView ( tableView, heightForFooterInSection: section)
255207 }
256208
257- func tableView( _ tableView: UITableView , willDisplayFooterView view: UIView , forSection section: Int ) {
258- adapter. tableView ( tableView, willDisplayFooterView: view, forSection: section)
259- }
260-
261209 //headers
262210
263211 func tableView( _ tableView: UITableView , estimatedHeightForHeaderInSection section: Int ) -> CGFloat {
@@ -268,9 +216,14 @@ extension TableViewController: UITableViewDelegate, UITableViewDataSource {
268216 return adapter. tableView ( tableView, heightForHeaderInSection: section)
269217 }
270218
271- func tableView( _ tableView: UITableView , willDisplayHeaderView view: UIView , forSection section: Int ) {
272- adapter. tableView ( tableView, willDisplayHeaderView: view, forSection: section)
219+ func tableView( _ tableView: UITableView , canEditRowAt indexPath: IndexPath ) -> Bool {
220+ return true
221+ }
222+
223+ func tableView( _ tableView: UITableView , commit editingStyle: UITableViewCellEditingStyle , forRowAt indexPath: IndexPath ) {
224+
273225 }
226+
274227}
275228
276229enum TweetCell {
@@ -398,10 +351,17 @@ enum TweetCell {
398351 Fix ( tweetNode)
399352 )
400353
354+ if rootNode. frame. size. height > 10 { // in editing mode...
355+ let newTweetHeight = ( rootNode. frame. height - pad - tweetNode. frame. minY)
356+ tweetNode. lx. set ( height: newTweetHeight)
357+ }
358+
401359 timeStampNode. lx. firstBaselineAnchor. follow ( userNode. lx. firstBaselineAnchor)
402360
403361 //calculate final cell height
404362 rootNode. frame. size. height = max ( tweetNode. frame. maxY + pad, avatarNode. frame. maxY + pad)
363+
364+
405365 }
406366
407367 return rootNode
@@ -433,6 +393,7 @@ extension TweetCell {
433393 let paragraphStyle = NSMutableParagraphStyle ( )
434394 paragraphStyle. alignment = . left
435395 paragraphStyle. lineHeightMultiple = 1.2
396+ paragraphStyle. lineBreakMode = . byTruncatingTail
436397 let attributes = [
437398 NSParagraphStyleAttributeName: paragraphStyle,
438399 NSFontAttributeName: UIFont . systemFont ( ofSize: 15.0 ) ,
@@ -516,3 +477,34 @@ extension RootNode {
516477 self . init ( subnodes: [ ] , layout: { _ in } )
517478 }
518479}
480+
481+ struct ClassicModel {
482+ let title : String
483+ let action : ( ) -> Void
484+ init ( title: String , action: @escaping ( ) -> Void ) {
485+ self . title = title
486+ self . action = action
487+ }
488+ }
489+
490+ class ClassicCell : UITableViewCell , PresentationModelView {
491+
492+ var presentationModel : ClassicModel ? {
493+ didSet {
494+ self . textLabel? . text = presentationModel? . title
495+ }
496+ }
497+
498+ override func setSelected( _ selected: Bool , animated: Bool ) {
499+ super. setSelected ( selected, animated: animated)
500+ if selected {
501+ presentationModel? . action ( )
502+ }
503+ }
504+ }
505+
506+ extension ClassicModel : PresentationModel {
507+ func calculate( for size: CGSize ) -> CGSize {
508+ return CGSize ( width: size. width, height: 50 )
509+ }
510+ }
0 commit comments