swiftasyncdisplaykit

How can I properly add nodes in an ASCellNode using Texture


I am learning AsyncDisplayKit/Texture. I am trying to create an ASTableNode with a custom cell.

I am struggling to understand how to properly set and anchor the nodes I create within my ExampleNode.

I have tried this

   override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {

        let stack = ASStackLayoutSpec.vertical()
        stack.children = textNode
        return stack
    }

But have an error

Cannot assign value of type 'ASTextNode' to type '[ASLayoutElement]?'

I then updated layoutSpecThatFits with

override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
  return ASStackLayoutSpec(
        direction: .horizontal,
        spacing: 16,
        justifyContent: .start,
        alignItems: .center,
        children: [textNode]
    )
}

But this has bumped the text right up against the left of the cell. No Spacing at all is applied.

enter image description here

I am struggling to find a decent guide on using this, so please forgive me if the answer is obvious.

What would be the correct way, using the below class, to add nodes to a cell?

import AsyncDisplayKit

final class FeedNodeController: ASViewController<ASDisplayNode> {

    var tableNode: ASTableNode {
        return node as! ASTableNode
    }

    private lazy var tableNodeProvider = FeedTableNodeProvider()

    init() {
        super.init(node: ASTableNode())
        tableNode.delegate = tableNodeProvider
        tableNode.dataSource = tableNodeProvider

        tableNode.view.tableFooterView = UIView()
    }

    required init?(coder aDecoder: NSCoder) {
        return nil
    }
}

class FeedTableNodeProvider: NSObject {
    private let feed = ["Foo", "Bar", "Boo", "Baz"]
}

extension FeedTableNodeProvider: ASTableDataSource, ASTableDelegate {

    func numberOfSections(in tableNode: ASTableNode) -> Int {
        return 1
    }
    func tableNode(_ tableNode: ASTableNode, nodeBlockForRowAt indexPath: IndexPath) -> ASCellNodeBlock {

        let node = { [unowned self] () -> ASCellNode in
            return ExampleNode(text: self.feed[indexPath.row])
        }

        return node
    }

    func tableNode(_ tableNode: ASTableNode, numberOfRowsInSection section: Int) -> Int {
        return feed.count
    }
}

class ExampleNode: ASCellNode {

    private lazy var textNode: ASTextNode = {
        let node = ASTextNode()
        node.backgroundColor = .blue
        return node
    }()

    init(text: String) {
        super.init()
        textNode.attributedText = NSAttributedString(string: text)
        backgroundColor = .purple
        addSubnode(textNode)
    }

    override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
        return ASStackLayoutSpec(
            direction: .horizontal,
            spacing: 16,
            justifyContent: .start,
            alignItems: .center,
            children: [textNode]
        )
    }
}

Solution

  • ASTexNode will calculate its width just for how long the text is if you don't set any width for it

    don't really understand what you ask

    if you want to add a padding, you can wrap you current ASStackLayoutSpec with ASInsetLayoutSpec

    ...
    let mainStack = ASStackLayoutSpec(
                direction: .horizontal,
                spacing: 16,
                justifyContent: .start,
                alignItems: .center,
                children: [textNode])
    
    let paddedMainStack = ASInsetLayoutSpec(insets: UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16), child: mainStack)
    
    return paddedMainStack
    ...
    

    then you will have your padding

    Happy Texturing