GithubHelp home page GithubHelp logo

facebookarchive / asyncdisplaykit Goto Github PK

View Code? Open in Web Editor NEW
13.4K 550.0 2.2K 127.96 MB

Smooth asynchronous user interfaces for iOS apps.

Home Page: http://asyncdisplaykit.org

License: Other

Objective-C 46.35% Objective-C++ 49.21% C++ 0.04% Ruby 0.20% Shell 0.19% Swift 3.82% Python 0.19%

asyncdisplaykit's Introduction

AsyncDisplayKit has been moved and renamed: Texture

Texture Logo



































AsyncDisplayKit

Apps Using Downloads

Platform Languages

Version Carthage compatible License

Installation

ASDK is available via CocoaPods or Carthage. See our Installation guide for instructions.

Performance Gains

AsyncDisplayKit's basic unit is the node. An ASDisplayNode is an abstraction over UIView, which in turn is an abstraction over CALayer. Unlike views, which can only be used on the main thread, nodes are thread-safe: you can instantiate and configure entire hierarchies of them in parallel on background threads.

To keep its user interface smooth and responsive, your app should render at 60 frames per second — the gold standard on iOS. This means the main thread has one-sixtieth of a second to push each frame. That's 16 milliseconds to execute all layout and drawing code! And because of system overhead, your code usually has less than ten milliseconds to run before it causes a frame drop.

AsyncDisplayKit lets you move image decoding, text sizing and rendering, layout, and other expensive UI operations off the main thread, to keep the main thread available to respond to user interaction.

Advanced Developer Features

As the framework has grown, many features have been added that can save developers tons of time by eliminating common boilerplate style structures common in modern iOS apps. If you've ever dealt with cell reuse bugs, tried to performantly preload data for a page or scroll style interface or even just tried to keep your app from dropping too many frames you can benefit from integrating ASDK.

Learn More

Getting Help

We use Slack for real-time debugging, community updates, and general talk about ASDK. Signup yourself or email AsyncDisplayKit(at)gmail.com to get an invite.

Contributing

We welcome any contributions. See the CONTRIBUTING file for how to get involved.

License

AsyncDisplayKit is BSD-licensed. We also provide an additional patent grant. The files in the /examples directory are licensed under a separate license as specified in each file; documentation is licensed CC-BY-4.0.

asyncdisplaykit's People

Contributors

aaronschubert0 avatar adlai-holler avatar andyscott avatar appleguy avatar eanagel avatar ejensen avatar eke avatar ekurutepe avatar erichoracek avatar gareth-chillingo avatar garrettmoon avatar george-gw avatar hannahmbanana avatar jack-stripe avatar knopp avatar lappp9 avatar levi avatar maicki avatar marmelroy avatar nguyenhuy avatar paulyoung avatar rahul-malik avatar rcancro avatar rnystrom avatar samhsiung avatar secretiverhyme avatar soniccat avatar srandazzo avatar tomizimobile avatar yue-wang-google avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

asyncdisplaykit's Issues

Kittens sample sometimes terminates with assertion failure: 'Incorrect display node thread affinity'

I downloaded the zip, and ran pod install in the Kittens sample directory. This error is thrown every few runs...

2014-10-20 11:37:46.437 Sample[18223:842005] *** Assertion failure in -[ASImageNode setImage:], /Users/n/Desktop/AsyncDisplayKit-master/AsyncDisplayKit/ASImageNode.mm:108
2014-10-20 11:37:46.437 Sample[18223:842008] *** Assertion failure in -[ASImageNode setImage:], /Users/n/Desktop/AsyncDisplayKit-master/AsyncDisplayKit/ASImageNode.mm:108
2014-10-20 11:37:46.437 Sample[18223:842014] *** Assertion failure in -[ASImageNode setImage:], /Users/n/Desktop/AsyncDisplayKit-master/AsyncDisplayKit/ASImageNode.mm:108
2014-10-20 11:37:46.445 Sample[18223:842008] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Incorrect display node thread affinity'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010b539f35 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010b1d2bb7 objc_exception_throw + 45
    2   CoreFoundation                      0x000000010b539d9a +[NSException raise:format:arguments:] + 106
    3   Foundation                          0x000000010adef5df -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 195
    4   Sample                              0x000000010ab40f73 -[ASImageNode setImage:] + 323
    5   Sample                              0x000000010ab0bc8f __25-[KittenNode fetchKitten]_block_invoke + 591
    6   CFNetwork                           0x000000010de31935 __67+[NSURLConnection sendAsynchronousRequest:queue:completionHandler:]_block_invoke_2 + 155
    7   Foundation                          0x000000010ae1301f __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 7
    8   Foundation                          0x000000010ad52db2 -[NSBlockOperation main] + 98
    9   Foundation                          0x000000010ad35384 -[__NSOperationInternal _start:] + 645
    10  Foundation                          0x000000010ad34f93 __NSOQSchedule_f + 184
    11  libdispatch.dylib                   0x000000010d3e37f4 _dispatch_client_callout + 8
    12  libdispatch.dylib                   0x000000010d3cbb22 _dispatch_queue_drain + 1417
    13  libdispatch.dylib                   0x000000010d3cb432 _dispatch_queue_invoke + 235
    14  libdispatch.dylib                   0x000000010d3cdfc1 _dispatch_root_queue_drain + 685
    15  libdispatch.dylib                   0x000000010d3cf5d9 _dispatch_worker_thread3 + 111
    16  libsystem_pthread.dylib             0x000000010d7676cb _pthread_wqthread + 729
    17  libsystem_pthread.dylib             0x000000010d7654a1 start_wqthread + 13
)
2014-10-20 11:37:46.445 Sample[18223:842014] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Incorrect display node thread affinity'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010b539f35 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010b1d2bb7 objc_exception_throw + 45
    2   CoreFoundation                      0x000000010b539d9a +[NSException raise:format:arguments:] + 106
    3   Foundation                          0x000000010adef5df -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 195
    4   Sample                              0x000000010ab40f73 -[ASImageNode setImage:] + 323
    5   Sample                              0x000000010ab0bc8f __25-[KittenNode fetchKitten]_block_invoke + 591
    6   CFNetwork                           0x000000010de31935 __67+[NSURLConnection sendAsynchronousRequest:queue:completionHandler:]_block_invoke_2 + 155
    7   Foundation                          0x000000010ae1301f __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 7
    8   Foundation                          0x000000010ad52db2 -[NSBlockOperation main] + 98
    9   Foundation                          0x000000010ad35384 -[__NSOperationInternal _start:] + 645
    10  Foundation                          0x000000010ad34f93 __NSOQSchedule_f + 184
    11  libdispatch.dylib                   0x000000010d3e37f4 _dispatch_client_callout + 8
    12  libdispatch.dylib                   0x000000010d3cbb22 _dispatch_queue_drain + 1417
    13  libdispatch.dylib                   0x000000010d3cb432 _dispatch_queue_invoke + 235
    14  libdispatch.dylib                   0x000000010d3cdfc1 _dispatch_root_queue_drain + 685
    15  libdispatch.dylib                   0x000000010d3cf5d9 _dispatch_worker_thread3 + 111
    16  libsystem_pthread.dylib             0x000000010d7676cb _pthread_wqthread + 729
    17  libsystem_pthread.dylib             0x000000010d7654a1 start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException2014-10-20 11:37:46.445 Sample[18223:842005] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Incorrect display node thread affinity'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010b539f35 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010b1d2bb7 objc_exception_throw + 45
    2   CoreFoundation                      0x000000010b539d9a +[NSException raise:format:arguments:] + 106
    3   Foundation                          0x000000010adef5df -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 195
    4   Sample                              0x000000010ab40f73 -[ASImageNode setImage:] + 323
    5   Sample                              0x000000010ab0bc8f __25-[KittenNode fetchKitten]_block_invoke + 591
    6   CFNetwork                           0x000000010de31935 __67+[NSURLConnection sendAsynchronousRequest:queue:completionHandler:]_block_invoke_2 + 155
    7   Foundation                          0x000000010ae1301f __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 7
    8   Foundation                          0x000000010ad52db2 -[NSBlockOperation main] + 98
    9   Foundation                          0x000000010ad35384 -[__NSOperationInternal _start:] + 645
    10  Foundation                          0x000000010ad34f93 __NSOQSchedule_f + 184
    11  libdispatch.dylib                   0x000000010d3e37f4 _dispatch_client_callout + 8
    12  libdispatch.dylib                   0x000000010d3cbb22 _dispatch_queue_drain + 1417
    13  libdispatch.dylib                   0x000000010d3cb432 _dispatch_queue_invoke + 235
    14  libdispatch.dylib                   0x000000010d3cdfc1 _dispatch_root_queue_drain + 685
    15  libdispatch.dylib                   0x000000010d3cf5d9 _dispatch_worker_thread3 + 111
    16  libsystem_pthread.dylib             0x000000010d7676cb _pthread_wqthread + 729
    17  libsystem_pthread.dylib             0x000000010d7654a1 start_wqthread + 13
)
libc++abi.dylib: 
terminating with uncaught exception of type NSExceptionlibc++abi.dylib: 

Caching code seems entirely unused

git grep -i cache shows mentions of caching but no actual logic.

A quick sweep shows that the following is unused:

  • ASDisplayNode: NSArray *cachedNodes
  • ASDisplayNode: BOOL cacheNode
  • ASDisplayNode: ASDisplayNode *superCacheNode
  • ASImageCacheProtocol: Unimplemented and unused

tintColor property default would fall out of sync if iOS were to change it.

See my comment on this PR: #75

This is not a critical issue, but it's worth thinking about how it could be improved. The only workaround I can immediately think of is for the ASDK framework to allocate a singleton UIView (on the main thread) simply to read its tintColor property, so that the default value can be set programmatically in that way.

Inconsistent boolean property naming

A lot of boolean properties don't follow Apple's naming conventions while a lot of others do. For example, in ASDisplayNode.h, there are a few boolean properties that look like this:

@property (nonatomic, readonly) BOOL isSynchronous;

Whereas in ASControlNode.h, all the properties follow the named getter convention:

@property (nonatomic, readwrite, assign, getter=isEnabled) BOOL enabled

Just wanted to point this out.

[ASTextNode] Improve documentation on using links

- (void)textNode:(ASTextNode *)textNode tappedLinkAttribute:(NSString *)attribute value:(id)value atPoint:(CGPoint)point textRange:(NSRange)textRange
{
    if (_linkClickedBlock) {
        if ([value isKindOfClass:[NSURL class]]) {
            _linkClickedBlock((NSURL *)value);
            return;
        } else if ([value isKindOfClass:[NSString class]]) {
            NSURL *url = [NSURL URLWithString:value];
            _linkClickedBlock(url);
        }
    }
}

- (BOOL)textNode:(ASTextNode *)textNode shouldHighlightLinkAttribute:(NSString *)attribute value:(id)value
{
    return NO;
    // Test with:
    // return [attribute isEqualToString:NSLinkAttributeName];
}

Text node is configured as such (code from just before NSLink was made a default link attribute):

        ASTextNode *textNode = [[ASTextNode alloc] init];
        textNode.delegate = self;
        textNode.linkAttributeNames = @[NSLinkAttributeName];
        textNode.opaque = YES;
        textNode.userInteractionEnabled = YES;

Breakpoint configured for the first delegate method is never hit unless the link is also highlight-able.

ASRangeController NSInternalInconsistencyException

The kitten sample is modified to be a UIPageViewController.
Just like feeds, an extra kitten node is appended after 1 sec in each ASTableView.

When the page controller is swiped, an error occurs.

 *** Assertion failure in -[ASRangeController appendNodesWithIndexPaths:], /Users/leo/Projects/AsyncDisplayKit_ASTableView_bug_with_UIPageViewController/Pods/AsyncDisplayKit/AsyncDisplayKit/Details/ASRangeController.mm:598
2014-10-23 13:46:48.037 Sample[10278:21109907] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'invalid argument'

example project: https://github.com/l4u/AsyncDisplayKit_ASTableView_bug_with_UIPageViewController/tree/append_bug
ful log:
https://gist.github.com/l4u/a3bf721107b37af83c4a

Question related to "Immutable Views"

After viewing this, I was wondering if the Components that is mentioned by Ari Grant, is/was using AsyncDisplay, or the idea predates AsyncDisplay altogether.

Just a quick addendum, I mean the use of immutability on the UI.

P.S: This might be wrong place to ask this, if there is a better one, please let me know.

Rename "sizeToFit:" to "sizeThatFits:"

The naming of

- (CGSize)sizeToFit:(CGSize)constrainedSize;

in ASDisplayNode is really confusing. UIView uses the exact same method name with void return type to actually resize the view, and sizeThatFits: for only computing the size. I think renaming the ASDisplayNode method to

- (CGSize)sizeThatFits:(CGSize)constrainedSize;

would make a lot of sense.

PS. The comment in ASDisplayNode.h already mentions it as a TODO.

Fix all appledoc warnings.

Once appledoc runs with zero warnings, add it as a Travis CI build step to ensure no documentation regressions.

[ASTextNode] Support NSDataDetectors

Quote from Apple docs:

NSRegularExpression is designed to be immutable and thread safe, so that a single instance can be used in matching operations on multiple threads at once.

UITextView property signature:

@property(nonatomic) UIDataDetectorTypes dataDetectorTypes

NSDataDetector factory method signature:

+ (NSDataDetector *)dataDetectorWithTypes:(NSTextCheckingTypes)checkingTypes error:(NSError **)error;

NSDataDetector's supported NSTextCheckingTypes:

NSTextCheckingTypeDate, NSTextCheckingTypeAddress, NSTextCheckingTypeLink, NSTextCheckingTypePhoneNumber, and NSTextCheckingTypeTransitInformation

UITextView's accepted UIDataDetectorType:

UIDataDetectorTypePhoneNumber   = 1 << 0,
   UIDataDetectorTypeLink          = 1 << 1,
   UIDataDetectorTypeAddress       = 1 << 2,
   UIDataDetectorTypeCalendarEvent = 1 << 3,
   UIDataDetectorTypeNone          = 0,
   UIDataDetectorTypeAll           = NSUIntegerMax

So basically, a very close correspondence in API. Seems like a pretty manageable add-in.

Provide an ASCollectionView

In the same way that ASTableView is a UITableView subclass that integrates node-based cells and a working range, a UICollectionView subclass that benefits form the advances made by ASDK would be fantastic.

Feature request: option to bypass UIImage decoding/drawing in ASImageNode

My understanding is that on every ASImageNode redraw, provided image is decoded and scaled in background context. This is unnecessary work for bundled images (like UI elements, icons, backgrounds etc.) which should already be provided in exactly same size as displayed in interface, and if image is loaded using imageNamed:, decoded image is cached by UIKit (decoding is done only once per image).

Using AsyncDisplayKit, if such image is used in many instances of ASImageNode, same work for scaling and decoding will be done each time any of these nodes redraws. This causes delay before UI element can be displayed.

What is more, images can be correctly decoded and sized even if they are downloaded from web. I'm using Path's FastImageCache https://github.com/path/FastImageCache for image caching. One of great features of FIC is background image sizing and decoding. Other frameworks and caching systems also often incorporate such functionality.

This issue is especially visible in UITableView cells, where same UI images are unnecessarily decoded and sized for nodes in every cell. Issue #37 causes even more additional image redraws.

Adding property to ASImageNode which would skip sizing and decoding should improve performance if image is already decoded and sized. Another solution could be caching of decoded images.

What are your thoughts on this issue?

Support UIMenuController

i.e. for copy-paste support on text nodes.

Trying to funnel - (BOOL)canPerformAction:(SEL)action withSender:(id)sender from _ASDisplayView to the node didn't seem to work.

Cell Node sliding

Somewhat annoyingly, the nodes seem to slide in after they're loaded. Is there a missing [CATransaction setDisableActions:] call somewhere?

(the fading is just due to application loading in; the sliding is the issue)
sliding

iOS 6 Support

Seems like AsyncDisplayKit only support iOS 7 or later due to dependency of TextKit. It's possible to add support for iOS 6 by rewriting ASTextNode with CoreText?

ASTextNode + setAttributedString + assert

I often handle assertion in -[ASTextNode setAttributedString] at line [self invalidateCalculatedSize].

I use next check to decide, if I should set text on mainThread:

 if (textNode.isNodeLoaded && [NSThread isMainThread] == NO) {
            dispatch_async(dispatch_get_main_queue(), ^{
                textNode.attributedString = text;
            });
        }
        else {
            textNode.attributedString = text;
        }

But node might be loaded after my check and before execution of line textNode.attributedString = text.

Is there other way to check if I should set attributedString on mainThread?
Is it a bad purpose to set attributedString after node is being loaded?

Retain cycles in ASDisplayNode and ASTableView

Preparing to send a pull request to fix some retain cycles in ASDisplayNode and ASTableView.

I don't know whether you guys are planning to keep the non-ARC test classes around. Gotta say I've found them pretty useful to test those memory issues so I'll be adding tests covering these cases.

There is one issue I noticed in ASRangeController that I didn't fix. Nodes are added to a shared workingView to start rendering but they are not removed from that view when ASRangeController is destroyed. This can cause nodes to stay around indefinitely.

An easy fix would be to copy this teardown code to dealloc:

for (UIView *view in [[ASRangeController workingView] subviews]) {
  [view removeFromSuperview];
}

But since the same workingView is shared across all ASRangeControllers, I don't know what impact this could have when an app uses many of them at the same time.

Appending Nodes at the start using appendNodesWithIndexPaths:

i am trying to add nodes at the start of the table view using appendNodesWithIndexPaths but it appends nodes at the end which leaves my table view in an inconsistent data. So is it possible to append nodes at the start using this method ,if not what are my options except reloading the entire table view?

Support ASCellNode resizing in ASTableView

The ability to updating rows is important when changing cell's height, otherwise we need to call - reloadData on ASTableView. But it's documented that - reloadData will "destroying the working range and all cached nodes", which is quite expensive.

Support ASDK as a static library without CocoaPods

I am including AsyncDisplayKit as static library in my project, but in order to import the headers in this way: #import <AsyncDisplayKit/AsyncDisplayKit.h>, the public headers folder path of the AsyncDisplayKit static library target needs to be changed to: include/$(TARGET_NAME). It would be great if you could update this in the next release.

ASRangeController teardownAllNodes issue

We should check if node is loaded in the cycle. Otherwise node.view might load view.

- (void)teardownAllNodes
{
  for (ASCellNode *node in _nodes.allValues) {
    [node removeFromSupernode];
    [node.view removeFromSuperview];
  }
  [_nodes removeAllObjects];
  _nodes = nil;

}

[ASDisplayNode] Support UIMenuController

I found two identifiers that were only mentioned in comments but the types themselves aren't defined anywhere:

ASDisplayNodeView, seems like a protocol that any view usable in a async display node would need to implement, mentioned in _ASPendingState.h:25.

ASDisplayNodeAsyncView, seems like a subclass of UIView that would too be usable in a node (also the way of adding more async views by subclassing), mentioned in ASDisplayNode.h:22.

Could you please add more details on these types? Plus some sort of a documentation of how to add a custom async view class. Thanks!

Need global locking in ASTextNodeRenderer.

Repro project:
http://www.atoulou.se/Repro.tar.bz2

Very barebones. Remember to set zombies to on. Tested using iPhone 5s (7.1) Simulator on OS X 10.9.

Crash 1 (almost every time):

(lldb) thread backtrace
* thread #4: tid = 0x18149, 0x00000001091accc4 CoreFoundation`___forwarding___ + 772, queue = 'com.facebook.AsyncDisplayKit.ASRangeController.sizingQueue', stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
    frame #0: 0x00000001091accc4 CoreFoundation`___forwarding___ + 772
    frame #1: 0x00000001091ac938 CoreFoundation`__forwarding_prep_0___ + 120
    frame #2: 0x000000010d980ade UIFoundation`-[NSTypesetter _updateParagraphStyleCache:] + 319
    frame #3: 0x000000010d981b5c UIFoundation`-[NSTypesetter getLineFragmentRect:usedRect:forParagraphSeparatorGlyphRange:atProposedOrigin:] + 633
    frame #4: 0x000000010d98430c UIFoundation`-[NSTypesetter _layoutGlyphsInLayoutManager:startingAtGlyphIndex:maxNumberOfLineFragments:maxCharacterIndex:nextGlyphIndex:nextCharacterIndex:] + 7720
    frame #5: 0x000000010d984872 UIFoundation`-[NSTypesetter layoutGlyphsInLayoutManager:startingAtGlyphIndex:maxNumberOfLineFragments:nextGlyphIndex:] + 105
    frame #6: 0x000000010d92b6fc UIFoundation`-[NSATSTypesetter layoutGlyphsInLayoutManager:startingAtGlyphIndex:maxNumberOfLineFragments:nextGlyphIndex:] + 460
  * frame #7: 0x000000010d94d313 UIFoundation`-[NSLayoutManager insertTextContainer:atIndex:] + 926
    frame #8: 0x000000010895250d Repro`-[ASTextNodeRenderer _initializeTextKitComponentsWithAttributedString:](self=0x00007f9259d004f0, _cmd=0x000000010896ba33, attributedString=0x0000000000000000) + 957 at ASTextNodeRenderer.mm:90
    frame #9: 0x0000000108952115 Repro`-[ASTextNodeRenderer _initializeTextKitComponentsIfNeeded](self=0x00007f9259d004f0, _cmd=0x000000010896bb70) + 101 at ASTextNodeRenderer.mm:69
    frame #10: 0x0000000108952d94 Repro`-[ASTextNodeRenderer size](self=0x00007f9259d004f0, _cmd=0x0000000110e50d67) + 36 at ASTextNodeRenderer.mm:169
    frame #11: 0x0000000108947c54 Repro`-[ASTextNode calculateSizeThatFits:](self=0x00007f9259e21a80, _cmd=0x000000010896804b, constrainedSize=CGSize at 0x00000001157ec948) + 2548 at ASTextNode.mm:184
    frame #12: 0x000000010891e0c4 Repro`-[ASDisplayNode measure:](self=0x00007f9259e21a80, _cmd=0x0000000108967ff7, constrainedSize=CGSize at 0x00000001157ecab8) + 660 at ASDisplayNode.mm:323
    frame #13: 0x0000000108901694 Repro`-[ReproNode calculateSizeThatFits:](self=0x00007f9259e21950, _cmd=0x000000010896804b, constrainedSize=CGSize at 0x00000001157ecb30) + 116 at ReproNode.m:33
    frame #14: 0x000000010891e0c4 Repro`-[ASDisplayNode measure:](self=0x00007f9259e21950, _cmd=0x0000000108967ff7, constrainedSize=CGSize at 0x00000001157ecc98) + 660 at ASDisplayNode.mm:323
    frame #15: 0x0000000108941fb5 Repro`__34-[ASRangeController sizeNextBlock]_block_invoke_2(.block_descriptor=<unavailable>) + 213 at ASRangeController.mm:538
    frame #16: 0x000000010ab6a851 libdispatch.dylib`_dispatch_call_block_and_release + 12
    frame #17: 0x000000010ab7d72d libdispatch.dylib`_dispatch_client_callout + 8
    frame #18: 0x000000010ab6beab libdispatch.dylib`_dispatch_async_redirect_invoke + 174
    frame #19: 0x000000010ab7d72d libdispatch.dylib`_dispatch_client_callout + 8
    frame #20: 0x000000010ab6db27 libdispatch.dylib`_dispatch_root_queue_drain + 380
    frame #21: 0x000000010ab6dd12 libdispatch.dylib`_dispatch_worker_thread2 + 40
    frame #22: 0x000000010af1bef8 libsystem_pthread.dylib`_pthread_wqthread + 314
    frame #23: 0x000000010af1efb9 libsystem_pthread.dylib`start_wqthread + 13
(lldb) 

Crash 2 (uncommon?):

(lldb) thread backtrace
* thread #4: tid = 0x17667, 0x0000000000000000, queue = 'com.facebook.AsyncDisplayKit.ASRangeController.sizingQueue', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
    frame #0: 0x0000000000000000
    frame #1: 0x00000001147cd893 UIFoundation`+[NSTextStorage allocWithZone:] + 33
  * frame #2: 0x000000010f7cb219 Repro`-[ASTextNodeRenderer _initializeTextKitComponentsWithAttributedString:](self=0x00007f880d110d50, _cmd=0x000000010f7e4a33, attributedString=0x0000000000000000) + 201 at ASTextNodeRenderer.mm:78
    frame #3: 0x000000010f7cb115 Repro`-[ASTextNodeRenderer _initializeTextKitComponentsIfNeeded](self=0x00007f880d110d50, _cmd=0x000000010f7e4b70) + 101 at ASTextNodeRenderer.mm:69
    frame #4: 0x000000010f7cbd94 Repro`-[ASTextNodeRenderer size](self=0x00007f880d110d50, _cmd=0x0000000117cb0d67) + 36 at ASTextNodeRenderer.mm:169
    frame #5: 0x000000010f7c0c54 Repro`-[ASTextNode calculateSizeThatFits:](self=0x00007f880ad16d70, _cmd=0x000000010f7e104b, constrainedSize=CGSize at 0x000000011c539948) + 2548 at ASTextNode.mm:184
    frame #6: 0x000000010f7970c4 Repro`-[ASDisplayNode measure:](self=0x00007f880ad16d70, _cmd=0x000000010f7e0ff7, constrainedSize=CGSize at 0x000000011c539ab8) + 660 at ASDisplayNode.mm:323
    frame #7: 0x000000010f77a694 Repro`-[ReproNode calculateSizeThatFits:](self=0x00007f880ad166b0, _cmd=0x000000010f7e104b, constrainedSize=CGSize at 0x000000011c539b30) + 116 at ReproNode.m:33
    frame #8: 0x000000010f7970c4 Repro`-[ASDisplayNode measure:](self=0x00007f880ad166b0, _cmd=0x000000010f7e0ff7, constrainedSize=CGSize at 0x000000011c539c98) + 660 at ASDisplayNode.mm:323
    frame #9: 0x000000010f7bafb5 Repro`__34-[ASRangeController sizeNextBlock]_block_invoke_2(.block_descriptor=<unavailable>) + 213 at ASRangeController.mm:538
    frame #10: 0x00000001119ca851 libdispatch.dylib`_dispatch_call_block_and_release + 12
    frame #11: 0x00000001119dd72d libdispatch.dylib`_dispatch_client_callout + 8
    frame #12: 0x00000001119cbeab libdispatch.dylib`_dispatch_async_redirect_invoke + 174
    frame #13: 0x00000001119dd72d libdispatch.dylib`_dispatch_client_callout + 8
    frame #14: 0x00000001119cdb27 libdispatch.dylib`_dispatch_root_queue_drain + 380
    frame #15: 0x00000001119cdd12 libdispatch.dylib`_dispatch_worker_thread2 + 40
    frame #16: 0x0000000111d72ef8 libsystem_pthread.dylib`_pthread_wqthread + 314
    frame #17: 0x0000000111d75fb9 libsystem_pthread.dylib`start_wqthread + 13
(lldb) list
   88     _textContainer.lineBreakMode = _truncationMode;
   89   
   90     [_layoutManager addTextContainer:_textContainer];
   91   
   92     [self _invalidateLayout];
   93   }
   94   
   95   #pragma mark - Layout Initialization
   96   
   97   - (void)_invalidateLayout

[ASDisplayNode] Support .transform and .subnodeTransform in point conversion methods

Tried updating this for a couple of hours yesterday (10-19). I realized that .transform isn't supported either, in addition to .subnodeTransform.

Technically, this could be seen as a bug when either .transform or .subnodeTransform aren't the identity matrix.

After banging at it for a while, I think that it's the right solution to reorient the methods to recursively call convertPoint/convertRect methods rather than trying to correctly compose arrays.

It's easier to understand and check, and any sane screen dimensions aren't going to be large enough numbers - floats should be accurate to within .5 up to 2^23 , and doubles up to 2^52 (per http://stackoverflow.com/questions/872544/precision-of-floating-point); the built up error from applying, say, seven transforms simply won't going to be that large - and this is for point conversion, not display.

That, or I could continue trying to figure out the right incantations to build the correct transform matrix, this time accounting for .transform and .supernode.subnodeTransform.

3 Failing tests on Xcode 6 beta (seed 4)

Seems like there are some failing tests on Xcode 6 beta (iOS 8 beta).

testSpaceBoundingBoxForNoWordKerning and testSpaceBoundingBoxForWordKerning fail because of bounding box's width, which returns different results on Xcode 5/iOS 7.1 (value = 4.0) and Xcode 6/iOS 8 (value = 3.55200005...). I'm assuming kerning returns different widths because the system font was slightly tweaked in iOS 8. Not sure how to fix this for both versions while still testing expected behavior.

testAttributeCleansing fails because apparently the expected and actual cleansed strings don't match, but from all the visible properties they are the same strings. So it might be the way NSAttributedString uses its isEqualToAttributedString: in iOS 8.

Sorry for not being too helpful, just wanted to keep an eye on these because it might mean Apple introduces slight changes in behaviour in text rendering that actually provide different values.

Fix incorrect -display and -drawInContext: references in ASDisplayNode(Subclasses)

ASDisplayNode+Subclasses.h references these methods…

// Subclasses should implement -display if the layer's contents will be set directly to an arbitrary buffer (e.g. decoded JPEG).
// Called on a background thread, some time after the view has been created.  This method is called if -drawInContext: is not implemented.
- (void)display;

// Subclasses should implement if a backing store / context is desired.  Called on a background thread, some time after the view has been created.
- (void)drawInContext:(CGContextRef)ctx;

…but they're actually no longer used. Update this header to reference the current mechanism from _ASDisplayLayer.h:

// Called on the display queue and/or main queue (MUST BE THREAD SAFE)

/**
 @summary Delegate method to draw layer contents into a CGBitmapContext. The current UIGraphics context will be set to an appropriate context.
 @param parameters An object describing all of the properties you need to draw. Return this from -drawParametersForAsyncLayer:
 @param isCancelled Execute this block to check whether the current drawing operation has been cancelled to avoid unnecessary work. A return value of YES means cancel drawing and return.
 @param isRasterizing YES if the layer is being rasterized into another layer, in which case drawRect: probably wants to avoid doing things like filling its bounds with a zero-alpha color to clear the backing store.
 */
+ (void)drawRect:(CGRect)bounds withParameters:(id<NSObject>)parameters isCancelled:(asdisplaynode_iscancelled_block_t)isCancelledBlock isRasterizing:(BOOL)isRasterizing;

/**
 @summary Delegate override to provide new layer contents as a UIImage.
 @param parameters An object describing all of the properties you need to draw. Return this from -drawParametersForAsyncLayer:
 @param isCancelled Execute this block to check whether the current drawing operation has been cancelled to avoid unnecessary work. A return value of YES means cancel drawing and return.
 @return A UIImage with contents that are ready to display on the main thread. Make sure that the image is already decoded before returning it here.
 */
+ (UIImage *)displayWithParameters:(id<NSObject>)parameters isCancelled:(asdisplaynode_iscancelled_block_t)isCancelledBlock;

// Called on the main thread only

/**
 @summary Delegate override for drawParameters
 */
- (NSObject *)drawParametersForAsyncLayer:(_ASDisplayLayer *)layer;

Runloop work distribution

In the NSLondon video, Scott talks about runloop work distribution. Unless I’m missing something here, this optimization does not seem to be implemented right now. I was wondering if you were still planning on adding this feature to the framework.

I understand this strategy applies to expensive operations that have to run on the main thread, such as creating views and adding them to the hierarchy. What about the opposite operations (removing from hierarchy and deallocating views)? Does those benefit from being distributed as well?

{.location = 0, .length = 0} is a valid NSRange

In ASRangeController.mm

static BOOL ASRangeIsValid(NSRange range)
{
  return range.location != NSNotFound && range.length > 0;
}

This causes an assert from -setVisibleRange: when you successfully scroll all available index paths offscreen, like so:
1
2

This assert seems erroneous as having no visible items is achievable normally.

ASControlNode's action is invoked twice in certain situations.

I found interesting bug when integrating AsyncDisplayKit into my project.
ASControlNode sends action second time if right after receiving first action UIActionSheet is shown. This bug occurs only if it's supernode has gesture recognizer attached and whole node hierarchy is subview of UIScrollView. Analogous setup using UIViews behaves correctly.

It's quite complicated, so just look at this test project: https://github.com/Jercik/ASDK_bug_actions. After tapping on cyan view (which is subclass of ASControlNode) UIActionSheet is shown twice, after tapping on red view (subclass of UIButton) UIActionSheet is shown once.

If UIActionSheet's showInView: is wrapped in dispatch_async problem don't exist.

//workaround:
dispatch_async(dispatch_get_main_queue(), ^{
    [actionSheet showInView:self.view];
});

Auto-completion broken for ASDisplayNode+Subclasses methods in Swift

My bridging header has the following:

#import <AsyncDisplayKit/AsyncDisplayKit.h>

However, auto-completion for several several critical ASDisplayNode+Subclasses methods — like didLoad(), calculateSizeThatFits(_:), and layout() — doesn't work. Adding the following line to my bridging header fixes this:

#import "ASDisplayNode+Subclasses.h"

I'm not sure if this is what you're expecting developers to do, though. I suspect #import <AsyncDisplayKit/AsyncDisplayKit.h> is meant to expose all public Obj-C headers for AsyncDisplayKit to Swift files.

Looking at the global header, I'm wondering if the issue is that the first two imports are for Objective-C++ headers, and that's why the category doesn't get picked up:

#import <AsyncDisplayKit/ASDisplayNode.h>
#import <AsyncDisplayKit/ASDisplayNodeExtras.h>

I don't have much experience with Obj-C++/Swift interop, so I'm not sure if the answer is as simple as dropping the category imports in the global header. Or if it needs a solution like this one. Or neither, and I'm just missing something obvious. :]

ASRangeController crashes when _delegate becomes nil.

It crashes with nil-node in block:

    for (NSIndexPath *indexPath in indexPaths) {
      ASCellNode *node = [_delegate rangeController:self nodeForIndexPath:indexPath];
      node.asyncdisplaykit_indexPath = indexPath;
      _nodes[indexPath] = node;
    }

Assert occurs with zero constrained size in block:

      dispatch_group_async(group, [ASRangeController sizingQueue], ^{
        [node measure:[_delegate rangeController:self constrainedSizeForNodeAtIndexPath:indexPath]];
        node.frame = CGRectMake(0.0f, 0.0f, node.calculatedSize.width, node.calculatedSize.height);
      });

ASTableView update methods

This is probably a blocker for me to start making use of it at work. For a feed, appending is sufficient, but for something as simple as reordering cells according to a different sort, having to trash the nodes is kind of a no-go.

Flickering and performance problems of layerBacked ASDisplayNodes

Setting "layerBacked" value to YES is recommended for performance, but I've found that in certain situations it causes ASDisplayNodes to flicker and perform additional (and unnecessary) drawing.

Here you can see flickering when presenting and dismissing view controller:
out

Only difference between two nodes is layerBacked property set to YES on right one.

I'm using long emoji string to make drawing more expensive so flickering effect is visible on simulator. On devices effect can be observed also with strings that are much less expensive to draw.

Same effect and can be observed with ASImageNode.

I can provide example project if necessary.

[ASDisplayNode] Keepalive reference for layer-backed nodes

_ASDisplayView implements a keepalive reference to its node so that it stays alive as long as the view is in the hierarchy. This is what makes the example shown here work, nothing else retains the node.

However, this mechanism is not implemented for layer-backed nodes, and I don't see an easy way to do it. As far as I know, CALayer does not have a direct equivalent to -[UIView willMoveToSuperview:]. There is the onOrderIn event but it is only sent when the layer enters a visible hierarchy. This is too late in our case.

Since converting to layer-backed nodes is said to be "as simple as" setting a boolean, I guess this limitation should be documented if a solution cannot be found.

Question about ASTextNode Highlight Overlay

Hey guys, I've recently implemented AsyncDisplayKit into a side-project i'm working on and its been amazing so far. One thing I'm confused about is the ASTextNode URL highlighting. Based on the API I thought it would have been there by default (for example ASTextNodeHighlightStyle). Is this not the case?

I did some digging and eventually found the problem was that no sublayer had as_allowsHighlightDrawing enabled on it, and with some more digging noticed that it isn't set anywhere even privately (unless I missed something).

I tried calling as_setAllowsHighlightDrawing on a ASTextNode layer itself just to see what would happen but the highlight overlay gets clipped because the text frame hasn't been adjusted.

Is this something coming in the future? Can I do anything to help bring it to light? Thanks!

Unexport _ASAsyncTransactionContainer+Private.h in podspec, project file

_ASAsyncTransactionContainer+Private.h currently resides at Details/Transactions/_ASAsyncTransactionContainer+Private.h. Since the podspec is somewhat coarse in its declarations, this private header is exported.

As far as I can tell from a quick audit, it's the only header file exported that doesn't need to be.

More info on CocoaPods' support to be found here: CocoaPods/CocoaPods#998

Might be bootcamp-able? Unless this is too trivial / not appropriate for that.

ASTableView deleting sections

Is there a similar API to the deleteSections: API in UITableView? Further, How does one interface with beginUpdates and endUpdates with Core Data?

Crash when dismissing ASTableView during layout

I have an ASTableView nested in a view controller a few levels deep in a UINavigationController stack. If the user dismisses the controller with the table while the table is performing asynchronous layout operations, the app occasionally crashes.

More specifically, crashes seem to occur in sizeNextBlock when nodeForIndexPath is called.

To circumvent this, I've implemented my data source with conditionals to validate the view's state and data.

func tableView(tableView: ASTableView!, nodeForRowAtIndexPath indexPath: NSIndexPath!) -> ASCellNode! {
    let cell = MyCell()
    if !self.isBeingDismissed() && indexPath.row < self.dataModel.count {
        cell.myObject = self.dataModel[indexPath.row]
    }
    return cell
}

Checking self.isBeingDismissed() seemed to account for most of the crashes. Adding the indexPath.row < self.dataModel.count seems to cover a few more race scenarios.

Is this a bug with ASTableView or am I using it incorrectly?

Add ASDISPLAYNODE_REQUIRES_SUPER to applicable methods.

#26 introduced an annotation to warn clients that accidentally fail to call superclass implementations of methods that require it.

Although ASDisplayKit is specifically designed to minimize its reliance on superclass method calls that are even possible for the programmer to leave out, there are a few places where they are required (particularly for methods that may be implemented by multiple levels of inheritance in classes created by the framework user).

Let's find the other relevant places to add the annotation.

API problem: Designated ASDisplayNode intiializer is the _least_ specific

ASDisplayNode.mm:

- (id)initWithViewClass:(Class)viewClass
{
  if (!(self = [self init]))
    return nil;
...
@implementation FooBarViewNode

- (instancetype)init // calls itself, resulting in crash due to stack overflow
//- (instancetype)init2 // doesn't
{
    if (self = [super initWithViewClass:[UIView class]]) {
...

Suggested solution:
Don't use a bar - (id)init as the designated initializer.

- (instancetype)initWithViewClass:(Class)viewClass layerClass:(Class)layerClass
Introduce that to ASDisplayNode+Subclasses.h. Assert that at least one of those parameters are nil, and forward - (id)initWithViewClass:(Class)viewClass, - (id)initWithLayerClass:(Class)layerClass and - (id)init to that.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.