diff --git a/_docs/asrunloopqueue.md b/_docs/asrunloopqueue.md
index 4c071387..24344087 100755
--- a/_docs/asrunloopqueue.md
+++ b/_docs/asrunloopqueue.md
@@ -11,4 +11,4 @@ Even with main thread work, AsyncDisplayKit is able to dramatically reduce its i
It's a longer discussion why this kind of technique is extremely challenging to implement with `UIKit`, but it has to do with the fact that `AsyncDisplayKit` prepares content in advance, giving it a buffer of time where it can spread out the creation of these objects in tiny chunks. If it doesn't finish by the time it needs to be on screen, then it finishes the rest of what needs to be created in a single chunk. `UIKit` has no similar mechanisms to create things in advance, and there is always just one huge chunk as a view controller or cell needs to come on screen.
-**ASRunLoopQueue is enabled by default when running AsyncDisplayKit.** The developer does not need to be aware of it's existence except to know that it helps reduce main thread blockage.
\ No newline at end of file
+**ASRunLoopQueue is enabled by default when running AsyncDisplayKit.** A developer does not need to be aware of it's existence except to know that it helps reduce main thread blockage.
diff --git a/_docs/automatic-layout-examples.md b/_docs/automatic-layout-examples.md
index bfc19b39..7b2b4139 100755
--- a/_docs/automatic-layout-examples.md
+++ b/_docs/automatic-layout-examples.md
@@ -11,8 +11,11 @@ Three examples in increasing order of complexity.
-```objective-c
+
+
SwiftObjective-C
+
+
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constraint
{
ASStackLayoutSpec *vStack = [[ASStackLayoutSpec alloc] init];
@@ -29,7 +32,12 @@ Three examples in increasing order of complexity.
return insetSpec;
}
-```
+
+
+
+
+
+
###Discussion
@@ -37,7 +45,11 @@ Three examples in increasing order of complexity.
-```objective-c
+
+
SwiftObjective-C
+
+
+
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize
{
// header stack
@@ -71,8 +83,12 @@ Three examples in increasing order of complexity.
return verticalStack;
}
+
+
-```
+
+
+
###Discussion
@@ -82,7 +98,11 @@ Get the full ASDK project at examples/ASDKgram.
-```objective-c
+
+
SwiftObjective-C
+
+
+
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize {
ASLayoutSpec *textSpec = [self textSpec];
@@ -172,7 +192,13 @@ Get the full ASDK project at examples/ASDKgram.
ASBackgroundLayoutSpec *soldOutLabelOverBackground = [ASBackgroundLayoutSpec backgroundLayoutSpecWithChild:centerSoldOutLabel background:centerSoldOut];
return soldOutLabelOverBackground;
}
-```
+
+
+
+
+
+
###Discussion
+
Get the full ASDK project at examples/CatDealsCollectionView.
diff --git a/_docs/batch-fetching-api.md b/_docs/batch-fetching-api.md
index 63c65bd6..2c6ca744 100644
--- a/_docs/batch-fetching-api.md
+++ b/_docs/batch-fetching-api.md
@@ -6,51 +6,111 @@ prevPage: hit-test-slop.html
nextPage: implicit-hierarchy-mgmt.html
---
-AsyncDisplayKit's Batch Fetching API makes it easy for developers to add fetching of new data in chunks. In case the user scrolled to a specific range of a table or collection view the automatic batch fetching mechanism of ASDK kicks in.
+AsyncDisplayKit's Batch Fetching API makes it easy to add fetching chunks of new data. Usually this would be done in a `-scrollViewDidScroll:` method, but ASDK provides a more structured mechanism.
-You as a developer can define the point when the batch fetching mechanism should start via the `leadingScreensForBatching` property on an `ASTableView` or `ASCollectionView`. The default value for this property is 2.0.
+By default, as a user is scrolling, when they approach the point in the table or collection where they are 2 "screens" away from the end of the current content, the table will try to fetch more data.
-To support batch fetching you have to implement two methods in your ASTableView or ASCollectionView delegate object:
-The first method you have to implement is for ASTableView delegate:
+If you'd like to configure how far away from the end you should be, just change the `leadingScreensForBatching` property on an `ASTableView` or `ASCollectionView` to something else.
-`- (BOOL)shouldBatchFetchForTableView:(ASTableView *)tableView`
+
+
SwiftObjective-C
-or for ASCollectionView delegate:
+
+
+tableNode.view.leadingScreensForBatching = 3.0; // overriding default of 2.0
+
+
+tableNode.view.leadingScreensForBatching = 3.0 // overriding default of 2.0
+
+
+
-`- (BOOL)shouldBatchFetchForCollectionView:(ASCollectionView *)collectionView`
+### Batch Fetching Delegate Methods
-In this method you have decide if the batch fetching mechanism should kick in if the user scrolled in batch fetching range or not. Usually this decision is based on if there is still data to fetch or not, based on e.g. previous API calls or some local dataset operations.
+The first thing you have to do in order to support batch fetching, is implement a method that decides if it's an appropriate time to load new content or not.
-If you return NO from `- (BOOL)shouldBatchFetchForCollectionView:(ASCollectionView *)collectionView`, no new batch fetching process will happen, in case you return YES the batch fetching mechanism will start and the following method is called for your ASTableView delegate:
+For tables it would look something like:
- - (void)tableView:(ASTableView *)tableView willBeginBatchFetchWithContext:(ASBatchContext *)context;
+
+
SwiftObjective-C
-or for ASCollectionView delegate:
-
- - (void)collectionView:(ASCollectionView *)collectionView willBeginBatchFetchWithContext:(ASBatchContext *)context;
-
-First of all, you have to be careful within this method as it's called on a background thread. If you have to do anything on the main thread, you are responsible for dispatching it to the main thread and proceed with work you have to do in process to finish the batch fetch.
-
-Within `- (void)collectionView:(ASCollectionView *)collectionView willBeginBatchFetchWithContext:(ASBatchContext *)context;` you should do any necessary steps to fetch the next chunk of data e.g. from a local database, an API etc.
-
-After you finished fetching the next chunk of data, it is very important to let ASDK know that you finished the process. To do that you have to call `completeBatchFetching:` on the `context` object that was passed in with a parameter value of YES. This assures that the whole batch fetching mechanism stays in sync and a next batch fetching cycle can happen. Only by passing YES will the context know to attempt another batch update when necessary. If you pass in NO nothing will happen.
-
-Here you can see an example how a batch fetching cycle could look like:
-
-```objective-c
-- (BOOL)shouldBatchFetchForTableView:(ASTableView *)tableView
+
+
+- (BOOL)shouldBatchFetchForTableView:(ASTableView *)tableView
{
- // Decide if the batch fetching mechanism should kick in
- if (_stillDataToFetch) {
+ if (_weNeedMoreContent) {
return YES;
}
+
return NO;
}
+
+
+func shouldBatchFetchForTableView(tableView: ASTableView) -> Bool {
+ if (weNeedMoreContent) {
+ return true
+ }
+ return false
+}
+
+
+
+
+and for collections:
+
+
+
SwiftObjective-C
+
+
+
+
+- (BOOL)shouldBatchFetchForCollectionView:(ASCollectionView *)collectionView
+{
+ if (_weNeedMoreContent) {
+ return YES;
+ }
+
+ return NO;
+}
+
+
+func shouldBatchFetchForCollectionView(collectionView: ASCollectionView) -> Bool {
+ if (weNeedMoreContent) {
+ return true
+ }
+
+ return false
+}
+
+
+
+
+These methods will be called when the user has scrolled into the batch fetching range, and their answer will determine if another request actually needs to be made or not. Usually this decision is based on if there is still data to fetch.
+
+If you return NO, then no new batch fetching process will happen. If you return YES, the batch fetching mechanism will start and the following method will be called next.
+
+`-tableView:willBeginBatchFetchWithContext:`
+
+or
+
+`-collectionView:willBeginBatchFetchWithContext:`
+
+This is where you should actually fetch data, be it from a web API or some local database.
+
+
+Note: This method will always be called on a background thread. This means, if you need to do any work on the main thread, you should dispatch it to the main thread and then proceed with the work needed in order to finish the batch fetch operation.
+
+
+
+
SwiftObjective-C
+
+
+
- (void)tableView:(ASTableView *)tableView willBeginBatchFetchWithContext:(ASBatchContext *)context
{
// Fetch data most of the time asynchronoulsy from an API or local database
- NSArray *data = ...;
+ NSArray *newPhotos = [SomeSource getNewPhotos];
// Insert data into table or collection view
[self insertNewRowsInTableView:newPhotos];
@@ -61,9 +121,28 @@ Here you can see an example how a batch fetching cycle could look like:
// Properly finish the batch fetch
[context completeBatchFetching:YES]
}
-```
+
+
+func tableView(tableView: ASTableView, willBeginBatchFetchWithContext context: ASBatchContext) {
+ // Fetch data most of the time asynchronoulsy from an API or local database
+ let newPhotos = SomeSource.getNewPhotos()
-Check out the following sample apps to see the batch fetching API implemented within an app:
+ // Insert data into table or collection view
+ insertNewRowsInTableView(newPhotos)
+
+ // Decide if it's still necessary to trigger more batch fetches in the future
+ stillDataToFetch = ...
+
+ // Properly finish the batch fetch
+ context.completeBatchFetching(true)
+}
+
+
+
+
+Once you've finished fetching your data, it is very important to let ASDK know that you have finished the process. To do that, you need to call `-completeBatchFetching:` on the `context` object that was passed in with a parameter value of `YES`. This assures that the whole batch fetching mechanism stays in sync and the next batch fetching cycle can happen. Only by passing `YES` will the context know to attempt another batch update when necessary.
+
+Check out the following sample apps to see the batch fetching API in action:
- ASDKgram
- Kittens
diff --git a/_docs/debug-tool-pixel-scaling.md b/_docs/debug-tool-pixel-scaling.md
index c5d3097e..7431e65e 100644
--- a/_docs/debug-tool-pixel-scaling.md
+++ b/_docs/debug-tool-pixel-scaling.md
@@ -10,16 +10,33 @@ nextPage: debug-tool-ASRangeController.html
This debug feature adds a red text overlay on the bottom right hand corner of an ASImageNode if (and only if) the image’s size in pixels does not match it’s bounds size in pixels, e.g.
-```objective-c
-imageSizeInPixels = image.size * image.scale
-boundsSizeInPixels = bounds.size * contentsScale
-scaleFactor = imageSizeInPixels / boundsSizeInPixels
+
+
SwiftObjective-C
+
+
+
+CGFloat imageSizeInPixels = image.size.width * image.size.height;
+CGFloat boundsSizeInPixels = imageView.bounds.size.width * imageView.bounds.size.height;
+CGFloat scaleFactor = imageSizeInPixels / boundsSizeInPixels;
if (scaleFactor != 1.0) {
NSString *scaleString = [NSString stringWithFormat:@"%.2fx", scaleFactor];
_debugLabelNode.hidden = NO;
}
-```
+
+
+let imageSizeInPixels = image.size.width * image.size.height
+let boundsSizeInPixels = imageView.bounds.size.width * imageView.bounds.size.height
+let scaleFactor = imageSizeInPixels / boundsSizeInPixels
+
+if scaleFactor != 1.0 {
+ let scaleString = "\(scaleFactor)"
+ _debugLabelNode.hidden = false
+}
+
+
+
+
This debug feature is useful for quickly determining if you are
diff --git a/_docs/hit-test-slop.md b/_docs/hit-test-slop.md
index 4f1d319c..f9369ec8 100755
--- a/_docs/hit-test-slop.md
+++ b/_docs/hit-test-slop.md
@@ -10,10 +10,31 @@ nextPage: batch-fetching-api.html
ASDisplayNode is the base class for all nodes, so this property is available on any of AsyncDisplayKit's nodes.
-Note:
-
- - the default value is UIEdgeInsetsZero
- - This affects the default implementation of `-hitTest` and `-pointInside`, so subclasses should call super if you override it and want hitTestSlop applied.
-
+
+Note: This affects the default implementation of -hitTest and -pointInside, so subclasses should call super if you override it and want hitTestSlop applied.
+
A node's ability to capture touch events is restricted by its parent's bounds + parent hitTestSlop UIEdgeInsets. Should you want to extend the hitTestSlop of a child outside its parent's bounds, simply extend the parent node's hitTestSlop to include the child's hitTestSlop needs.
+
+### Usage
+
+A common need for hit test slop, is when you have a text node (aka label) you'd like to use as a button. Often, the text node's height won't meet the 44 point minimum recommended for tappable areas. In that case, you can calculate the difference, and apply a negative inset to your label to increase the tappable area.
+
+
+
SwiftObjective-C
+
+
+
+ASTextNode *textNode = [[ASTextNode alloc] init];
+
+CGFloat padding = (44.0 - button.bounds.size.height)/2.0;
+textNode.hitTestSlop = UIEdgeInsetsMake(-padding, 0, -padding, 0);
+
+
+let textNode = ASTextNode()
+
+let padding = (44.0 - button.bounds.size.height)/2.0
+textNode.hitTestSlop = UIEdgeInsetsMake(-padding, 0, -padding, 0)
+
+
+
\ No newline at end of file
diff --git a/_docs/image-modification-block.md b/_docs/image-modification-block.md
index b9f67768..bb39b234 100755
--- a/_docs/image-modification-block.md
+++ b/_docs/image-modification-block.md
@@ -6,4 +6,40 @@ prevPage: implicit-hierarchy-mgmt.html
nextPage: placeholder-fade-duration.html
---
-😑 This page is coming soon...
\ No newline at end of file
+Many times, operations that would affect the appearance of an image you're displaying are big sources of main thread work. Naturally, you want to move these to a background thread. By assigning an `imageModificationBlock` to your imageNode, you can define a set of transformations that need to happen asynchronously to any image that gets set on the imageNode.
+
+
+
SwiftObjective-C
+
+
+
+_backgroundImageNode.imageModificationBlock = ^(UIImage *image) {
+ UIImage *newImage = [image applyBlurWithRadius:30
+ tintColor:[UIColor colorWithWhite:0.5 alpha:0.3]
+ saturationDeltaFactor:1.8
+ maskImage:nil];
+ return newImage ? newImage : image;
+};
+
+//some time later...
+
+_backgroundImageNode.image = someImage;
+
+
+
+backgroundImageNode.imageModificationBlock = { image in
+ let newImage = image.applyBlurWithRadius(30, tintColor: UIColor(white: 0.5, alpha: 0.3),
+ saturationDeltaFactor: 1.8,
+ maskImage: nil)
+ return (newImage != nil) ? newImage : image
+}
+
+//some time later...
+
+backgroundImageNode.image = someImage
+
+
+
+
+The image named "someImage" will now be blurred asynchronously before being assigned to the imageNode to be displayed.
+
diff --git a/_docs/layer-backing.md b/_docs/layer-backing.md
index 7e5df017..b93cd28f 100755
--- a/_docs/layer-backing.md
+++ b/_docs/layer-backing.md
@@ -8,7 +8,6 @@ nextPage: subtree-rasterization.html
In some cases, you can substantially improve your app's performance by using layers instead of views. We recommend enabling layer-backing as a matter of course in **any custom node that doesn't need touch handling**.
-
With UIKit, manually converting view-based code to layers is laborious due to the difference in APIs. Worse, if at some point you need to enable touch handling or other view-specific functionality, you have to manually convert everything back (and risk regressions!).
With all AsyncDisplayKit nodes, converting an entire subtree from views to layers is as simple as...
@@ -16,7 +15,7 @@ With all AsyncDisplayKit nodes, converting an entire subtree from views to layer
SwiftObjective-C
-
+
rootNode.layerBacked = YES;
@@ -24,7 +23,6 @@ rootNode.layerBacked = true
-
...and if you need to go back, it's as simple as deleting one line.
diff --git a/_docs/scroll-node.md b/_docs/scroll-node.md
index f12a34c5..958e6189 100755
--- a/_docs/scroll-node.md
+++ b/_docs/scroll-node.md
@@ -6,4 +6,40 @@ prevPage: video-node.html
nextPage: automatic-layout-containers.html
---
-😑 This page is coming soon...
\ No newline at end of file
+`ASScrollNode` is literally a wrapped `UIScrollView`.
+
+### Basic Usage
+
+In case you're not familiar with scroll views, they are basically windows into content that would take up more space than can fit in that area.
+
+Say you have a giant image, but you only want to take up 200x200 pts on the screen.
+
+
+
SwiftObjective-C
+
+
+
+UIImage *scrollNodeImage = [UIImage imageNamed:@"image"];
+ASScrollNode *scrollNode = [[ASScrollNode alloc] init];
+
+scrollNode.preferredFrameSize = CGSizeMake(200.0, 200.0);
+
+UIScrollView *scrollNodeView = scrollNode.view;
+[scrollNodeView addSubview:[[UIImageView alloc] initWithImage:scrollNodeImage]];
+scrollNodeView.contentSize = scrollNodeImage.size;
+
+
+let scrollNodeImage = UIImage(named: "image")
+let scrollNode = ASScrollNode()
+
+scrollNode.preferredFrameSize = CGSize(width: 200.0, height: 200.0)
+
+let scrollNodeView = scrollNode.view
+scrollNodeView.addSubview(UIImageView(image: scrollNodeImage))
+scrollNodeView.contentSize = scrollNodeImage.size
+
+
+
+
+As you can see, the scrollNode's underlying view is a `UIScrollView`.
+
diff --git a/static/main.css b/static/main.css
index e6f58543..aba1a4f6 100755
--- a/static/main.css
+++ b/static/main.css
@@ -92,7 +92,7 @@ code {
p code, span code, li code {
border: 1px solid rgb(220, 220, 220);
- background-color: rgba(90, 140, 140, 0.1);
+ background-color: rgba(135, 215, 255, 0.2);
}
.highlight pre, .redhighlight pre {