Currently measurement always needs to happen on the main thread if implicit hierarchy management is enabled as adding and removing from nodes needs to happen on the main thread. We now will trampoline to the main thread to do the insertion and deletion of nodes.
This also resolves the issue that can occur if a node is already loaded deep in the layout hierarchy in the layout that the node is transforming to. Before insertion or deletion is happening we need to crawl the layout hierarchy to check that though.
* [ASDataController] Add some assertions to clarify what queues things happen on
* [ASCollectionDataController] Optimize willReloadData
* [ASDataController] Minor optimizations, no functional changes
* [ASDataController] Always reload data on _editingTransactionQueue
* [ASDataController] Remove async data fetching option, deprecate callbacks
* [ASDataController] Not mutable
* [ASMultidimensionalArrayUtils] Use fast enumeration
* Optimize ASMultidimensionalArrayUtils
* Fix some concurrency problems detected by Xcode 8's new Thread Sanitizer.
Some of these changes are arguably just to silence the warnings from Thread Sanitizer.
* Fix several memory leaks in the unit tests.
A number of the unit test source files are compield with `-fno-objc-arc`. This was clearly overlooked when writing several of the unit tests.
Fixed by (mostly) switching to use of `-autorelease` for the problem code.
NOTE: This commit doesn't fix all the memory leaks found. There's still at least one leak in `-[ASDisplayNodeTests testSetNeedsDataFetchImmediateState]`, and several leaks in `ASBasicImageDownloader.mm`. I wasn't able to find a trivial cause to these, unfortunately.
Currently within `ASCollectionView`, there is an assumption that there will always be a static number of supplementary views per section—even when additional items are added or removed from that section. This is evidenced by the fact that when you invoke -[ASCollectionView insertItemsAtIndexPaths:], the data source method -[ASCollectionDataSource collectionView:nodeForSupplementaryElementOfKind:atIndexPath:] is not invoked, preventing consumers from specifying a new number of supplementary nodes for the new set of items.
With this change, the set of supplementary nodes for a section is now recalculated not only on section-level mutations, but also on item-level mutations as well. This adds item-level counterparts to the section-level `-prepareFor...` subclassing hooks in `ASDataController+Subclasses.h` to make this possible.
This should fix#1278 and #1322
This has been tested in my project and seen to fix the assertion. Open to suggestions on how to test in a more universal way.
* make variable naming reflect ASEnvironmentTraitCollection vs ASTraitCollection
* move trait propagation to cell allocation instead of via a nested block
* move trait propagation when setting a displaynode's supernode instead of when adding a subnode
* fixed misspelling of "colection"
* Fixed bug in `ASEnvironmentMergeObjectAndState`
* New ASLayoutSpec methods for `setChild`/`setChildren`/`setChild:forIdentifier:` have been added to take in a trait collection.
* Added `setChild:`-like methods for ASLayoutSpecs take a traitCollection
* Fixed instances where nodes in a data controller were not getting their trait collections
* propagate traitCollection in ASDisplayNode on insertSubnode or addSubnode
Initial attempt to get display traits working with ASEnvironment.
To get proper ASDisplayTraits support, you must use an ASViewController. The ASViewController implements UITraitCollection-related methods (`traitCollectionDidChange:`, `willTransitionToTraitCollection:withTransitionCoordinator:`, viewWillTransitionToSize:withTransitionCoordinator`) to update the internal ASDisplayTraits and propagate them to subnodes.
ASTableNode and ASCollectionNode don't actually have their cells as subnodes, so a little bit of trickery is involved (on `setEnvironment:` the table/collection node gets its data controllers completedNodes and propagates the new traits. see `ASDisplayTraitsCollectionTableSetEnvironmentState`). The data controller also passes the current display traits when creating new cells.
ASViewController also supports the ability to return a custom set of display traits. So if you have a modal dialog that should always be told it is in a compact size class, you can set the override block before displaying the VC.
A new example, called Display Traits, has been added. It shows how display traits can be used in a ASViewController with a normal ASDisplayNode as its root, as well as in ASViewControllers hosting table nodes and collection nodes. There is also an example of overriding the default display traits of a VC.
Please provide feedback!
Summary:
We observed a deadlock which occurred when two threads were laying out the same set of nodes.
On one thread, layout would occur on a leaf node. It would lock and as part of this layout
process, ASDK walks up the node tree and calls __setNeedsLayout on its supernode until it
reaches the supernode with no supernode. When the supernode gets its call to __setNeedsLayout
it also locks. So leaf node locks and then awaits supernode lock.
On another thread, we're doing a layout pass on the supernode in the above thread. This locks
the supernode and attempts to lock the leaf node. This deadlocks (remember the above thread
is holding onto the leaf lock and awaiting the supernode lock. This thread is holding onto
the supernode lock and awaiting the leaf lock).
This is all exacerbated by the use of recursive locks.
The issue was: The left operand of '>=' is a garbage value in else if check for lengths[i+1][j] ... I had to rewrite the algorithm to quiet the static analyzer.