Skip to content

Commit

Permalink
[Dev docs] fix broken image links (#1597)
Browse files Browse the repository at this point in the history
  • Loading branch information
hanton authored and ernestmama committed Jul 25, 2019
1 parent 9cedd4e commit 7aba287
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 7 deletions.
4 changes: 2 additions & 2 deletions docs/_docs/development/how-to-debug.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ The crash count had risen suddenly in recent versions, so this indicated that a

This change ensured that the collection view should clear out its data when the data source was being nilled out. This release would occur in situations like when the collection view is being deallocated. Something very important to note is Texture has the capability to asynchronously deallocate objects by "stealing" the pointer from the reference counter, and using a run loop timer to batch release the pointer triggering the actual work to deallocate via child objects's `dealloc`.

![crashlog1](/docs/static/images/development/crashingcallstack.png)
![crashlog1](/static/images/development/crashingcallstack.png)

__Analyzing section *A*__

Expand Down Expand Up @@ -94,7 +94,7 @@ Using `if (ASActivateExperimentalFeature(ASExperimentalSkipClearData)) {` you ca

Now this is where things get a little bit fun. Let's look at another crash with nearly the same call stack.

![crashlog2](/docs/static/images/development/crashingcallstack2.png)
![crashlog2](/static/images/development/crashingcallstack2.png)

Trying to understand what's going on in those top UIKit frames would indicate another solution which could hopefully eliminate this family of erroneous states.

Expand Down
4 changes: 2 additions & 2 deletions docs/_docs/development/layout-specs.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Looking at the example project:

This is the function that will recursively call through its underlying tree of nodes.

![layoutcallstack1](/docs/static/images/development/layoutspecs1.png)
![layoutcallstack1](/static/images/development/layoutspecs1.png)

This is what a typical call stack will look like for the layout of an `ASViewController` with a simple view hierarchy. Here we clicked on the "Photo with outset icon overlay" in the Layout Specs Examples project. Breakpointing on the `-[PhotoWithOutsetIconOverlay layoutSpecThatFits:]` reveals that call stack.

Expand Down Expand Up @@ -120,7 +120,7 @@ However, at this point between the above call stack and the below call stack, th

Where these layout specs are used in the rendering operation is during the UIKit `layoutIfNeeded` phase. See `-[ASDisplayNode(UIViewBridge) layoutIfNeeded]`.

![layoutcallstack2](/docs/static/images/development/layoutspecs2.png)
![layoutcallstack2](/static/images/development/layoutspecs2.png)

This is where pending layout is consumed in order to determine the frames and bounds of the soon to be displayed nodes. There are a few different steps to the sizing and placing process. However, you can see one of the core methods here `-[ASDisplayNode(Layout) _layoutSublayouts]` and look at the callers if you are curious.

Expand Down
6 changes: 3 additions & 3 deletions docs/_docs/development/threading.md
Original file line number Diff line number Diff line change
Expand Up @@ -340,21 +340,21 @@ This is a `dispatch_queue_t` that is privately held by each UICollectionView. Th
__Describing the Batch Update flow__

<!-- <img src="/static/images/development/threading1.png"> -->
![Threading1](/docs/static/images/development/threading1.png)
![Threading1](/static/images/development/threading1.png)

Starting with a simple example, let's say everything was on the main thread. The app would then appear unresponsive to the user until the entire flow finished. This is because the main thread's run loop (which receives operating system events for input) and the main thread dispatch queue compete for service time on the main thread. Execution goes back and forth between the run loop and the main dispatch queue while work is present in either. Now you can see that the work your code wants to schedule competes for time with system and user input events.

Let's identify the items that are not critical for execution on the main thread and dispatch those as blocks onto a background thread.

<!-- <img src="/static/images/development/threading2.png"> -->
![Threading2](/docs/static/images/development/threading2.png)
![Threading2](/static/images/development/threading2.png)

Ok, this is starting to look better. The main thread now only performs the minimal amount of work. This means the app will feel responsive to the user as it is able to consume Run Loop events with little interruption. However, a lot of the background work is still being done serially in one long running operation. If the network is the longest running task in this sequence, you would want to make sure they get fired off as early as possible. Let's also introduce another condition, we have a NSTimer running which injects a "hint" cell into the collection view. This is to demonstrate how the editing transaction queue is consumed serially.

The reason we must design the work to consume the editing transaction queue serially alongside the main queue is change sets must represent a transformation of the current data set in the collection view. This means that each time a `performBatchUpdate` is intended to be performed, it _must_ calculate using the latest data set used for display in the collection view. In this following image, this means that change sets can only be calculated from `A -> B`, and then when `performBatchUpdate` task is fully finished, another calculation can be done from `B -> C`. Consider data sets `B` and `C` coming in right after the other. If the queues consumed concurrently, then you would get a change set for `A -> B` and `A -> C`. The collection view will crash if a change set is requested for `A -> C`, while a `performBatchUpdate` is updating the collection view to reflect `A -> B` with a `A -> C` operation is queued. All this means that we create a pseudo-lock on the `editingTransactionQueue` by consuming it one operation at a time, either when the queue is empty or when an operation has finished as called by the completed `performBatchUpdate` invocation.

<!-- <img src="/static/images/development/threading3.png"> -->
![Threading3](/docs/static/images/development/threading3.png)
![Threading3](/static/images/development/threading3.png)

One small note is these diagrams are missing a representation of the main dispatch queue. Remember this is separate from the main thread. It is a data structure operated by GCD similarly to ASMainSerialQueue which handles execution to the main thread. All the work that goes from the background threads to the main thread is first put onto the main dispatch queue when using `dispatch_async(dispatch_get_main_queue())`.
.

0 comments on commit 7aba287

Please sign in to comment.