mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
Merge branch 'master' into update-objc
Conflicts: AsyncDisplayKit/ASDisplayNode+Subclasses.h AsyncDisplayKit/ASMultiplexImageNode.h AsyncDisplayKit/ASViewController.h AsyncDisplayKit/Details/ASDataController.h
This commit is contained in:
@@ -11,6 +11,7 @@ env:
|
||||
- MODE=tests
|
||||
- MODE=examples
|
||||
- MODE=life-without-cocoapods
|
||||
- MODE=framework
|
||||
script: ./build.sh $MODE
|
||||
after_success:
|
||||
- slather
|
||||
|
||||
@@ -140,6 +140,8 @@
|
||||
205F0E211B376416007741D0 /* CGRect+ASConvenience.h in Headers */ = {isa = PBXBuildFile; fileRef = 205F0E1F1B376416007741D0 /* CGRect+ASConvenience.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
205F0E221B376416007741D0 /* CGRect+ASConvenience.m in Sources */ = {isa = PBXBuildFile; fileRef = 205F0E201B376416007741D0 /* CGRect+ASConvenience.m */; };
|
||||
242995D31B29743C00090100 /* ASBasicImageDownloaderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 242995D21B29743C00090100 /* ASBasicImageDownloaderTests.m */; };
|
||||
2767E9411BB19BD600EA9B77 /* ASViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = ACC945A81BA9E7A0005E1FB8 /* ASViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
2767E9421BB19BD600EA9B77 /* ASViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = ACC945AA1BA9E7C1005E1FB8 /* ASViewController.m */; settings = {ASSET_TAGS = (); }; };
|
||||
2911485C1A77147A005D0878 /* ASControlNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2911485B1A77147A005D0878 /* ASControlNodeTests.m */; };
|
||||
291B63FB1AA53A7A000A71B3 /* ASScrollDirection.h in Headers */ = {isa = PBXBuildFile; fileRef = 296A0A311A951715005ACEAA /* ASScrollDirection.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
292C599F1A956527007E5DD6 /* ASLayoutRangeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 292C59991A956527007E5DD6 /* ASLayoutRangeType.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -154,6 +156,7 @@
|
||||
299DA1AA1A828D2900162D41 /* ASBatchContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = 299DA1A81A828D2900162D41 /* ASBatchContext.mm */; };
|
||||
29CDC2E21AAE70D000833CA4 /* ASBasicImageDownloaderContextTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 29CDC2E11AAE70D000833CA4 /* ASBasicImageDownloaderContextTests.m */; };
|
||||
2C107F5B1BA9F54500F13DE5 /* AsyncDisplayKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
34566CB31BC1213700715E6B /* ASPhotosFrameworkImageRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m */; settings = {ASSET_TAGS = (); }; };
|
||||
34EFC75B1B701BAF00AD841F /* ASDimension.h in Headers */ = {isa = PBXBuildFile; fileRef = ACF6ED071B17843500DA7C62 /* ASDimension.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
34EFC75C1B701BD200AD841F /* ASDimension.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED081B17843500DA7C62 /* ASDimension.mm */; };
|
||||
34EFC75D1B701BE900AD841F /* ASInternalHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = ACF6ED431B17847A00DA7C62 /* ASInternalHelpers.h */; };
|
||||
@@ -372,6 +375,10 @@
|
||||
B350625D1B0111740018CF92 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 051943141A1575670030A7D0 /* Photos.framework */; };
|
||||
B350625E1B0111780018CF92 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 051943121A1575630030A7D0 /* AssetsLibrary.framework */; };
|
||||
B350625F1B0111800018CF92 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 058D09AF195D04C000B7D73C /* Foundation.framework */; };
|
||||
CC7FD9DE1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
CC7FD9DF1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m */; settings = {ASSET_TAGS = (); }; };
|
||||
CC7FD9E11BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC7FD9E01BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m */; settings = {ASSET_TAGS = (); }; };
|
||||
CC7FD9E21BB603FF005CCB2B /* ASPhotosFrameworkImageRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D785F6621A74327E00291744 /* ASScrollNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D785F6601A74327E00291744 /* ASScrollNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D785F6631A74327E00291744 /* ASScrollNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D785F6611A74327E00291744 /* ASScrollNode.m */; };
|
||||
DB7121BCD50849C498C886FB /* libPods-AsyncDisplayKitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */; };
|
||||
@@ -617,6 +624,9 @@
|
||||
ACF6ED5B1B178DC700DA7C62 /* ASStackLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASStackLayoutSpecSnapshotTests.mm; sourceTree = "<group>"; };
|
||||
B35061DA1B010EDF0018CF92 /* AsyncDisplayKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AsyncDisplayKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B35061DD1B010EDF0018CF92 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = "../AsyncDisplayKit-iOS/Info.plist"; sourceTree = "<group>"; };
|
||||
CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPhotosFrameworkImageRequest.h; sourceTree = "<group>"; };
|
||||
CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPhotosFrameworkImageRequest.m; sourceTree = "<group>"; };
|
||||
CC7FD9E01BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPhotosFrameworkImageRequestTests.m; sourceTree = "<group>"; };
|
||||
D3779BCFF841AD3EB56537ED /* Pods-AsyncDisplayKitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AsyncDisplayKitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
D785F6601A74327E00291744 /* ASScrollNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASScrollNode.h; sourceTree = "<group>"; };
|
||||
D785F6611A74327E00291744 /* ASScrollNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASScrollNode.m; sourceTree = "<group>"; };
|
||||
@@ -799,6 +809,7 @@
|
||||
ACF6ED581B178DC700DA7C62 /* ASLayoutSpecSnapshotTestsHelper.m */,
|
||||
242995D21B29743C00090100 /* ASBasicImageDownloaderTests.m */,
|
||||
29CDC2E11AAE70D000833CA4 /* ASBasicImageDownloaderContextTests.m */,
|
||||
CC7FD9E01BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m */,
|
||||
296A0A341A951ABF005ACEAA /* ASBatchFetchingTests.m */,
|
||||
9F06E5CC1B4CAF4200F015D8 /* ASCollectionViewTests.m */,
|
||||
2911485B1A77147A005D0878 /* ASControlNodeTests.m */,
|
||||
@@ -834,6 +845,8 @@
|
||||
058D09E1195D050800B7D73C /* Details */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */,
|
||||
CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m */,
|
||||
058D09E2195D050800B7D73C /* _ASDisplayLayer.h */,
|
||||
058D09E3195D050800B7D73C /* _ASDisplayLayer.mm */,
|
||||
058D09E4195D050800B7D73C /* _ASDisplayView.h */,
|
||||
@@ -1104,6 +1117,7 @@
|
||||
9C8221951BA237B80037F19A /* ASStackBaselinePositionedLayout.h in Headers */,
|
||||
9C49C36F1B853957000B0DD5 /* ASStackLayoutable.h in Headers */,
|
||||
AC21EC101B3D0BF600C8B19A /* ASStackLayoutDefines.h in Headers */,
|
||||
CC7FD9DE1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h in Headers */,
|
||||
ACF6ED2F1B17843500DA7C62 /* ASStackLayoutSpec.h in Headers */,
|
||||
ACF6ED4E1B17847A00DA7C62 /* ASStackLayoutSpecUtilities.h in Headers */,
|
||||
ACF6ED4F1B17847A00DA7C62 /* ASStackPositionedLayout.h in Headers */,
|
||||
@@ -1206,7 +1220,9 @@
|
||||
9C8221961BA237B80037F19A /* ASStackBaselinePositionedLayout.h in Headers */,
|
||||
9C49C3701B853961000B0DD5 /* ASStackLayoutable.h in Headers */,
|
||||
34EFC7701B701CFA00AD841F /* ASStackLayoutDefines.h in Headers */,
|
||||
CC7FD9E21BB603FF005CCB2B /* ASPhotosFrameworkImageRequest.h in Headers */,
|
||||
34EFC7711B701CFF00AD841F /* ASStackLayoutSpec.h in Headers */,
|
||||
2767E9411BB19BD600EA9B77 /* ASViewController.h in Headers */,
|
||||
044284FE1BAA387800D16268 /* ASStackLayoutSpecUtilities.h in Headers */,
|
||||
34EFC7751B701D2400AD841F /* ASStackPositionedLayout.h in Headers */,
|
||||
34EFC7771B701D2D00AD841F /* ASStackUnpositionedLayout.h in Headers */,
|
||||
@@ -1490,6 +1506,7 @@
|
||||
058D0A21195D050800B7D73C /* NSMutableAttributedString+TextKitAdditions.m in Sources */,
|
||||
205F0E101B371875007741D0 /* UICollectionViewLayout+ASConvenience.m in Sources */,
|
||||
058D0A25195D050800B7D73C /* UIView+ASConvenience.m in Sources */,
|
||||
CC7FD9DF1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -1511,6 +1528,7 @@
|
||||
056D21551ABCEF50001107EF /* ASImageNodeSnapshotTests.m in Sources */,
|
||||
ACF6ED5E1B178DC700DA7C62 /* ASInsetLayoutSpecSnapshotTests.mm in Sources */,
|
||||
ACF6ED601B178DC700DA7C62 /* ASLayoutSpecSnapshotTestsHelper.m in Sources */,
|
||||
CC7FD9E11BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m in Sources */,
|
||||
052EE0661A159FEF002C6279 /* ASMultiplexImageNodeTests.m in Sources */,
|
||||
058D0A3C195D057000B7D73C /* ASMutableAttributedStringBuilderTests.m in Sources */,
|
||||
ACF6ED611B178DC700DA7C62 /* ASOverlayLayoutSpecSnapshotTests.mm in Sources */,
|
||||
@@ -1534,6 +1552,7 @@
|
||||
B35062401B010EFD0018CF92 /* _ASAsyncTransactionContainer.m in Sources */,
|
||||
B35062421B010EFD0018CF92 /* _ASAsyncTransactionGroup.m in Sources */,
|
||||
B350624A1B010EFD0018CF92 /* _ASCoreAnimationExtras.mm in Sources */,
|
||||
2767E9421BB19BD600EA9B77 /* ASViewController.m in Sources */,
|
||||
B35062101B010EFD0018CF92 /* _ASDisplayLayer.mm in Sources */,
|
||||
B35062121B010EFD0018CF92 /* _ASDisplayView.mm in Sources */,
|
||||
B350624C1B010EFD0018CF92 /* _ASPendingState.m in Sources */,
|
||||
@@ -1594,6 +1613,7 @@
|
||||
B35062351B010EFD0018CF92 /* ASTextNodeTextKitHelpers.mm in Sources */,
|
||||
B35062381B010EFD0018CF92 /* ASTextNodeWordKerner.m in Sources */,
|
||||
509E68661B3AEDD7009B9150 /* CGRect+ASConvenience.m in Sources */,
|
||||
34566CB31BC1213700715E6B /* ASPhotosFrameworkImageRequest.m in Sources */,
|
||||
B350623B1B010EFD0018CF92 /* NSMutableAttributedString+TextKitAdditions.m in Sources */,
|
||||
044284FD1BAA365100D16268 /* UICollectionViewLayout+ASConvenience.m in Sources */,
|
||||
B35062441B010EFD0018CF92 /* UIView+ASConvenience.m in Sources */,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0630"
|
||||
LastUpgradeVersion = "0700"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
@@ -14,7 +14,7 @@
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "2C5B669C1B3A796F005926A7"
|
||||
BlueprintIdentifier = "B35061D91B010EDF0018CF92"
|
||||
BuildableName = "AsyncDisplayKit.framework"
|
||||
BlueprintName = "AsyncDisplayKit-iOS"
|
||||
ReferencedContainer = "container:AsyncDisplayKit.xcodeproj">
|
||||
@@ -23,26 +23,29 @@
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "2C5B669C1B3A796F005926A7"
|
||||
BlueprintIdentifier = "B35061D91B010EDF0018CF92"
|
||||
BuildableName = "AsyncDisplayKit.framework"
|
||||
BlueprintName = "AsyncDisplayKit-iOS"
|
||||
ReferencedContainer = "container:AsyncDisplayKit.xcodeproj">
|
||||
@@ -52,15 +55,15 @@
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "2C5B669C1B3A796F005926A7"
|
||||
BlueprintIdentifier = "B35061D91B010EDF0018CF92"
|
||||
BuildableName = "AsyncDisplayKit.framework"
|
||||
BlueprintName = "AsyncDisplayKit-iOS"
|
||||
ReferencedContainer = "container:AsyncDisplayKit.xcodeproj">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0600"
|
||||
LastUpgradeVersion = "0700"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
@@ -37,10 +37,10 @@
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
@@ -62,15 +62,18 @@
|
||||
ReferencedContainer = "container:AsyncDisplayKit.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
@@ -85,10 +88,10 @@
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
|
||||
@@ -15,6 +15,29 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
@interface ASCellNode : ASDisplayNode
|
||||
|
||||
/**
|
||||
* @abstract When enabled, ensures that the cell is completely displayed before allowed onscreen.
|
||||
*
|
||||
* @default NO
|
||||
* @discussion Normally, ASCellNodes are preloaded and have finished display before they are onscreen.
|
||||
* However, if the Table or Collection's rangeTuningParameters are set to small values (or 0),
|
||||
* or if the user is scrolling rapidly on a slow device, it is possible for a cell's display to
|
||||
* be incomplete when it becomes visible.
|
||||
*
|
||||
* In this case, normally placeholder states are shown and scrolling continues uninterrupted.
|
||||
* The finished, drawn content is then shown as soon as it is ready.
|
||||
*
|
||||
* With this property set to YES, the main thread will be blocked until display is complete for
|
||||
* the cell. This is more similar to UIKit, and in fact makes AsyncDisplayKit scrolling visually
|
||||
* indistinguishible from UIKit's, except being faster.
|
||||
*
|
||||
* Using this option does not eliminate all of the performance advantages of AsyncDisplayKit.
|
||||
* Normally, a cell has been preloading and is almost done when it reaches the screen, so the
|
||||
* blocking time is very short. If the rangeTuningParameters are set to 0, still this option
|
||||
* outperforms UIKit: while the main thread is waiting, subnode display executes concurrently.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL neverShowPlaceholders;
|
||||
|
||||
/*
|
||||
* ASTableView uses these properties when configuring UITableViewCells that host ASCellNodes.
|
||||
*/
|
||||
|
||||
@@ -213,6 +213,15 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
- (ASCellNode *)nodeForItemAtIndexPath:(NSIndexPath *)indexPath;
|
||||
|
||||
/**
|
||||
* Similar to -indexPathForCell:.
|
||||
*
|
||||
* @param cellNode a cellNode part of the table view
|
||||
*
|
||||
* @returns an indexPath for this cellNode
|
||||
*/
|
||||
- (NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode;
|
||||
|
||||
/**
|
||||
* Similar to -visibleCells.
|
||||
*
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
#import "UICollectionViewLayout+ASConvenience.h"
|
||||
#import "ASInternalHelpers.h"
|
||||
|
||||
// FIXME: Temporary nonsense import until method names are finalized and exposed
|
||||
#import "ASDisplayNode+Subclasses.h"
|
||||
|
||||
const static NSUInteger kASCollectionViewAnimationNone = UITableViewRowAnimationNone;
|
||||
|
||||
|
||||
@@ -234,7 +237,8 @@ static BOOL _isInterceptedSelector(SEL sel)
|
||||
|
||||
- (void)setDataSource:(id<UICollectionViewDataSource>)dataSource
|
||||
{
|
||||
ASDisplayNodeAssert(NO, @"ASCollectionView uses asyncDataSource, not UICollectionView's dataSource property.");
|
||||
// UIKit can internally generate a call to this method upon changing the asyncDataSource; only assert for non-nil.
|
||||
ASDisplayNodeAssert(dataSource == nil, @"ASCollectionView uses asyncDataSource, not UICollectionView's dataSource property.");
|
||||
}
|
||||
|
||||
- (void)setDelegate:(id<UICollectionViewDelegate>)delegate
|
||||
@@ -314,6 +318,16 @@ static BOOL _isInterceptedSelector(SEL sel)
|
||||
return [[_dataController nodeAtIndexPath:indexPath] calculatedSize];
|
||||
}
|
||||
|
||||
- (ASCellNode *)nodeForItemAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
return [_dataController nodeAtIndexPath:indexPath];
|
||||
}
|
||||
|
||||
- (NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode
|
||||
{
|
||||
return [_dataController indexPathForNode:cellNode];
|
||||
}
|
||||
|
||||
- (NSArray *)visibleNodes
|
||||
{
|
||||
NSArray *indexPaths = [self indexPathsForVisibleItems];
|
||||
@@ -391,11 +405,6 @@ static BOOL _isInterceptedSelector(SEL sel)
|
||||
[_dataController moveRowAtIndexPath:indexPath toIndexPath:newIndexPath withAnimationOptions:kASCollectionViewAnimationNone];
|
||||
}
|
||||
|
||||
- (ASCellNode *)nodeForItemAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
return [_dataController nodeAtIndexPath:indexPath];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Intercepted selectors.
|
||||
|
||||
@@ -489,6 +498,11 @@ static BOOL _isInterceptedSelector(SEL sel)
|
||||
if ([_asyncDelegate respondsToSelector:@selector(collectionView:willDisplayNodeForItemAtIndexPath:)]) {
|
||||
[_asyncDelegate collectionView:self willDisplayNodeForItemAtIndexPath:indexPath];
|
||||
}
|
||||
|
||||
ASCellNode *cellNode = [self nodeForItemAtIndexPath:indexPath];
|
||||
if (cellNode.neverShowPlaceholders) {
|
||||
[cellNode recursivelyEnsureDisplay];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
|
||||
|
||||
@@ -431,9 +431,41 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
// This method has proven helpful in a few rare scenarios, similar to a category extension on UIView,
|
||||
// but it's considered private API for now and its use should not be encouraged.
|
||||
- (nullable ASDisplayNode *)_supernodeWithClass:(Class)supernodeClass;
|
||||
|
||||
// The two methods below will eventually be exposed, but their names are subject to change.
|
||||
/**
|
||||
* @abstract Ensure that all rendering is complete for this node and its descendents.
|
||||
*
|
||||
* @discussion Calling this method on the main thread after a node is added to the view heirarchy will ensure that
|
||||
* placeholder states are never visible to the user. It is used by ASTableView, ASCollectionView, and ASViewController
|
||||
* to implement their respective ".neverShowPlaceholders" option.
|
||||
*
|
||||
* If all nodes have layer.contents set and/or their layer does not have -needsDisplay set, the method will return immediately.
|
||||
*
|
||||
* This method is capable of handling a mixed set of nodes, with some not having started display, some in progress on an
|
||||
* asynchronous display operation, and some already finished.
|
||||
*
|
||||
* In order to guarantee against deadlocks, this method should only be called on the main thread.
|
||||
* It may block on the private queue, [_ASDisplayLayer displayQueue]
|
||||
*/
|
||||
- (void)recursivelyEnsureDisplay;
|
||||
|
||||
/**
|
||||
* @abstract Allows a node to bypass all ensureDisplay passes. Defaults to NO.
|
||||
*
|
||||
* @discussion Nodes that are expensive to draw and expected to have placeholder even with
|
||||
* .neverShowPlaceholders enabled should set this to YES.
|
||||
*
|
||||
* ASImageNode uses the default of NO, as it is often used for UI images that are expected to synchronize with ensureDisplay.
|
||||
*
|
||||
* ASNetworkImageNode and ASMultiplexImageNode set this to YES, because they load data from a database or server,
|
||||
* and are expected to support a placeholder state given that display is often blocked on slow data fetching.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL shouldBypassEnsureDisplay;
|
||||
|
||||
@end
|
||||
|
||||
#define ASDisplayNodeAssertThreadAffinity(viewNode) ASDisplayNodeAssert(!viewNode || ASDisplayNodeThreadIsMain() || !(viewNode).nodeLoaded, @"Incorrect display node thread affinity")
|
||||
#define ASDisplayNodeCAssertThreadAffinity(viewNode) ASDisplayNodeCAssert(!viewNode || ASDisplayNodeThreadIsMain() || !(viewNode).nodeLoaded, @"Incorrect display node thread affinity")
|
||||
#define ASDisplayNodeAssertThreadAffinity(viewNode) ASDisplayNodeAssert(!viewNode || ASDisplayNodeThreadIsMain() || !(viewNode).nodeLoaded, @"Incorrect display node thread affinity - this method should not be called off the main thread after the ASDisplayNode's view or layer have been created")
|
||||
#define ASDisplayNodeCAssertThreadAffinity(viewNode) ASDisplayNodeCAssert(!viewNode || ASDisplayNodeThreadIsMain() || !(viewNode).nodeLoaded, @"Incorrect display node thread affinity - this method should not be called off the main thread after the ASDisplayNode's view or layer have been created")
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import "_ASAsyncTransaction.h"
|
||||
#import "_ASAsyncTransactionContainer+Private.h"
|
||||
#import "_ASPendingState.h"
|
||||
#import "_ASDisplayView.h"
|
||||
#import "_ASScopeTimer.h"
|
||||
@@ -671,25 +672,20 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
||||
// This is the root node. Trigger a full measurement pass on *current* thread. Old constrained size is re-used.
|
||||
[self measureWithSizeRange:oldConstrainedSize];
|
||||
|
||||
CGSize oldSize = self.bounds.size;
|
||||
CGRect oldBounds = self.bounds;
|
||||
CGSize oldSize = oldBounds.size;
|
||||
CGSize newSize = _layout.size;
|
||||
|
||||
if (! CGSizeEqualToSize(oldSize, newSize)) {
|
||||
CGRect bounds = self.bounds;
|
||||
bounds.size = newSize;
|
||||
self.bounds = bounds;
|
||||
self.bounds = (CGRect){ oldBounds.origin, newSize };
|
||||
|
||||
// Frame's origin must be preserved. Since it is computed from bounds size, anchorPoint
|
||||
// and position (see frame setter in ASDisplayNode+UIViewBridge), position needs to be adjusted.
|
||||
BOOL useLayer = (_layer && ASDisplayNodeThreadIsMain());
|
||||
CGPoint anchorPoint = (useLayer ? _layer.anchorPoint : self.anchorPoint);
|
||||
CGPoint oldPosition = (useLayer ? _layer.position : self.position);
|
||||
|
||||
CGPoint anchorPoint = self.anchorPoint;
|
||||
CGPoint oldPosition = self.position;
|
||||
CGFloat xDelta = (newSize.width - oldSize.width) * anchorPoint.x;
|
||||
CGFloat yDelta = (newSize.height - oldSize.height) * anchorPoint.y;
|
||||
CGPoint newPosition = CGPointMake(oldPosition.x + xDelta, oldPosition.y + yDelta);
|
||||
|
||||
useLayer ? _layer.position = newPosition : self.position = newPosition;
|
||||
self.position = CGPointMake(oldPosition.x + xDelta, oldPosition.y + yDelta);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1415,6 +1411,68 @@ static NSInteger incrementIfFound(NSInteger i) {
|
||||
[_placeholderLayer removeFromSuperlayer];
|
||||
}
|
||||
|
||||
void recursivelyEnsureDisplayForLayer(CALayer *layer)
|
||||
{
|
||||
// This recursion must handle layers in various states:
|
||||
// 1. Just added to hierarchy, CA hasn't yet called -display
|
||||
// 2. Previously in a hierarchy (such as a working window owned by an Intelligent Preloading class, like ASTableView / ASCollectionView / ASViewController)
|
||||
// 3. Has no content to display at all
|
||||
// Specifically for case 1), we need to explicitly trigger a -display call now.
|
||||
// Otherwise, there is no opportunity to block the main thread after CoreAnimation's transaction commit
|
||||
// (even a runloop observer at a late call order will not stop the next frame from compositing, showing placeholders).
|
||||
|
||||
ASDisplayNode *node = [layer asyncdisplaykit_node];
|
||||
if (!layer.contents && [node _implementsDisplay]) {
|
||||
// For layers that do get displayed here, this immediately kicks off the work on the concurrent -[_ASDisplayLayer displayQueue].
|
||||
// At the same time, it creates an associated _ASAsyncTransaction, which we can use to block on display completion. See ASDisplayNode+AsyncDisplay.mm.
|
||||
[layer displayIfNeeded];
|
||||
}
|
||||
|
||||
// Kick off the recursion first, so that all necessary display calls are sent and the displayQueue is full of parallelizable work.
|
||||
for (CALayer *sublayer in layer.sublayers) {
|
||||
recursivelyEnsureDisplayForLayer(sublayer);
|
||||
}
|
||||
|
||||
// As the recursion unwinds, verify each transaction is complete and block if it is not.
|
||||
// While blocking on one transaction, others may be completing concurrently, so it doesn't matter which blocks first.
|
||||
BOOL waitUntilComplete = (!node.shouldBypassEnsureDisplay);
|
||||
if (waitUntilComplete) {
|
||||
for (_ASAsyncTransaction *transaction in [layer.asyncdisplaykit_asyncLayerTransactions copy]) {
|
||||
// Even if none of the layers have had a chance to start display earlier, they will still be allowed to saturate a multicore CPU while blocking main.
|
||||
// This significantly reduces time on the main thread relative to UIKit.
|
||||
[transaction waitUntilComplete];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)recursivelyEnsureDisplay
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
ASDisplayNodeAssert(self.isNodeLoaded, @"Node must have layer or view loaded to use -recursivelyEnsureDisplay");
|
||||
ASDisplayNodeAssert(self.inHierarchy && (self.isLayerBacked || self.view.window != nil), @"Node must be in a hierarchy to use -recursivelyEnsureDisplay");
|
||||
|
||||
CALayer *layer = self.layer;
|
||||
// -layoutIfNeeded is recursive, and even walks up to superlayers to check if they need layout,
|
||||
// so we should call it outside of starting the recursion below. If our own layer is not marked
|
||||
// as dirty, we can assume layout has run on this subtree before.
|
||||
if ([layer needsLayout]) {
|
||||
[layer layoutIfNeeded];
|
||||
}
|
||||
recursivelyEnsureDisplayForLayer(layer);
|
||||
}
|
||||
|
||||
- (void)setShouldBypassEnsureDisplay:(BOOL)shouldBypassEnsureDisplay
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
_flags.shouldBypassEnsureDisplay = shouldBypassEnsureDisplay;
|
||||
}
|
||||
|
||||
- (BOOL)shouldBypassEnsureDisplay
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
return _flags.shouldBypassEnsureDisplay;
|
||||
}
|
||||
|
||||
#pragma mark - For Subclasses
|
||||
|
||||
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
|
||||
@@ -1484,6 +1542,7 @@ static NSInteger incrementIfFound(NSInteger i) {
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
return _preferredFrameSize;
|
||||
}
|
||||
|
||||
- (UIImage *)placeholderImage
|
||||
{
|
||||
return nil;
|
||||
|
||||
@@ -12,7 +12,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol ASEditableTextNodeDelegate;
|
||||
|
||||
/// @abstract ASEditableTextNode implements a node that supports text editing.
|
||||
/**
|
||||
@abstract Implements a node that supports text editing.
|
||||
@discussion Does not support layer backing.
|
||||
*/
|
||||
@interface ASEditableTextNode : ASDisplayNode
|
||||
|
||||
// @abstract The text node's delegate, which must conform to the <ASEditableTextNodeDelegate> protocol.
|
||||
|
||||
@@ -143,6 +143,7 @@
|
||||
_textKitComponents.textView.accessibilityHint = _placeholderTextKitComponents.textStorage.string;
|
||||
configureTextView(_textKitComponents.textView);
|
||||
[self.view addSubview:_textKitComponents.textView];
|
||||
[self _updateDisplayingPlaceholder];
|
||||
}
|
||||
|
||||
- (CGSize)calculateSizeThatFits:(CGSize)constrainedSize
|
||||
@@ -188,6 +189,12 @@
|
||||
_placeholderTextKitComponents.textView.opaque = opaque;
|
||||
}
|
||||
|
||||
- (void)setLayerBacked:(BOOL)layerBacked
|
||||
{
|
||||
ASDisplayNodeAssert(!layerBacked, @"Cannot set layerBacked to YES on ASEditableTextNode – instances must be view-backed in order to ensure touch events can be passed to the internal UITextView during editing.");
|
||||
[super setLayerBacked:layerBacked];
|
||||
}
|
||||
|
||||
#pragma mark - Configuration
|
||||
@synthesize delegate = _delegate;
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#import <AsyncDisplayKit/ASImageNode.h>
|
||||
#import <AsyncDisplayKit/ASImageProtocols.h>
|
||||
|
||||
#import <Photos/Photos.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol ASMultiplexImageNodeDelegate;
|
||||
@@ -100,6 +102,13 @@ typedef NS_ENUM(NSUInteger, ASMultiplexImageNodeErrorCode) {
|
||||
*/
|
||||
@property (nullable, nonatomic, readonly) ASImageIdentifier displayedImageIdentifier;
|
||||
|
||||
/**
|
||||
* @abstract The image manager that this image node should use when requesting images from the Photos framework. If this is `nil` (the default), then `PHImageManager.defaultManager` is used.
|
||||
|
||||
* @see `+[NSURL URLWithAssetLocalIdentifier:targetSize:contentMode:options:]` below.
|
||||
*/
|
||||
@property (nonatomic, strong) PHImageManager *imageManager;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -197,13 +206,34 @@ didFinishDownloadingImageWithIdentifier:(ASImageIdentifier)imageIdentifier
|
||||
* @abstract An image URL for the specified identifier.
|
||||
* @param imageNode The sender.
|
||||
* @param imageIdentifier The identifier for the image that will be downloaded.
|
||||
* @discussion Supported URLs include assets-library, Photo framework URLs (ph://), HTTP, HTTPS, and FTP URLs. If the
|
||||
* image is already available to the data source, it should be provided via <[ASMultiplexImageNodeDataSource
|
||||
* @discussion Supported URLs include HTTP, HTTPS, AssetsLibrary, and FTP URLs as well as Photos framework URLs (see note).
|
||||
*
|
||||
* If the image is already available to the data source, it should be provided via <[ASMultiplexImageNodeDataSource
|
||||
* multiplexImageNode:imageForImageIdentifier:]> instead.
|
||||
* @returns An NSURL for the image identified by `imageIdentifier`, or nil if none is available.
|
||||
* @return An NSURL for the image identified by `imageIdentifier`, or nil if none is available.
|
||||
* @see `+[NSURL URLWithAssetLocalIdentifier:targetSize:contentMode:options:]` below.
|
||||
*/
|
||||
- (nullable NSURL *)multiplexImageNode:(ASMultiplexImageNode *)imageNode URLForImageIdentifier:(ASImageIdentifier)imageIdentifier;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
#pragma mark -
|
||||
|
||||
@interface NSURL (ASPhotosFrameworkURLs)
|
||||
|
||||
/**
|
||||
* @abstract Create an NSURL that specifies an image from the Photos framework.
|
||||
*
|
||||
* @discussion When implementing `-multiplexImageNode:URLForImageIdentifier:`, you can return a URL
|
||||
* created by this method and the image node will attempt to load the image from the Photos framework.
|
||||
* @note The `synchronous` flag in `options` is ignored.
|
||||
* @note The `Opportunistic` delivery mode is not supported and will be treated as `HighQualityFormat`.
|
||||
*/
|
||||
+ (NSURL *)URLWithAssetLocalIdentifier:(NSString *)assetLocalIdentifier
|
||||
targetSize:(CGSize)targetSize
|
||||
contentMode:(PHImageContentMode)contentMode
|
||||
options:(PHImageRequestOptions *)options;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -18,6 +18,7 @@
|
||||
#import "ASBaseDefines.h"
|
||||
#import "ASDisplayNode+Subclasses.h"
|
||||
#import "ASLog.h"
|
||||
#import "ASPhotosFrameworkImageRequest.h"
|
||||
|
||||
#if !AS_IOS8_SDK_OR_LATER
|
||||
#error ASMultiplexImageNode can be used on iOS 7, but must be linked against the iOS 8 SDK.
|
||||
@@ -26,8 +27,6 @@
|
||||
NSString *const ASMultiplexImageNodeErrorDomain = @"ASMultiplexImageNodeErrorDomain";
|
||||
|
||||
static NSString *const kAssetsLibraryURLScheme = @"assets-library";
|
||||
static NSString *const kPHAssetURLScheme = @"ph";
|
||||
static NSString *const kPHAssetURLPrefix = @"ph://";
|
||||
|
||||
/**
|
||||
@abstract Signature for the block to be performed after an image has loaded.
|
||||
@@ -120,14 +119,14 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
||||
- (void)_loadALAssetWithIdentifier:(id)imageIdentifier URL:(NSURL *)assetURL completion:(void (^)(UIImage *image, NSError *error))completionBlock;
|
||||
|
||||
/**
|
||||
@abstract Loads the image corresponding to the given assetURL from the Photos framework.
|
||||
@abstract Loads the image corresponding to the given image request from the Photos framework.
|
||||
@param imageIdentifier The identifier for the image to be loaded. May not be nil.
|
||||
@param assetURL The photos framework URL (e.g., "ph://identifier") of the image to load, from PHAsset. May not be nil.
|
||||
@param request The photos image request to load. May not be nil.
|
||||
@param completionBlock The block to be performed when the image has been loaded, if possible. May not be nil.
|
||||
@param image The image that was loaded. May be nil if no image could be downloaded.
|
||||
@param error An error describing why the load failed, if it failed; nil otherwise.
|
||||
*/
|
||||
- (void)_loadPHAssetWithIdentifier:(id)imageIdentifier URL:(NSURL *)assetURL completion:(void (^)(UIImage *image, NSError *error))completionBlock;
|
||||
- (void)_loadPHAssetWithRequest:(ASPhotosFrameworkImageRequest *)request identifier:(id)imageIdentifier completion:(void (^)(UIImage *image, NSError *error))completionBlock;
|
||||
|
||||
/**
|
||||
@abstract Downloads the image corresponding to the given imageIdentifier from the given URL.
|
||||
@@ -158,6 +157,7 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
||||
|
||||
_cache = cache;
|
||||
_downloader = downloader;
|
||||
self.shouldBypassEnsureDisplay = YES;
|
||||
|
||||
return self;
|
||||
}
|
||||
@@ -456,8 +456,8 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
||||
}];
|
||||
}
|
||||
// Likewise, if it's a iOS 8 Photo asset, we need to fetch it accordingly.
|
||||
else if (AS_AT_LEAST_IOS8 && [[nextImageURL scheme] isEqualToString:kPHAssetURLScheme]) {
|
||||
[self _loadPHAssetWithIdentifier:nextImageIdentifier URL:nextImageURL completion:^(UIImage *image, NSError *error) {
|
||||
else if (ASPhotosFrameworkImageRequest *request = [ASPhotosFrameworkImageRequest requestWithURL:nextImageURL]) {
|
||||
[self _loadPHAssetWithRequest:request identifier:nextImageIdentifier completion:^(UIImage *image, NSError *error) {
|
||||
ASMultiplexImageNodeCLogDebug(@"[%p] Acquired next image (%@) from Photos Framework", weakSelf, nextImageIdentifier);
|
||||
finishedLoadingBlock(image, nextImageIdentifier, error);
|
||||
}];
|
||||
@@ -511,38 +511,48 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)_loadPHAssetWithIdentifier:(id)imageIdentifier URL:(NSURL *)assetURL completion:(void (^)(UIImage *image, NSError *error))completionBlock
|
||||
- (void)_loadPHAssetWithRequest:(ASPhotosFrameworkImageRequest *)request identifier:(id)imageIdentifier completion:(void (^)(UIImage *image, NSError *error))completionBlock
|
||||
{
|
||||
ASDisplayNodeAssert(AS_AT_LEAST_IOS8, @"PhotosKit is unavailable on iOS 7.");
|
||||
ASDisplayNodeAssertNotNil(imageIdentifier, @"imageIdentifier is required");
|
||||
ASDisplayNodeAssertNotNil(assetURL, @"assetURL is required");
|
||||
ASDisplayNodeAssertNotNil(request, @"request is required");
|
||||
ASDisplayNodeAssertNotNil(completionBlock, @"completionBlock is required");
|
||||
|
||||
// Get the PHAsset itself.
|
||||
ASDisplayNodeAssertTrue([[assetURL absoluteString] hasPrefix:kPHAssetURLPrefix]);
|
||||
NSString *assetIdentifier = [[assetURL absoluteString] substringFromIndex:[kPHAssetURLPrefix length]];
|
||||
PHFetchResult *assetFetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[assetIdentifier] options:nil];
|
||||
if ([assetFetchResult count] == 0) {
|
||||
// Error.
|
||||
completionBlock(nil, nil);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the best image we can.
|
||||
PHAsset *imageAsset = [assetFetchResult firstObject];
|
||||
|
||||
PHImageRequestOptions *requestOptions = [[PHImageRequestOptions alloc] init];
|
||||
requestOptions.version = PHImageRequestOptionsVersionCurrent;
|
||||
requestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
|
||||
requestOptions.resizeMode = PHImageRequestOptionsResizeModeNone;
|
||||
|
||||
[[PHImageManager defaultManager] requestImageForAsset:imageAsset
|
||||
targetSize:CGSizeMake(2048.0, 2048.0) // Ideally we would use PHImageManagerMaximumSize and kill the options, but we get back nil when requesting images of video assets. rdar://18447788
|
||||
contentMode:PHImageContentModeDefault
|
||||
options:requestOptions
|
||||
resultHandler:^(UIImage *image, NSDictionary *info) {
|
||||
completionBlock(image, info[PHImageErrorKey]);
|
||||
}];
|
||||
|
||||
// This is sometimes called on main but there's no reason to stay there
|
||||
dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{
|
||||
// Get the PHAsset itself.
|
||||
PHFetchResult *assetFetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[request.assetIdentifier] options:nil];
|
||||
if ([assetFetchResult count] == 0) {
|
||||
// Error.
|
||||
completionBlock(nil, nil);
|
||||
return;
|
||||
}
|
||||
|
||||
PHAsset *imageAsset = [assetFetchResult firstObject];
|
||||
PHImageRequestOptions *options = [request.options copy];
|
||||
|
||||
// We don't support opportunistic delivery – one request, one image.
|
||||
if (options.deliveryMode == PHImageRequestOptionsDeliveryModeOpportunistic) {
|
||||
options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
|
||||
}
|
||||
|
||||
if (options.deliveryMode == PHImageRequestOptionsDeliveryModeHighQualityFormat) {
|
||||
// Without this flag the result will be delivered on the main queue, which is pointless
|
||||
// But synchronous -> HighQualityFormat so we only use it if high quality format is specified
|
||||
options.synchronous = YES;
|
||||
}
|
||||
|
||||
PHImageManager *imageManager = self.imageManager ?: PHImageManager.defaultManager;
|
||||
[imageManager requestImageForAsset:imageAsset targetSize:request.targetSize contentMode:request.contentMode options:options resultHandler:^(UIImage *image, NSDictionary *info) {
|
||||
if (NSThread.isMainThread) {
|
||||
dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{
|
||||
completionBlock(image, info[PHImageErrorKey]);
|
||||
});
|
||||
} else {
|
||||
completionBlock(image, info[PHImageErrorKey]);
|
||||
}
|
||||
}];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)_fetchImageWithIdentifierFromCache:(id)imageIdentifier URL:(NSURL *)imageURL completion:(void (^)(UIImage *image))completionBlock
|
||||
@@ -642,3 +652,16 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSURL (ASPhotosFrameworkURLs)
|
||||
|
||||
+ (NSURL *)URLWithAssetLocalIdentifier:(NSString *)assetLocalIdentifier targetSize:(CGSize)targetSize contentMode:(PHImageContentMode)contentMode options:(PHImageRequestOptions *)options
|
||||
{
|
||||
ASPhotosFrameworkImageRequest *request = [[ASPhotosFrameworkImageRequest alloc] initWithAssetIdentifier:assetLocalIdentifier];
|
||||
request.options = options;
|
||||
request.contentMode = contentMode;
|
||||
request.targetSize = targetSize;
|
||||
return request.url;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -44,6 +44,7 @@
|
||||
_cache = cache;
|
||||
_downloader = downloader;
|
||||
_shouldCacheImage = YES;
|
||||
self.shouldBypassEnsureDisplay = YES;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -28,8 +28,28 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
@interface ASTableView : UITableView
|
||||
|
||||
@property (nonatomic, weak) id<ASTableViewDataSource> asyncDataSource;
|
||||
@property (nonatomic, weak) id<ASTableViewDelegate> asyncDelegate; // must not be nil
|
||||
@property (nonatomic, weak) id<ASTableViewDataSource> asyncDataSource;
|
||||
|
||||
/**
|
||||
* Initializer.
|
||||
*
|
||||
* @param frame A rectangle specifying the initial location and size of the table view in its superview’s coordinates.
|
||||
* The frame of the table view changes as table cells are added and deleted.
|
||||
*
|
||||
* @param style A constant that specifies the style of the table view. See UITableViewStyle for descriptions of valid constants.
|
||||
*
|
||||
* @param asyncDataFetchingEnabled This option is reserved for future use, and currently a no-op.
|
||||
*
|
||||
* @discussion If asyncDataFetching is enabled, the `ASTableView` will fetch data through `tableView:numberOfRowsInSection:` and
|
||||
* `tableView:nodeForRowAtIndexPath:` in async mode from background thread. Otherwise, the methods will be invoked synchronically
|
||||
* from calling thread.
|
||||
* Enabling asyncDataFetching could avoid blocking main thread for `ASCellNode` allocation, which is frequently reported issue for
|
||||
* large scale data. On another hand, the application code need take the responsibility to avoid data inconsistence. Specifically,
|
||||
* we will lock the data source through `tableViewLockDataSource`, and unlock it by `tableViewUnlockDataSource` after the data fetching.
|
||||
* The application should not update the data source while the data source is locked, to keep data consistence.
|
||||
*/
|
||||
- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style asyncDataFetching:(BOOL)asyncDataFetchingEnabled;
|
||||
|
||||
/**
|
||||
* Tuning parameters for a range.
|
||||
@@ -51,26 +71,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType;
|
||||
|
||||
/**
|
||||
* Initializer.
|
||||
*
|
||||
* @param frame A rectangle specifying the initial location and size of the table view in its superview’s coordinates.
|
||||
* The frame of the table view changes as table cells are added and deleted.
|
||||
*
|
||||
* @param style A constant that specifies the style of the table view. See UITableViewStyle for descriptions of valid constants.
|
||||
*
|
||||
* @param asyncDataFetchingEnabled Enable the data fetching in async mode.
|
||||
*
|
||||
* @discussion If asyncDataFetching is enabled, the `ASTableView` will fetch data through `tableView:numberOfRowsInSection:` and
|
||||
* `tableView:nodeForRowAtIndexPath:` in async mode from background thread. Otherwise, the methods will be invoked synchronically
|
||||
* from calling thread.
|
||||
* Enabling asyncDataFetching could avoid blocking main thread for `ASCellNode` allocation, which is frequently reported issue for
|
||||
* large scale data. On another hand, the application code need take the responsibility to avoid data inconsistence. Specifically,
|
||||
* we will lock the data source through `tableViewLockDataSource`, and unlock it by `tableViewUnlockDataSource` after the data fetching.
|
||||
* The application should not update the data source while the data source is locked, to keep data consistence.
|
||||
*/
|
||||
- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style asyncDataFetching:(BOOL)asyncDataFetchingEnabled;
|
||||
|
||||
/**
|
||||
* The number of screens left to scroll before the delegate -tableView:beginBatchFetchingWithContext: is called.
|
||||
*
|
||||
@@ -228,6 +228,15 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
- (ASCellNode *)nodeForRowAtIndexPath:(NSIndexPath *)indexPath;
|
||||
|
||||
/**
|
||||
* Similar to -indexPathForCell:.
|
||||
*
|
||||
* @param cellNode a cellNode part of the table view
|
||||
*
|
||||
* @returns an indexPath for this cellNode
|
||||
*/
|
||||
- (NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode;
|
||||
|
||||
/**
|
||||
* Similar to -visibleCells.
|
||||
*
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
#import "ASInternalHelpers.h"
|
||||
#import "ASLayout.h"
|
||||
|
||||
// FIXME: Temporary nonsense import until method names are finalized and exposed
|
||||
#import "ASDisplayNode+Subclasses.h"
|
||||
|
||||
//#define LOG(...) NSLog(__VA_ARGS__)
|
||||
#define LOG(...)
|
||||
|
||||
@@ -259,7 +262,8 @@ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) {
|
||||
|
||||
- (void)setDataSource:(id<UITableViewDataSource>)dataSource
|
||||
{
|
||||
ASDisplayNodeAssert(NO, @"ASTableView uses asyncDataSource, not UITableView's dataSource property.");
|
||||
// UIKit can internally generate a call to this method upon changing the asyncDataSource; only assert for non-nil.
|
||||
ASDisplayNodeAssert(dataSource == nil, @"ASTableView uses asyncDataSource, not UITableView's dataSource property.");
|
||||
}
|
||||
|
||||
- (void)setDelegate:(id<UITableViewDelegate>)delegate
|
||||
@@ -345,6 +349,11 @@ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) {
|
||||
return [_dataController nodeAtIndexPath:indexPath];
|
||||
}
|
||||
|
||||
- (NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode
|
||||
{
|
||||
return [_dataController indexPathForNode:cellNode];
|
||||
}
|
||||
|
||||
- (NSArray *)visibleNodes
|
||||
{
|
||||
NSArray *indexPaths = [self indexPathsForVisibleRows];
|
||||
@@ -563,6 +572,11 @@ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) {
|
||||
if ([_asyncDelegate respondsToSelector:@selector(tableView:willDisplayNodeForRowAtIndexPath:)]) {
|
||||
[_asyncDelegate tableView:self willDisplayNodeForRowAtIndexPath:indexPath];
|
||||
}
|
||||
|
||||
ASCellNode *cellNode = [self nodeForRowAtIndexPath:indexPath];
|
||||
if (cellNode.neverShowPlaceholders) {
|
||||
[cellNode recursivelyEnsureDisplay];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath
|
||||
|
||||
@@ -15,6 +15,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@property (nonatomic, strong, readonly) ASDisplayNode *node;
|
||||
|
||||
// AsyncDisplayKit 2.0 BETA: This property is still being tested, but it allows
|
||||
// blocking as a view controller becomes visible to ensure no placeholders flash onscreen.
|
||||
// Refer to examples/SynchronousConcurrency, AsyncViewController.m
|
||||
@property (nonatomic, assign) BOOL neverShowPlaceholders;
|
||||
|
||||
- (instancetype)initWithNode:(ASDisplayNode *)node;
|
||||
|
||||
@end
|
||||
|
||||
@@ -10,7 +10,13 @@
|
||||
#import "ASAssert.h"
|
||||
#import "ASDimension.h"
|
||||
|
||||
// FIXME: Temporary nonsense import until method names are finalized and exposed
|
||||
#import "ASDisplayNode+Subclasses.h"
|
||||
|
||||
@implementation ASViewController
|
||||
{
|
||||
BOOL _ensureDisplayed;
|
||||
}
|
||||
|
||||
- (instancetype)initWithNode:(ASDisplayNode *)node
|
||||
{
|
||||
@@ -33,15 +39,25 @@
|
||||
|
||||
- (void)viewWillLayoutSubviews
|
||||
{
|
||||
[super viewWillLayoutSubviews];
|
||||
CGSize viewSize = self.view.bounds.size;
|
||||
ASSizeRange constrainedSize = ASSizeRangeMake(viewSize, viewSize);
|
||||
[_node measureWithSizeRange:constrainedSize];
|
||||
[super viewWillLayoutSubviews];
|
||||
}
|
||||
|
||||
- (void)viewDidLayoutSubviews
|
||||
{
|
||||
if (_ensureDisplayed && self.neverShowPlaceholders) {
|
||||
_ensureDisplayed = NO;
|
||||
[self.node recursivelyEnsureDisplay];
|
||||
}
|
||||
[super viewDidLayoutSubviews];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
_ensureDisplayed = YES;
|
||||
[_node recursivelyFetchData];
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#import <AsyncDisplayKit/ASBasicImageDownloader.h>
|
||||
#import <AsyncDisplayKit/ASMultiplexImageNode.h>
|
||||
#import <AsyncDisplayKit/ASNetworkImageNode.h>
|
||||
#import <AsyncDisplayKit/ASPhotosFrameworkImageRequest.h>
|
||||
|
||||
#import <AsyncDisplayKit/ASTableView.h>
|
||||
#import <AsyncDisplayKit/ASCollectionView.h>
|
||||
|
||||
@@ -175,6 +175,8 @@ typedef NSUInteger ASDataControllerAnimationOptions;
|
||||
|
||||
- (nullable ASCellNode *)nodeAtIndexPath:(NSIndexPath *)indexPath;
|
||||
|
||||
- (nullable NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode;
|
||||
|
||||
- (NSArray<ASCellNode *> *)nodesAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
|
||||
|
||||
- (NSArray<NSArray <ASCellNode *> *> *)completedNodes; // This provides efficient access to the entire _completedNodes multidimensional array.
|
||||
|
||||
@@ -24,7 +24,8 @@ const static NSUInteger kASDataControllerSizingCountPerProcessor = 5;
|
||||
static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
|
||||
@interface ASDataController () {
|
||||
NSMutableArray *_completedNodes; // Main thread only. External data access can immediately query this.
|
||||
NSMutableArray *_externalCompletedNodes; // Main thread only. External data access can immediately query this if available.
|
||||
NSMutableArray *_completedNodes; // Main thread only. External data access can immediately query this if _externalCompletedNodes is unavailable.
|
||||
NSMutableArray *_editingNodes; // Modified on _editingTransactionQueue only. Updates propogated to _completedNodes.
|
||||
|
||||
NSMutableArray *_pendingEditCommandBlocks; // To be run on the main thread. Handles begin/endUpdates tracking.
|
||||
@@ -104,31 +105,27 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
}
|
||||
|
||||
dispatch_group_t layoutGroup = dispatch_group_create();
|
||||
|
||||
ASSizeRange *nodeBoundSizes = (ASSizeRange *)malloc(sizeof(ASSizeRange) * nodes.count);
|
||||
for (NSUInteger j = 0; j < nodes.count && j < indexPaths.count; j += kASDataControllerSizingCountPerProcessor) {
|
||||
NSArray *subIndexPaths = [indexPaths subarrayWithRange:NSMakeRange(j, MIN(kASDataControllerSizingCountPerProcessor, indexPaths.count - j))];
|
||||
NSInteger batchCount = MIN(kASDataControllerSizingCountPerProcessor, indexPaths.count - j);
|
||||
|
||||
//TODO: There should be a fast-path that avoids all of this object creation.
|
||||
NSMutableArray *nodeBoundSizes = [[NSMutableArray alloc] initWithCapacity:kASDataControllerSizingCountPerProcessor];
|
||||
[subIndexPaths enumerateObjectsUsingBlock:^(NSIndexPath *indexPath, NSUInteger idx, BOOL *stop) {
|
||||
ASSizeRange constrainedSize = [_dataSource dataController:self constrainedSizeForNodeAtIndexPath:indexPath];
|
||||
[nodeBoundSizes addObject:[NSValue valueWithBytes:&constrainedSize objCType:@encode(ASSizeRange)]];
|
||||
}];
|
||||
for (NSUInteger k = j; k < j + batchCount; k++) {
|
||||
nodeBoundSizes[k] = [_dataSource dataController:self constrainedSizeForNodeAtIndexPath:indexPaths[k]];
|
||||
}
|
||||
|
||||
dispatch_group_async(layoutGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[subIndexPaths enumerateObjectsUsingBlock:^(NSIndexPath *indexPath, NSUInteger idx, BOOL *stop) {
|
||||
ASCellNode *node = nodes[j + idx];
|
||||
ASSizeRange constrainedSize;
|
||||
[nodeBoundSizes[idx] getValue:&constrainedSize];
|
||||
for (NSUInteger k = j; k < j + batchCount; k++) {
|
||||
ASCellNode *node = nodes[k];
|
||||
ASSizeRange constrainedSize = nodeBoundSizes[k];
|
||||
[node measureWithSizeRange:constrainedSize];
|
||||
node.frame = CGRectMake(0.0f, 0.0f, node.calculatedSize.width, node.calculatedSize.height);
|
||||
}];
|
||||
node.frame = CGRectMake(0, 0, node.calculatedSize.width, node.calculatedSize.height);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Block the _editingTransactionQueue from executing a new edit transaction until layout is done & _editingNodes array is updated.
|
||||
dispatch_group_wait(layoutGroup, DISPATCH_TIME_FOREVER);
|
||||
|
||||
free(nodeBoundSizes);
|
||||
// Insert finished nodes into data storage
|
||||
[self _insertNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOptions];
|
||||
}
|
||||
@@ -347,6 +344,10 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
|
||||
[_editingTransactionQueue addOperationWithBlock:^{
|
||||
ASDisplayNodePerformBlockOnMainThread(^{
|
||||
// Deep copy _completedNodes to _externalCompletedNodes.
|
||||
// Any external queries from now on will be done on _externalCompletedNodes, to guarantee data consistency with the delegate.
|
||||
_externalCompletedNodes = (NSMutableArray *)ASMultidimensionalArrayDeepMutableCopy(_completedNodes);
|
||||
|
||||
LOG(@"endUpdatesWithCompletion - begin updates call to delegate");
|
||||
[_delegate dataControllerBeginUpdates:self];
|
||||
});
|
||||
@@ -363,6 +364,9 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
|
||||
[_editingTransactionQueue addOperationWithBlock:^{
|
||||
ASDisplayNodePerformBlockOnMainThread(^{
|
||||
// Now that the transaction is done, _completedNodes can be accessed externally again.
|
||||
_externalCompletedNodes = nil;
|
||||
|
||||
LOG(@"endUpdatesWithCompletion - calling delegate end");
|
||||
[_delegate dataController:self endUpdatesAnimated:animated completion:completion];
|
||||
});
|
||||
@@ -617,31 +621,51 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
- (NSUInteger)numberOfSections
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
return [_completedNodes count];
|
||||
return [[self completedNodes] count];
|
||||
}
|
||||
|
||||
- (NSUInteger)numberOfRowsInSection:(NSUInteger)section
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
return [_completedNodes[section] count];
|
||||
return [[self completedNodes][section] count];
|
||||
}
|
||||
|
||||
- (ASCellNode *)nodeAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
return _completedNodes[indexPath.section][indexPath.row];
|
||||
return [self completedNodes][indexPath.section][indexPath.row];
|
||||
}
|
||||
|
||||
- (NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode;
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
|
||||
NSArray *nodes = [self completedNodes];
|
||||
NSUInteger numberOfNodes = nodes.count;
|
||||
|
||||
// Loop through each section to look for the cellNode
|
||||
for (NSUInteger i = 0; i < numberOfNodes; i++) {
|
||||
NSArray *sectionNodes = nodes[i];
|
||||
NSUInteger cellIndex = [sectionNodes indexOfObjectIdenticalTo:cellNode];
|
||||
if (cellIndex != NSNotFound) {
|
||||
return [NSIndexPath indexPathForRow:cellIndex inSection:i];
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSArray *)nodesAtIndexPaths:(NSArray *)indexPaths
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
return ASFindElementsInMultidimensionalArrayAtIndexPaths(_completedNodes, [indexPaths sortedArrayUsingSelector:@selector(compare:)]);
|
||||
return ASFindElementsInMultidimensionalArrayAtIndexPaths((NSMutableArray *)[self completedNodes], [indexPaths sortedArrayUsingSelector:@selector(compare:)]);
|
||||
}
|
||||
|
||||
/// Returns nodes that can be queried externally. _externalCompletedNodes is used if available, _completedNodes otherwise.
|
||||
- (NSArray *)completedNodes
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
return _completedNodes;
|
||||
return _externalCompletedNodes != nil ? _externalCompletedNodes : _completedNodes;
|
||||
}
|
||||
|
||||
#pragma mark - Dealloc
|
||||
|
||||
66
AsyncDisplayKit/Details/ASPhotosFrameworkImageRequest.h
Normal file
66
AsyncDisplayKit/Details/ASPhotosFrameworkImageRequest.h
Normal file
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// ASPhotosFrameworkImageRequest.h
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Adlai Holler on 9/25/15.
|
||||
// Copyright © 2015 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <Photos/Photos.h>
|
||||
|
||||
// NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
extern NSString *const ASPhotosURLScheme;
|
||||
|
||||
/**
|
||||
@abstract Use ASPhotosFrameworkImageRequest to encapsulate all the information needed to request an image from
|
||||
the Photos framework and store it in a URL.
|
||||
*/
|
||||
@interface ASPhotosFrameworkImageRequest : NSObject <NSCopying>
|
||||
|
||||
- (instancetype)initWithAssetIdentifier:(NSString *)assetIdentifier NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
@return A new image request deserialized from `url`, or nil if `url` is not a valid photos URL.
|
||||
*/
|
||||
+ (/*nullable*/ ASPhotosFrameworkImageRequest *)requestWithURL:(NSURL *)url;
|
||||
|
||||
/**
|
||||
@abstract The asset identifier for this image request provided during initialization.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSString *assetIdentifier;
|
||||
|
||||
/**
|
||||
@abstract The target size for this image request. Defaults to `PHImageManagerMaximumSize`.
|
||||
*/
|
||||
@property (nonatomic) CGSize targetSize;
|
||||
|
||||
/**
|
||||
@abstract The content mode for this image request. Defaults to `PHImageContentModeDefault`.
|
||||
|
||||
@see `PHImageManager`
|
||||
*/
|
||||
@property (nonatomic) PHImageContentMode contentMode;
|
||||
|
||||
/**
|
||||
@abstract The options specified for this request. Default value is the result of `[PHImageRequestOptions new]`.
|
||||
|
||||
@discussion Some properties of this object are ignored when converting this request into a URL.
|
||||
As of iOS SDK 9.0, these properties are `progressHandler` and `synchronous`.
|
||||
*/
|
||||
@property (nonatomic, strong) PHImageRequestOptions *options;
|
||||
|
||||
/**
|
||||
@return A new URL converted from this request.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSURL *url;
|
||||
|
||||
/**
|
||||
@return `YES` if `object` is an equivalent image request, `NO` otherwise.
|
||||
*/
|
||||
- (BOOL)isEqual:(id)object;
|
||||
|
||||
@end
|
||||
|
||||
// NS_ASSUME_NONNULL_END
|
||||
161
AsyncDisplayKit/Details/ASPhotosFrameworkImageRequest.m
Normal file
161
AsyncDisplayKit/Details/ASPhotosFrameworkImageRequest.m
Normal file
@@ -0,0 +1,161 @@
|
||||
//
|
||||
// ASPhotosFrameworkImageRequest.m
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Adlai Holler on 9/25/15.
|
||||
// Copyright © 2015 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ASPhotosFrameworkImageRequest.h"
|
||||
#import "ASBaseDefines.h"
|
||||
#import "ASAvailability.h"
|
||||
|
||||
NSString *const ASPhotosURLScheme = @"ph";
|
||||
|
||||
static NSString *const _ASPhotosURLQueryKeyWidth = @"width";
|
||||
static NSString *const _ASPhotosURLQueryKeyHeight = @"height";
|
||||
|
||||
// value is PHImageContentMode value
|
||||
static NSString *const _ASPhotosURLQueryKeyContentMode = @"contentmode";
|
||||
|
||||
// value is PHImageRequestOptionsResizeMode value
|
||||
static NSString *const _ASPhotosURLQueryKeyResizeMode = @"resizemode";
|
||||
|
||||
// value is PHImageRequestOptionsDeliveryMode value
|
||||
static NSString *const _ASPhotosURLQueryKeyDeliveryMode = @"deliverymode";
|
||||
|
||||
// value is PHImageRequestOptionsVersion value
|
||||
static NSString *const _ASPhotosURLQueryKeyVersion = @"version";
|
||||
|
||||
// value is 0 or 1
|
||||
static NSString *const _ASPhotosURLQueryKeyAllowNetworkAccess = @"network";
|
||||
|
||||
static NSString *const _ASPhotosURLQueryKeyCropOriginX = @"crop_x";
|
||||
static NSString *const _ASPhotosURLQueryKeyCropOriginY = @"crop_y";
|
||||
static NSString *const _ASPhotosURLQueryKeyCropWidth = @"crop_w";
|
||||
static NSString *const _ASPhotosURLQueryKeyCropHeight = @"crop_h";
|
||||
|
||||
@implementation ASPhotosFrameworkImageRequest
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
ASDISPLAYNODE_NOT_DESIGNATED_INITIALIZER();
|
||||
self = [self initWithAssetIdentifier:@""];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (instancetype)initWithAssetIdentifier:(NSString *)assetIdentifier
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_assetIdentifier = assetIdentifier;
|
||||
_options = [PHImageRequestOptions new];
|
||||
_contentMode = PHImageContentModeDefault;
|
||||
_targetSize = PHImageManagerMaximumSize;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark NSCopying
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone
|
||||
{
|
||||
ASPhotosFrameworkImageRequest *copy = [[ASPhotosFrameworkImageRequest alloc] initWithAssetIdentifier:self.assetIdentifier];
|
||||
copy.options = [self.options copy];
|
||||
copy.targetSize = self.targetSize;
|
||||
copy.contentMode = self.contentMode;
|
||||
return copy;
|
||||
}
|
||||
|
||||
#pragma mark Converting to URL
|
||||
|
||||
- (NSURL *)url
|
||||
{
|
||||
NSURLComponents *comp = [NSURLComponents new];
|
||||
comp.scheme = ASPhotosURLScheme;
|
||||
comp.host = _assetIdentifier;
|
||||
NSMutableArray *queryItems = [NSMutableArray arrayWithObjects:
|
||||
[NSURLQueryItem queryItemWithName:_ASPhotosURLQueryKeyWidth value:@(_targetSize.width).stringValue],
|
||||
[NSURLQueryItem queryItemWithName:_ASPhotosURLQueryKeyHeight value:@(_targetSize.height).stringValue],
|
||||
[NSURLQueryItem queryItemWithName:_ASPhotosURLQueryKeyVersion value:@(_options.version).stringValue],
|
||||
[NSURLQueryItem queryItemWithName:_ASPhotosURLQueryKeyContentMode value:@(_contentMode).stringValue],
|
||||
[NSURLQueryItem queryItemWithName:_ASPhotosURLQueryKeyAllowNetworkAccess value:@(_options.networkAccessAllowed).stringValue],
|
||||
[NSURLQueryItem queryItemWithName:_ASPhotosURLQueryKeyResizeMode value:@(_options.resizeMode).stringValue],
|
||||
[NSURLQueryItem queryItemWithName:_ASPhotosURLQueryKeyDeliveryMode value:@(_options.deliveryMode).stringValue]
|
||||
, nil];
|
||||
|
||||
CGRect cropRect = _options.normalizedCropRect;
|
||||
if (!CGRectIsEmpty(cropRect)) {
|
||||
[queryItems addObjectsFromArray:@[
|
||||
[NSURLQueryItem queryItemWithName:_ASPhotosURLQueryKeyCropOriginX value:@(cropRect.origin.x).stringValue],
|
||||
[NSURLQueryItem queryItemWithName:_ASPhotosURLQueryKeyCropOriginY value:@(cropRect.origin.y).stringValue],
|
||||
[NSURLQueryItem queryItemWithName:_ASPhotosURLQueryKeyCropWidth value:@(cropRect.size.width).stringValue],
|
||||
[NSURLQueryItem queryItemWithName:_ASPhotosURLQueryKeyCropHeight value:@(cropRect.size.height).stringValue]
|
||||
]];
|
||||
}
|
||||
comp.queryItems = queryItems;
|
||||
return comp.URL;
|
||||
}
|
||||
|
||||
#pragma mark Converting from URL
|
||||
|
||||
+ (ASPhotosFrameworkImageRequest *)requestWithURL:(NSURL *)url
|
||||
{
|
||||
// not a photos URL or iOS < 8
|
||||
if (![url.scheme isEqualToString:ASPhotosURLScheme] || !AS_AT_LEAST_IOS8) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSURLComponents *comp = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO];
|
||||
|
||||
ASPhotosFrameworkImageRequest *request = [[ASPhotosFrameworkImageRequest alloc] initWithAssetIdentifier:url.host];
|
||||
|
||||
CGRect cropRect = CGRectZero;
|
||||
CGSize targetSize = PHImageManagerMaximumSize;
|
||||
for (NSURLQueryItem *item in comp.queryItems) {
|
||||
if ([_ASPhotosURLQueryKeyAllowNetworkAccess isEqualToString:item.name]) {
|
||||
request.options.networkAccessAllowed = item.value.boolValue;
|
||||
} else if ([_ASPhotosURLQueryKeyWidth isEqualToString:item.name]) {
|
||||
targetSize.width = item.value.doubleValue;
|
||||
} else if ([_ASPhotosURLQueryKeyHeight isEqualToString:item.name]) {
|
||||
targetSize.height = item.value.doubleValue;
|
||||
} else if ([_ASPhotosURLQueryKeyContentMode isEqualToString:item.name]) {
|
||||
request.contentMode = (PHImageContentMode)item.value.integerValue;
|
||||
} else if ([_ASPhotosURLQueryKeyVersion isEqualToString:item.name]) {
|
||||
request.options.version = (PHImageRequestOptionsVersion)item.value.integerValue;
|
||||
} else if ([_ASPhotosURLQueryKeyCropOriginX isEqualToString:item.name]) {
|
||||
cropRect.origin.x = item.value.doubleValue;
|
||||
} else if ([_ASPhotosURLQueryKeyCropOriginY isEqualToString:item.name]) {
|
||||
cropRect.origin.y = item.value.doubleValue;
|
||||
} else if ([_ASPhotosURLQueryKeyCropWidth isEqualToString:item.name]) {
|
||||
cropRect.size.width = item.value.doubleValue;
|
||||
} else if ([_ASPhotosURLQueryKeyCropHeight isEqualToString:item.name]) {
|
||||
cropRect.size.height = item.value.doubleValue;
|
||||
} else if ([_ASPhotosURLQueryKeyResizeMode isEqualToString:item.name]) {
|
||||
request.options.resizeMode = (PHImageRequestOptionsResizeMode)item.value.integerValue;
|
||||
} else if ([_ASPhotosURLQueryKeyDeliveryMode isEqualToString:item.name]) {
|
||||
request.options.deliveryMode = (PHImageRequestOptionsDeliveryMode)item.value.integerValue;
|
||||
}
|
||||
}
|
||||
request.targetSize = targetSize;
|
||||
request.options.normalizedCropRect = cropRect;
|
||||
return request;
|
||||
}
|
||||
|
||||
#pragma mark NSObject
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
if (![object isKindOfClass:ASPhotosFrameworkImageRequest.class]) {
|
||||
return NO;
|
||||
}
|
||||
ASPhotosFrameworkImageRequest *other = object;
|
||||
return [other.assetIdentifier isEqualToString:self.assetIdentifier] &&
|
||||
other.contentMode == self.contentMode &&
|
||||
CGSizeEqualToSize(other.targetSize, self.targetSize) &&
|
||||
CGRectEqualToRect(other.options.normalizedCropRect, self.options.normalizedCropRect) &&
|
||||
other.options.resizeMode == self.options.resizeMode &&
|
||||
other.options.version == self.options.version;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -26,6 +26,7 @@ typedef NS_ENUM(NSUInteger, ASAsyncTransactionState) {
|
||||
ASAsyncTransactionStateOpen = 0,
|
||||
ASAsyncTransactionStateCommitted,
|
||||
ASAsyncTransactionStateCanceled,
|
||||
ASAsyncTransactionStateComplete
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -54,6 +55,13 @@ typedef NS_ENUM(NSUInteger, ASAsyncTransactionState) {
|
||||
- (id)initWithCallbackQueue:(dispatch_queue_t)callbackQueue
|
||||
completionBlock:(asyncdisplaykit_async_transaction_completion_block_t)completionBlock;
|
||||
|
||||
/**
|
||||
@summary Block the main thread until the transaction is complete, including callbacks.
|
||||
|
||||
@desc This must be called on the main thread.
|
||||
*/
|
||||
- (void)waitUntilComplete;
|
||||
|
||||
/**
|
||||
The dispatch queue that the completion blocks will be called on.
|
||||
*/
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
#import "_ASAsyncTransaction.h"
|
||||
|
||||
#import "_ASAsyncTransactionGroup.h"
|
||||
#import "ASAssert.h"
|
||||
|
||||
@interface ASDisplayNodeAsyncTransactionOperation : NSObject
|
||||
@@ -40,6 +40,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"<ASDisplayNodeAsyncTransactionOperation: %p - value = %@", self, self.value];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _ASAsyncTransaction
|
||||
@@ -140,7 +145,7 @@
|
||||
ASDisplayNodeAssertMainThread();
|
||||
ASDisplayNodeAssert(_state == ASAsyncTransactionStateOpen, @"You cannot double-commit a transaction");
|
||||
_state = ASAsyncTransactionStateCommitted;
|
||||
|
||||
|
||||
if ([_operations count] == 0) {
|
||||
// Fast path: if a transaction was opened, but no operations were added, execute completion block synchronously.
|
||||
if (_completionBlock) {
|
||||
@@ -148,18 +153,59 @@
|
||||
}
|
||||
} else {
|
||||
ASDisplayNodeAssert(_group != NULL, @"If there are operations, dispatch group should have been created");
|
||||
|
||||
dispatch_group_notify(_group, _callbackQueue, ^{
|
||||
BOOL isCanceled = (_state == ASAsyncTransactionStateCanceled);
|
||||
for (ASDisplayNodeAsyncTransactionOperation *operation in _operations) {
|
||||
[operation callAndReleaseCompletionBlock:isCanceled];
|
||||
}
|
||||
if (_completionBlock) {
|
||||
_completionBlock(self, isCanceled);
|
||||
}
|
||||
// _callbackQueue is the main queue in current practice (also asserted in -waitUntilComplete).
|
||||
// This code should be reviewed before taking on significantly different use cases.
|
||||
ASDisplayNodeAssertMainThread();
|
||||
[self completeTransaction];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (void)completeTransaction
|
||||
{
|
||||
if (_state != ASAsyncTransactionStateComplete) {
|
||||
BOOL isCanceled = (_state == ASAsyncTransactionStateCanceled);
|
||||
for (ASDisplayNodeAsyncTransactionOperation *operation in _operations) {
|
||||
[operation callAndReleaseCompletionBlock:isCanceled];
|
||||
}
|
||||
|
||||
// Always set _state to Complete, even if we were cancelled, to block any extraneous
|
||||
// calls to this method that may have been scheduled for the next runloop
|
||||
// (e.g. if we needed to force one in this runloop with -waitUntilComplete, but another was already scheduled)
|
||||
_state = ASAsyncTransactionStateComplete;
|
||||
|
||||
if (_completionBlock) {
|
||||
_completionBlock(self, isCanceled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)waitUntilComplete
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
if (_state != ASAsyncTransactionStateComplete) {
|
||||
if (_group) {
|
||||
ASDisplayNodeAssertTrue(_callbackQueue == dispatch_get_main_queue());
|
||||
dispatch_group_wait(_group, DISPATCH_TIME_FOREVER);
|
||||
|
||||
// At this point, the asynchronous operation may have completed, but the runloop
|
||||
// observer has not committed the batch of transactions we belong to. It's important to
|
||||
// commit ourselves via the group to avoid double-committing the transaction.
|
||||
// This is only necessary when forcing display work to complete before allowing the runloop
|
||||
// to continue, e.g. in the implementation of -[ASDisplayNode recursivelyEnsureDisplay].
|
||||
if (_state == ASAsyncTransactionStateOpen) {
|
||||
[_ASAsyncTransactionGroup commit];
|
||||
ASDisplayNodeAssert(_state != ASAsyncTransactionStateOpen, @"Transaction should not be open after committing group");
|
||||
}
|
||||
// If we needed to commit the group above, -completeTransaction may have already been run.
|
||||
// It is designed to accomodate this by checking _state to ensure it is not complete.
|
||||
[self completeTransaction];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Helper Methods
|
||||
|
||||
@@ -174,4 +220,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"<_ASAsyncTransaction: %p - _state = %lu, _group = %@, _operations = %@>", self, (unsigned long)_state, _group, _operations];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
@interface _ASAsyncTransactionGroup : NSObject
|
||||
/// The main transaction group is scheduled to commit on every tick of the main runloop.
|
||||
+ (instancetype)mainTransactionGroup;
|
||||
+ (void)commit;
|
||||
|
||||
/// Add a transaction container to be committed.
|
||||
/// @param containerLayer A layer containing a transaction to be commited. May or may not be a container layer.
|
||||
|
||||
@@ -95,6 +95,11 @@ static void _transactionGroupRunLoopObserverCallback(CFRunLoopObserverRef observ
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)commit
|
||||
{
|
||||
[[_ASAsyncTransactionGroup mainTransactionGroup] commit];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static void _transactionGroupRunLoopObserverCallback(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info)
|
||||
|
||||
@@ -98,6 +98,7 @@ static Class gDefaultLayoutOptionsClass = nil;
|
||||
self.spacingBefore = layoutOptions.spacingBefore;
|
||||
self.flexGrow = layoutOptions.flexGrow;
|
||||
self.flexShrink = layoutOptions.flexShrink;
|
||||
self.alignSelf = layoutOptions.alignSelf;
|
||||
|
||||
self.ascender = layoutOptions.ascender;
|
||||
self.descender = layoutOptions.descender;
|
||||
|
||||
@@ -58,18 +58,14 @@
|
||||
[sublayouts addObject:sublayout];
|
||||
}
|
||||
|
||||
if (isnan(size.width) || size.width >= FLT_MAX - FLT_EPSILON) {
|
||||
size.width = constrainedSize.min.width;
|
||||
for (ASLayout *sublayout in sublayouts) {
|
||||
size.width = MAX(size.width, sublayout.position.x + sublayout.size.width);
|
||||
}
|
||||
size.width = constrainedSize.min.width;
|
||||
for (ASLayout *sublayout in sublayouts) {
|
||||
size.width = MAX(size.width, sublayout.position.x + sublayout.size.width);
|
||||
}
|
||||
|
||||
if (isnan(size.height) || size.height >= FLT_MAX - FLT_EPSILON) {
|
||||
size.height = constrainedSize.min.height;
|
||||
for (ASLayout *sublayout in sublayouts) {
|
||||
size.height = MAX(size.height, sublayout.position.y + sublayout.size.height);
|
||||
}
|
||||
size.height = constrainedSize.min.height;
|
||||
for (ASLayout *sublayout in sublayouts) {
|
||||
size.height = MAX(size.height, sublayout.position.y + sublayout.size.height);
|
||||
}
|
||||
|
||||
return [ASLayout layoutWithLayoutableObject:self
|
||||
|
||||
@@ -94,6 +94,8 @@ static void __ASDisplayLayerDecrementConcurrentDisplayCount(BOOL displayIsAsync,
|
||||
// Capture these outside the display block so they are retained.
|
||||
UIColor *backgroundColor = self.backgroundColor;
|
||||
CGRect bounds = self.bounds;
|
||||
CGFloat cornerRadius = self.cornerRadius;
|
||||
BOOL clipsToBounds = self.clipsToBounds;
|
||||
|
||||
CGRect frame;
|
||||
|
||||
@@ -129,7 +131,7 @@ static void __ASDisplayLayerDecrementConcurrentDisplayCount(BOOL displayIsAsync,
|
||||
CGContextTranslateCTM(context, frame.origin.x, frame.origin.y);
|
||||
|
||||
//support cornerRadius
|
||||
if (rasterizingFromAscendent && self.cornerRadius && self.clipsToBounds) {
|
||||
if (rasterizingFromAscendent && cornerRadius && clipsToBounds) {
|
||||
[[UIBezierPath bezierPathWithRoundedRect:bounds cornerRadius:self.cornerRadius] addClip];
|
||||
}
|
||||
|
||||
@@ -308,16 +310,14 @@ static void __ASDisplayLayerDecrementConcurrentDisplayCount(BOOL displayIsAsync,
|
||||
return BOOL(displaySentinelValue != displaySentinel.value);
|
||||
};
|
||||
|
||||
// If we're participating in an ancestor's asyncTransaction, find it here
|
||||
ASDisplayNodeAssert(_layer, @"Expect _layer to be not nil");
|
||||
CALayer *containerLayer = _layer.asyncdisplaykit_parentTransactionContainer ?: _layer;
|
||||
_ASAsyncTransaction *transaction = containerLayer.asyncdisplaykit_asyncTransaction;
|
||||
|
||||
// Set up displayBlock to call either display or draw on the delegate and return a UIImage contents
|
||||
asyncdisplaykit_async_transaction_operation_block_t displayBlock = [self _displayBlockWithAsynchronous:asynchronously isCancelledBlock:isCancelledBlock rasterizing:NO];
|
||||
|
||||
if (!displayBlock) {
|
||||
return;
|
||||
}
|
||||
|
||||
ASDisplayNodeAssert(_layer, @"Expect _layer to be not nil");
|
||||
|
||||
// This block is called back on the main thread after rendering at the completion of the current async transaction, or immediately if !asynchronously
|
||||
asyncdisplaykit_async_transaction_operation_completion_block_t completionBlock = ^(id<NSObject> value, BOOL canceled){
|
||||
@@ -335,16 +335,27 @@ static void __ASDisplayLayerDecrementConcurrentDisplayCount(BOOL displayIsAsync,
|
||||
}
|
||||
};
|
||||
|
||||
if (displayBlock != NULL) {
|
||||
// Call willDisplay immediately in either case
|
||||
[self willDisplayAsyncLayer:self.asyncLayer];
|
||||
// Call willDisplay immediately in either case
|
||||
[self willDisplayAsyncLayer:self.asyncLayer];
|
||||
|
||||
if (asynchronously) {
|
||||
[transaction addOperationWithBlock:displayBlock queue:[_ASDisplayLayer displayQueue] completion:completionBlock];
|
||||
} else {
|
||||
UIImage *contents = (UIImage *)displayBlock();
|
||||
completionBlock(contents, NO);
|
||||
}
|
||||
if (asynchronously) {
|
||||
// Async rendering operations are contained by a transaction, which allows them to proceed and concurrently
|
||||
// while synchronizing the final application of the results to the layer's contents property (completionBlock).
|
||||
|
||||
// First, look to see if we are expected to join a parent's transaction container.
|
||||
CALayer *containerLayer = _layer.asyncdisplaykit_parentTransactionContainer ?: _layer;
|
||||
|
||||
// In the case that a transaction does not yet exist (such as for an individual node outside of a container),
|
||||
// this call will allocate the transaction and add it to _ASAsyncTransactionGroup.
|
||||
// It will automatically commit the transaction at the end of the runloop.
|
||||
_ASAsyncTransaction *transaction = containerLayer.asyncdisplaykit_asyncTransaction;
|
||||
|
||||
// Adding this displayBlock operation to the transaction will start it IMMEDIATELY.
|
||||
// The only function of the transaction commit is to gate the calling of the completionBlock.
|
||||
[transaction addOperationWithBlock:displayBlock queue:[_ASDisplayLayer displayQueue] completion:completionBlock];
|
||||
} else {
|
||||
UIImage *contents = (UIImage *)displayBlock();
|
||||
completionBlock(contents, NO);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
#define _messageToLayer(layerSelector) __loaded ? [_layer layerSelector] : [self.pendingViewState layerSelector]
|
||||
|
||||
/**
|
||||
* This category implements certainly frequently-used properties and methods of UIView and CALayer so that ASDisplayNode clients can just call the view/layer methods on the node,
|
||||
* This category implements certain frequently-used properties and methods of UIView and CALayer so that ASDisplayNode clients can just call the view/layer methods on the node,
|
||||
* with minimal loss in performance. Unlike UIView and CALayer methods, these can be called from a non-main thread until the view or layer is created.
|
||||
* This allows text sizing in -calculateSizeThatFits: (essentially a simplified layout) to happen off the main thread
|
||||
* without any CALayer or UIView actually existing while still being able to set and read properties from ASDisplayNode instances.
|
||||
@@ -122,7 +122,7 @@
|
||||
// Frame is only defined when transform is identity.
|
||||
#if DEBUG
|
||||
// Checking if the transform is identity is expensive, so disable when unnecessary. We have assertions on in Release, so DEBUG is the only way I know of.
|
||||
ASDisplayNodeAssert(CATransform3DIsIdentity(self.transform), @"Must be an identity transform");
|
||||
ASDisplayNodeAssert(CATransform3DIsIdentity(self.transform), @"-[ASDisplayNode frame] - self.transform must be identity in order to use the frame property. (From Apple's UIView documentation: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.)");
|
||||
#endif
|
||||
|
||||
CGPoint position = self.position;
|
||||
@@ -140,7 +140,7 @@
|
||||
// Frame is only defined when transform is identity because we explicitly diverge from CALayer behavior and define frame without transform
|
||||
#if DEBUG
|
||||
// Checking if the transform is identity is expensive, so disable when unnecessary. We have assertions on in Release, so DEBUG is the only way I know of.
|
||||
ASDisplayNodeAssert(CATransform3DIsIdentity(self.transform), @"Must be an identity transform");
|
||||
ASDisplayNodeAssert(CATransform3DIsIdentity(self.transform), @"-[ASDisplayNode setFrame:] - self.transform must be identity in order to set the frame property. (From Apple's UIView documentation: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.)");
|
||||
#endif
|
||||
|
||||
BOOL useLayer = (_layer && ASDisplayNodeThreadIsMain());
|
||||
|
||||
@@ -80,6 +80,7 @@ typedef NS_OPTIONS(NSUInteger, ASDisplayNodeMethodOverrides) {
|
||||
unsigned layerBacked:1;
|
||||
unsigned displaysAsynchronously:1;
|
||||
unsigned shouldRasterizeDescendants:1;
|
||||
unsigned shouldBypassEnsureDisplay:1;
|
||||
unsigned displaySuspended:1;
|
||||
|
||||
// whether custom drawing is enabled
|
||||
|
||||
60
AsyncDisplayKitTests/ASPhotosFrameworkImageRequestTests.m
Normal file
60
AsyncDisplayKitTests/ASPhotosFrameworkImageRequestTests.m
Normal file
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// ASPhotosFrameworkImageRequestTests.m
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Adlai Holler on 9/25/15.
|
||||
// Copyright © 2015 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
#import "ASPhotosFrameworkImageRequest.h"
|
||||
|
||||
static NSString *const kTestAssetID = @"testAssetID";
|
||||
|
||||
@interface ASPhotosFrameworkImageRequestTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation ASPhotosFrameworkImageRequestTests
|
||||
|
||||
#pragma mark Example Data
|
||||
|
||||
+ (ASPhotosFrameworkImageRequest *)exampleImageRequest
|
||||
{
|
||||
ASPhotosFrameworkImageRequest *req = [[ASPhotosFrameworkImageRequest alloc] initWithAssetIdentifier:kTestAssetID];
|
||||
req.options.networkAccessAllowed = YES;
|
||||
req.options.normalizedCropRect = CGRectMake(0.2, 0.1, 0.6, 0.8);
|
||||
req.targetSize = CGSizeMake(1024, 1536);
|
||||
req.contentMode = PHImageContentModeAspectFill;
|
||||
req.options.version = PHImageRequestOptionsVersionOriginal;
|
||||
req.options.resizeMode = PHImageRequestOptionsResizeModeFast;
|
||||
return req;
|
||||
}
|
||||
|
||||
+ (NSURL *)urlForExampleImageRequest
|
||||
{
|
||||
NSString *str = [NSString stringWithFormat:@"ph://%@?width=1024&height=1536&version=2&contentmode=1&network=1&resizemode=1&deliverymode=0&crop_x=0.2&crop_y=0.1&crop_w=0.6&crop_h=0.8", kTestAssetID];
|
||||
return [NSURL URLWithString:str];
|
||||
}
|
||||
|
||||
#pragma mark Test cases
|
||||
|
||||
- (void)testThatConvertingToURLWorks
|
||||
{
|
||||
XCTAssertEqualObjects([self.class exampleImageRequest].url, [self.class urlForExampleImageRequest]);
|
||||
}
|
||||
|
||||
- (void)testThatParsingFromURLWorks
|
||||
{
|
||||
NSURL *url = [self.class urlForExampleImageRequest];
|
||||
XCTAssertEqualObjects([ASPhotosFrameworkImageRequest requestWithURL:url], [self.class exampleImageRequest]);
|
||||
}
|
||||
|
||||
- (void)testThatCopyingWorks
|
||||
{
|
||||
ASPhotosFrameworkImageRequest *example = [self.class exampleImageRequest];
|
||||
ASPhotosFrameworkImageRequest *copy = [[self.class exampleImageRequest] copy];
|
||||
XCTAssertEqualObjects(example, copy);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -428,4 +428,27 @@
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)testIndexPathForNode
|
||||
{
|
||||
CGSize tableViewSize = CGSizeMake(100, 500);
|
||||
ASTestTableView *tableView = [[ASTestTableView alloc] initWithFrame:CGRectMake(0, 0, tableViewSize.width, tableViewSize.height)
|
||||
style:UITableViewStylePlain
|
||||
asyncDataFetching:YES];
|
||||
ASTableViewFilledDataSource *dataSource = [ASTableViewFilledDataSource new];
|
||||
|
||||
tableView.asyncDelegate = dataSource;
|
||||
tableView.asyncDataSource = dataSource;
|
||||
|
||||
[tableView reloadDataWithCompletion:^{
|
||||
for (NSUInteger i = 0; i < NumberOfSections; i++) {
|
||||
for (NSUInteger j = 0; j < NumberOfRowsPerSection; j++) {
|
||||
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:j inSection:i];
|
||||
ASCellNode *cellNode = [tableView nodeForRowAtIndexPath:indexPath];
|
||||
NSIndexPath *reportedIndexPath = [tableView indexPathForNode:cellNode];
|
||||
XCTAssertEqual(indexPath.row, reportedIndexPath.row);
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
BIN
ObjectiveC.gcno
Normal file
BIN
ObjectiveC.gcno
Normal file
Binary file not shown.
@@ -10,4 +10,4 @@ SPEC CHECKSUMS:
|
||||
FBSnapshotTestCase: 3dc3899168747a0319c5278f5b3445c13a6532dd
|
||||
OCMock: a6a7dc0e3997fb9f35d99f72528698ebf60d64f2
|
||||
|
||||
COCOAPODS: 0.37.2
|
||||
COCOAPODS: 0.38.2
|
||||
|
||||
BIN
QuartzCore.gcno
Normal file
BIN
QuartzCore.gcno
Normal file
Binary file not shown.
13
build.sh
13
build.sh
@@ -60,4 +60,17 @@ if [ "$MODE" = "life-without-cocoapods" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$MODE" = "framework" ]; then
|
||||
echo "Verifying that AsyncDisplayKit functions as a dynamic framework (for Swift/Carthage users)."
|
||||
|
||||
xctool \
|
||||
-project "smoke-tests/Framework/Sample.xcodeproj" \
|
||||
-scheme Sample \
|
||||
-sdk "$SDK" \
|
||||
-destination "$PLATFORM" \
|
||||
build
|
||||
trap - EXIT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Unrecognised mode '$MODE'."
|
||||
|
||||
@@ -100,9 +100,6 @@
|
||||
|
||||
- (void)thrashTableView
|
||||
{
|
||||
_tableView.asyncDelegate = self;
|
||||
_tableView.asyncDataSource = self;
|
||||
|
||||
[_tableView reloadData];
|
||||
|
||||
NSArray *indexPathsAddedAndRemoved = nil;
|
||||
|
||||
@@ -38,7 +38,7 @@ static const CGFloat kInnerPadding = 10.0f;
|
||||
|
||||
@implementation KittenNode
|
||||
|
||||
// lorem ipsum text courtesy http://kittyipsum.com/ <3
|
||||
// lorem ipsum text courtesy https://kittyipsum.com/ <3
|
||||
+ (NSArray *)placeholders
|
||||
{
|
||||
static NSArray *placeholders = nil;
|
||||
@@ -82,7 +82,7 @@ static const CGFloat kInnerPadding = 10.0f;
|
||||
// kitten image, with a solid background colour serving as placeholder
|
||||
_imageNode = [[ASNetworkImageNode alloc] init];
|
||||
_imageNode.backgroundColor = ASDisplayNodeDefaultPlaceholderColor();
|
||||
_imageNode.URL = [NSURL URLWithString:[NSString stringWithFormat:@"http://placekitten.com/%zd/%zd",
|
||||
_imageNode.URL = [NSURL URLWithString:[NSString stringWithFormat:@"https://placekitten.com/%zd/%zd",
|
||||
(NSInteger)roundl(_kittenSize.width),
|
||||
(NSInteger)roundl(_kittenSize.height)]];
|
||||
// _imageNode.contentMode = UIViewContentModeCenter;
|
||||
|
||||
BIN
examples/SynchronousConcurrency/Default-568h@2x.png
Normal file
BIN
examples/SynchronousConcurrency/Default-568h@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
examples/SynchronousConcurrency/Default-667h@2x.png
Normal file
BIN
examples/SynchronousConcurrency/Default-667h@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
BIN
examples/SynchronousConcurrency/Default-736h@3x.png
Normal file
BIN
examples/SynchronousConcurrency/Default-736h@3x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
3
examples/SynchronousConcurrency/Podfile
Normal file
3
examples/SynchronousConcurrency/Podfile
Normal file
@@ -0,0 +1,3 @@
|
||||
source 'https://github.com/CocoaPods/Specs.git'
|
||||
platform :ios, '8.0'
|
||||
pod 'AsyncDisplayKit', :path => '../..'
|
||||
361
examples/SynchronousConcurrency/Sample.xcodeproj/project.pbxproj
Normal file
361
examples/SynchronousConcurrency/Sample.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,361 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0585428019D4DBE100606EA6 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0585427F19D4DBE100606EA6 /* Default-568h@2x.png */; };
|
||||
05E2128719D4DB510098F589 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 05E2128619D4DB510098F589 /* main.m */; };
|
||||
05E2128A19D4DB510098F589 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 05E2128919D4DB510098F589 /* AppDelegate.m */; };
|
||||
05E2128D19D4DB510098F589 /* AsyncTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 05E2128C19D4DB510098F589 /* AsyncTableViewController.m */; };
|
||||
18748FDB1BB727B20053A9C1 /* AsyncViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18748FDA1BB727B20053A9C1 /* AsyncViewController.m */; settings = {ASSET_TAGS = (); }; };
|
||||
18C2ED861B9B8CE700F627B3 /* RandomCoreGraphicsNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 18C2ED851B9B8CE700F627B3 /* RandomCoreGraphicsNode.m */; };
|
||||
3EC0CDCBA10D483D9F386E5E /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D24B17D1E4A4E7A9566C5E9 /* libPods.a */; };
|
||||
6C2C82AC19EE274300767484 /* Default-667h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6C2C82AA19EE274300767484 /* Default-667h@2x.png */; };
|
||||
6C2C82AD19EE274300767484 /* Default-736h@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6C2C82AB19EE274300767484 /* Default-736h@3x.png */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0585427F19D4DBE100606EA6 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "../Default-568h@2x.png"; sourceTree = "<group>"; };
|
||||
05E2128119D4DB510098F589 /* Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sample.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
05E2128519D4DB510098F589 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
05E2128619D4DB510098F589 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
05E2128819D4DB510098F589 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
05E2128919D4DB510098F589 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
05E2128B19D4DB510098F589 /* AsyncTableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AsyncTableViewController.h; sourceTree = "<group>"; };
|
||||
05E2128C19D4DB510098F589 /* AsyncTableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AsyncTableViewController.m; sourceTree = "<group>"; };
|
||||
088AA6578212BE9BFBB07B70 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
|
||||
18748FD91BB727B20053A9C1 /* AsyncViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AsyncViewController.h; sourceTree = "<group>"; };
|
||||
18748FDA1BB727B20053A9C1 /* AsyncViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AsyncViewController.m; sourceTree = "<group>"; };
|
||||
18C2ED841B9B8CE700F627B3 /* RandomCoreGraphicsNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RandomCoreGraphicsNode.h; sourceTree = "<group>"; };
|
||||
18C2ED851B9B8CE700F627B3 /* RandomCoreGraphicsNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RandomCoreGraphicsNode.m; sourceTree = "<group>"; };
|
||||
3D24B17D1E4A4E7A9566C5E9 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6C2C82AA19EE274300767484 /* Default-667h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-667h@2x.png"; sourceTree = SOURCE_ROOT; };
|
||||
6C2C82AB19EE274300767484 /* Default-736h@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-736h@3x.png"; sourceTree = SOURCE_ROOT; };
|
||||
C068F1D3F0CC317E895FCDAB /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
05E2127E19D4DB510098F589 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3EC0CDCBA10D483D9F386E5E /* libPods.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
05E2127819D4DB510098F589 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05E2128319D4DB510098F589 /* Sample */,
|
||||
05E2128219D4DB510098F589 /* Products */,
|
||||
1A943BF0259746F18D6E423F /* Frameworks */,
|
||||
1AE410B73DA5C3BD087ACDD7 /* Pods */,
|
||||
);
|
||||
indentWidth = 2;
|
||||
sourceTree = "<group>";
|
||||
tabWidth = 2;
|
||||
usesTabs = 0;
|
||||
};
|
||||
05E2128219D4DB510098F589 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05E2128119D4DB510098F589 /* Sample.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
05E2128319D4DB510098F589 /* Sample */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05E2128819D4DB510098F589 /* AppDelegate.h */,
|
||||
05E2128919D4DB510098F589 /* AppDelegate.m */,
|
||||
05E2128B19D4DB510098F589 /* AsyncTableViewController.h */,
|
||||
05E2128C19D4DB510098F589 /* AsyncTableViewController.m */,
|
||||
18748FD91BB727B20053A9C1 /* AsyncViewController.h */,
|
||||
18748FDA1BB727B20053A9C1 /* AsyncViewController.m */,
|
||||
18C2ED841B9B8CE700F627B3 /* RandomCoreGraphicsNode.h */,
|
||||
18C2ED851B9B8CE700F627B3 /* RandomCoreGraphicsNode.m */,
|
||||
05E2128419D4DB510098F589 /* Supporting Files */,
|
||||
);
|
||||
path = Sample;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
05E2128419D4DB510098F589 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0585427F19D4DBE100606EA6 /* Default-568h@2x.png */,
|
||||
6C2C82AA19EE274300767484 /* Default-667h@2x.png */,
|
||||
6C2C82AB19EE274300767484 /* Default-736h@3x.png */,
|
||||
05E2128519D4DB510098F589 /* Info.plist */,
|
||||
05E2128619D4DB510098F589 /* main.m */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1A943BF0259746F18D6E423F /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3D24B17D1E4A4E7A9566C5E9 /* libPods.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1AE410B73DA5C3BD087ACDD7 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C068F1D3F0CC317E895FCDAB /* Pods.debug.xcconfig */,
|
||||
088AA6578212BE9BFBB07B70 /* Pods.release.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
05E2128019D4DB510098F589 /* Sample */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 05E212A419D4DB510098F589 /* Build configuration list for PBXNativeTarget "Sample" */;
|
||||
buildPhases = (
|
||||
E080B80F89C34A25B3488E26 /* Check Pods Manifest.lock */,
|
||||
05E2127D19D4DB510098F589 /* Sources */,
|
||||
05E2127E19D4DB510098F589 /* Frameworks */,
|
||||
05E2127F19D4DB510098F589 /* Resources */,
|
||||
F012A6F39E0149F18F564F50 /* Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Sample;
|
||||
productName = Sample;
|
||||
productReference = 05E2128119D4DB510098F589 /* Sample.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
05E2127919D4DB510098F589 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0600;
|
||||
ORGANIZATIONNAME = Facebook;
|
||||
TargetAttributes = {
|
||||
05E2128019D4DB510098F589 = {
|
||||
CreatedOnToolsVersion = 6.0.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 05E2127C19D4DB510098F589 /* Build configuration list for PBXProject "Sample" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 05E2127819D4DB510098F589;
|
||||
productRefGroup = 05E2128219D4DB510098F589 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
05E2128019D4DB510098F589 /* Sample */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
05E2127F19D4DB510098F589 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0585428019D4DBE100606EA6 /* Default-568h@2x.png in Resources */,
|
||||
6C2C82AC19EE274300767484 /* Default-667h@2x.png in Resources */,
|
||||
6C2C82AD19EE274300767484 /* Default-736h@3x.png in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
E080B80F89C34A25B3488E26 /* Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
F012A6F39E0149F18F564F50 /* Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Copy Pods Resources";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
05E2127D19D4DB510098F589 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
18C2ED861B9B8CE700F627B3 /* RandomCoreGraphicsNode.m in Sources */,
|
||||
18748FDB1BB727B20053A9C1 /* AsyncViewController.m in Sources */,
|
||||
05E2128D19D4DB510098F589 /* AsyncTableViewController.m in Sources */,
|
||||
05E2128A19D4DB510098F589 /* AppDelegate.m in Sources */,
|
||||
05E2128719D4DB510098F589 /* main.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
05E212A219D4DB510098F589 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
05E212A319D4DB510098F589 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
05E212A519D4DB510098F589 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = C068F1D3F0CC317E895FCDAB /* Pods.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
INFOPLIST_FILE = Sample/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
05E212A619D4DB510098F589 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 088AA6578212BE9BFBB07B70 /* Pods.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
INFOPLIST_FILE = Sample/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
05E2127C19D4DB510098F589 /* Build configuration list for PBXProject "Sample" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
05E212A219D4DB510098F589 /* Debug */,
|
||||
05E212A319D4DB510098F589 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
05E212A419D4DB510098F589 /* Build configuration list for PBXNativeTarget "Sample" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
05E212A519D4DB510098F589 /* Debug */,
|
||||
05E212A619D4DB510098F589 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 05E2127919D4DB510098F589 /* Project object */;
|
||||
}
|
||||
7
examples/SynchronousConcurrency/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
examples/SynchronousConcurrency/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:Sample.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0620"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "05E2128019D4DB510098F589"
|
||||
BuildableName = "Sample.app"
|
||||
BlueprintName = "Sample"
|
||||
ReferencedContainer = "container:Sample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "05E2128019D4DB510098F589"
|
||||
BuildableName = "Sample.app"
|
||||
BlueprintName = "Sample"
|
||||
ReferencedContainer = "container:Sample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "05E2128019D4DB510098F589"
|
||||
BuildableName = "Sample.app"
|
||||
BlueprintName = "Sample"
|
||||
ReferencedContainer = "container:Sample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "05E2128019D4DB510098F589"
|
||||
BuildableName = "Sample.app"
|
||||
BlueprintName = "Sample"
|
||||
ReferencedContainer = "container:Sample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
1
examples/SynchronousConcurrency/Sample.xcworkspace/contents.xcworkspacedata
generated
Normal file
1
examples/SynchronousConcurrency/Sample.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?><Workspace version='1.0'><FileRef location='group:Sample.xcodeproj'/><FileRef location='group:Pods/Pods.xcodeproj'/></Workspace>
|
||||
20
examples/SynchronousConcurrency/Sample/AppDelegate.h
Normal file
20
examples/SynchronousConcurrency/Sample/AppDelegate.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#define UseAutomaticLayout 1
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
|
||||
@end
|
||||
33
examples/SynchronousConcurrency/Sample/AppDelegate.m
Normal file
33
examples/SynchronousConcurrency/Sample/AppDelegate.m
Normal file
@@ -0,0 +1,33 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import "AsyncTableViewController.h"
|
||||
#import "AsyncViewController.h"
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
{
|
||||
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||
self.window.backgroundColor = [UIColor whiteColor];
|
||||
|
||||
UITabBarController *tabBarController = [[UITabBarController alloc] initWithNibName:nil bundle:nil];
|
||||
self.window.rootViewController = tabBarController;
|
||||
|
||||
[tabBarController setViewControllers:@[[[AsyncTableViewController alloc] init], [[AsyncViewController alloc] init]]];
|
||||
|
||||
[self.window makeKeyAndVisible];
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,16 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AsyncTableViewController : UIViewController
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,91 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
#import <AsyncDisplayKit/ASAssert.h>
|
||||
|
||||
#import "AsyncTableViewController.h"
|
||||
#import "RandomCoreGraphicsNode.h"
|
||||
|
||||
@interface AsyncTableViewController () <ASTableViewDataSource, ASTableViewDelegate>
|
||||
{
|
||||
ASTableView *_tableView;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation AsyncTableViewController
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark UIViewController.
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if (!(self = [super init]))
|
||||
return nil;
|
||||
|
||||
_tableView = [[ASTableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
|
||||
_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
|
||||
_tableView.asyncDataSource = self;
|
||||
_tableView.asyncDelegate = self;
|
||||
|
||||
ASRangeTuningParameters tuningParameters;
|
||||
tuningParameters.leadingBufferScreenfuls = 0.5;
|
||||
tuningParameters.trailingBufferScreenfuls = 1.0;
|
||||
[_tableView setTuningParameters:tuningParameters forRangeType:ASLayoutRangeTypePreload];
|
||||
[_tableView setTuningParameters:tuningParameters forRangeType:ASLayoutRangeTypeRender];
|
||||
|
||||
self.tabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemFeatured tag:0];
|
||||
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRedo
|
||||
target:self
|
||||
action:@selector(reloadEverything)];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)reloadEverything
|
||||
{
|
||||
[_tableView reloadData];
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
[self.view addSubview:_tableView];
|
||||
}
|
||||
|
||||
- (void)viewWillLayoutSubviews
|
||||
{
|
||||
_tableView.frame = self.view.bounds;
|
||||
}
|
||||
|
||||
- (BOOL)prefersStatusBarHidden
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark ASTableView.
|
||||
|
||||
- (ASCellNode *)tableView:(ASTableView *)tableView nodeForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
RandomCoreGraphicsNode *elementNode = [[RandomCoreGraphicsNode alloc] init];
|
||||
elementNode.preferredFrameSize = CGSizeMake(320, 100);
|
||||
return elementNode;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
@end
|
||||
13
examples/SynchronousConcurrency/Sample/AsyncViewController.h
Normal file
13
examples/SynchronousConcurrency/Sample/AsyncViewController.h
Normal file
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// AsyncViewController.h
|
||||
// Sample
|
||||
//
|
||||
// Created by Scott Goodson on 9/26/15.
|
||||
// Copyright © 2015 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ASViewController.h"
|
||||
|
||||
@interface AsyncViewController : ASViewController <UITabBarControllerDelegate>
|
||||
|
||||
@end
|
||||
37
examples/SynchronousConcurrency/Sample/AsyncViewController.m
Normal file
37
examples/SynchronousConcurrency/Sample/AsyncViewController.m
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// AsyncViewController.m
|
||||
// Sample
|
||||
//
|
||||
// Created by Scott Goodson on 9/26/15.
|
||||
// Copyright © 2015 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "AsyncViewController.h"
|
||||
#import "RandomCoreGraphicsNode.h"
|
||||
|
||||
@implementation AsyncViewController
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if (!(self = [super initWithNode:[[RandomCoreGraphicsNode alloc] init]])) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
self.neverShowPlaceholders = YES;
|
||||
self.tabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemFavorites tag:0];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
// FIXME: This is only being called on the first time the UITabBarController shows us.
|
||||
[super viewWillAppear:animated];
|
||||
}
|
||||
|
||||
- (void)viewDidDisappear:(BOOL)animated
|
||||
{
|
||||
[self.node recursivelyClearContents];
|
||||
[super viewDidDisappear:animated];
|
||||
}
|
||||
|
||||
@end
|
||||
36
examples/SynchronousConcurrency/Sample/Info.plist
Normal file
36
examples/SynchronousConcurrency/Sample/Info.plist
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.facebook.AsyncDisplayKit.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// RandomCoreGraphicsNode.h
|
||||
// Sample
|
||||
//
|
||||
// Created by Scott Goodson on 9/5/15.
|
||||
// Copyright (c) 2015 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
|
||||
@interface RandomCoreGraphicsNode : ASCellNode
|
||||
{
|
||||
ASTextNode *_textNode;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// RandomCoreGraphicsNode.m
|
||||
// Sample
|
||||
//
|
||||
// Created by Scott Goodson on 9/5/15.
|
||||
// Copyright (c) 2015 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RandomCoreGraphicsNode.h"
|
||||
#import <AsyncDisplayKit/ASDisplayNode+Subclasses.h>
|
||||
|
||||
@implementation RandomCoreGraphicsNode
|
||||
|
||||
+ (UIColor *)randomColor
|
||||
{
|
||||
CGFloat hue = ( arc4random() % 256 / 256.0 ); // 0.0 to 1.0
|
||||
CGFloat saturation = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from white
|
||||
CGFloat brightness = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from black
|
||||
return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1];
|
||||
}
|
||||
|
||||
+ (void)drawRect:(CGRect)bounds withParameters:(id<NSObject>)parameters isCancelled:(asdisplaynode_iscancelled_block_t)isCancelledBlock isRasterizing:(BOOL)isRasterizing
|
||||
{
|
||||
CGFloat locations[3];
|
||||
NSMutableArray *colors = [NSMutableArray arrayWithCapacity:3];
|
||||
[colors addObject:(id)[[RandomCoreGraphicsNode randomColor] CGColor]];
|
||||
locations[0] = 0.0;
|
||||
[colors addObject:(id)[[RandomCoreGraphicsNode randomColor] CGColor]];
|
||||
locations[1] = 1.0;
|
||||
[colors addObject:(id)[[RandomCoreGraphicsNode randomColor] CGColor]];
|
||||
locations[2] = ( arc4random() % 256 / 256.0 );
|
||||
|
||||
|
||||
CGContextRef ctx = UIGraphicsGetCurrentContext();
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (CFArrayRef)colors, locations);
|
||||
|
||||
CGGradientDrawingOptions drawingOptions;
|
||||
CGContextDrawLinearGradient(ctx, gradient, CGPointZero, CGPointMake(bounds.size.width, bounds.size.height), drawingOptions);
|
||||
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
}
|
||||
|
||||
- (NSObject *)drawParametersForAsyncLayer:(_ASDisplayLayer *)layer
|
||||
{
|
||||
return [self description];
|
||||
}
|
||||
|
||||
- (NSDictionary *)textStyle
|
||||
{
|
||||
UIFont *font = [UIFont fontWithName:@"HelveticaNeue" size:36.0f];
|
||||
|
||||
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
|
||||
style.paragraphSpacing = 0.5 * font.lineHeight;
|
||||
style.hyphenationFactor = 1.0;
|
||||
|
||||
return @{ NSFontAttributeName: font,
|
||||
NSParagraphStyleAttributeName: style };
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if (!(self = [super init])) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
_textNode = [[ASTextNode alloc] init];
|
||||
_textNode.placeholderEnabled = NO;
|
||||
_textNode.attributedString = [[NSAttributedString alloc] initWithString:@"Hello, ASDK!"
|
||||
attributes:[self textStyle]];
|
||||
[self addSubnode:_textNode];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (CGSize)calculateSizeThatFits:(CGSize)constrainedSize
|
||||
{
|
||||
[_textNode measure:constrainedSize];
|
||||
return CGSizeMake(constrainedSize.width, 100);
|
||||
}
|
||||
|
||||
- (void)layout
|
||||
{
|
||||
CGSize boundsSize = self.bounds.size;
|
||||
CGSize textSize = _textNode.calculatedSize;
|
||||
CGRect textRect = CGRectMake(roundf((boundsSize.width - textSize.width) / 2.0),
|
||||
roundf((boundsSize.height - textSize.height) / 2.0),
|
||||
textSize.width,
|
||||
textSize.height);
|
||||
_textNode.frame = textRect;
|
||||
}
|
||||
|
||||
@end
|
||||
20
examples/SynchronousConcurrency/Sample/main.m
Normal file
20
examples/SynchronousConcurrency/Sample/main.m
Normal file
@@ -0,0 +1,20 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
||||
BIN
smoke-tests/Framework/Default-568h@2x.png
Normal file
BIN
smoke-tests/Framework/Default-568h@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
smoke-tests/Framework/Default-667h@2x.png
Normal file
BIN
smoke-tests/Framework/Default-667h@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
BIN
smoke-tests/Framework/Default-736h@3x.png
Normal file
BIN
smoke-tests/Framework/Default-736h@3x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
11
smoke-tests/Framework/README.md
Normal file
11
smoke-tests/Framework/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# "Framework"
|
||||
|
||||
This is a very simple pseudo-"integration test" project that links against
|
||||
AsyncDisplayKit as a dynamic framework, for Swift/Carthage users.
|
||||
|
||||
If it fails to compile, Travis CI builds will fail. To escape from such dire straits:
|
||||
|
||||
* If you've added a new class intended for public use, make sure you added its
|
||||
header to the "Public" group of the "Headers" build phase in the
|
||||
AsyncDisplayKit-iOS framework target. Note that this smoke test will only fail
|
||||
if you remembered to add your new file to the umbrella helper.
|
||||
410
smoke-tests/Framework/Sample.xcodeproj/project.pbxproj
Normal file
410
smoke-tests/Framework/Sample.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,410 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
050E7C7419D22E19004363C2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 050E7C7319D22E19004363C2 /* AppDelegate.swift */; };
|
||||
050E7C7619D22E19004363C2 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 050E7C7519D22E19004363C2 /* ViewController.swift */; };
|
||||
05DDD8DB19D2336300013C30 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 05DDD8DA19D2336300013C30 /* Default-568h@2x.png */; };
|
||||
34566CAA1BC1204100715E6B /* AsyncDisplayKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34566CA91BC1202A00715E6B /* AsyncDisplayKit.framework */; };
|
||||
34566CAB1BC1204100715E6B /* AsyncDisplayKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34566CA91BC1202A00715E6B /* AsyncDisplayKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
6C5053DB19EE266A00E385DE /* Default-667h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6C5053D919EE266A00E385DE /* Default-667h@2x.png */; };
|
||||
6C5053DC19EE266A00E385DE /* Default-736h@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6C5053DA19EE266A00E385DE /* Default-736h@3x.png */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
34566CA21BC1202A00715E6B /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 34566C9B1BC1202A00715E6B /* AsyncDisplayKit.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 058D09AC195D04C000B7D73C;
|
||||
remoteInfo = AsyncDisplayKit;
|
||||
};
|
||||
34566CA41BC1202A00715E6B /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 34566C9B1BC1202A00715E6B /* AsyncDisplayKit.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 058D09BC195D04C000B7D73C;
|
||||
remoteInfo = AsyncDisplayKitTests;
|
||||
};
|
||||
34566CA61BC1202A00715E6B /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 34566C9B1BC1202A00715E6B /* AsyncDisplayKit.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 057D02BF1AC0A66700C7AC3C;
|
||||
remoteInfo = AsyncDisplayKitTestHost;
|
||||
};
|
||||
34566CA81BC1202A00715E6B /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 34566C9B1BC1202A00715E6B /* AsyncDisplayKit.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = B35061DA1B010EDF0018CF92;
|
||||
remoteInfo = "AsyncDisplayKit-iOS";
|
||||
};
|
||||
34566CAC1BC1204100715E6B /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 34566C9B1BC1202A00715E6B /* AsyncDisplayKit.xcodeproj */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = B35061D91B010EDF0018CF92;
|
||||
remoteInfo = "AsyncDisplayKit-iOS";
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
34566CAE1BC1204100715E6B /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
34566CAB1BC1204100715E6B /* AsyncDisplayKit.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
050E7C6E19D22E19004363C2 /* Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sample.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
050E7C7219D22E19004363C2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
050E7C7319D22E19004363C2 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
050E7C7519D22E19004363C2 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||
05DDD8DA19D2336300013C30 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "../Default-568h@2x.png"; sourceTree = "<group>"; };
|
||||
34566C9B1BC1202A00715E6B /* AsyncDisplayKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = AsyncDisplayKit.xcodeproj; path = ../../AsyncDisplayKit.xcodeproj; sourceTree = "<group>"; };
|
||||
34566CAF1BC1208200715E6B /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = System/Library/Frameworks/Photos.framework; sourceTree = SDKROOT; };
|
||||
34566CB11BC1208700715E6B /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; };
|
||||
6C5053D919EE266A00E385DE /* Default-667h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-667h@2x.png"; sourceTree = SOURCE_ROOT; };
|
||||
6C5053DA19EE266A00E385DE /* Default-736h@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-736h@3x.png"; sourceTree = SOURCE_ROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
050E7C6B19D22E19004363C2 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
34566CAA1BC1204100715E6B /* AsyncDisplayKit.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
050E7C6519D22E19004363C2 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
34566C9B1BC1202A00715E6B /* AsyncDisplayKit.xcodeproj */,
|
||||
050E7C7019D22E19004363C2 /* Sample */,
|
||||
050E7C6F19D22E19004363C2 /* Products */,
|
||||
092C2001FE124604891D6E90 /* Frameworks */,
|
||||
);
|
||||
indentWidth = 2;
|
||||
sourceTree = "<group>";
|
||||
tabWidth = 2;
|
||||
usesTabs = 0;
|
||||
};
|
||||
050E7C6F19D22E19004363C2 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
050E7C6E19D22E19004363C2 /* Sample.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
050E7C7019D22E19004363C2 /* Sample */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
050E7C7319D22E19004363C2 /* AppDelegate.swift */,
|
||||
050E7C7519D22E19004363C2 /* ViewController.swift */,
|
||||
050E7C7119D22E19004363C2 /* Supporting Files */,
|
||||
);
|
||||
path = Sample;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
050E7C7119D22E19004363C2 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
050E7C7219D22E19004363C2 /* Info.plist */,
|
||||
05DDD8DA19D2336300013C30 /* Default-568h@2x.png */,
|
||||
6C5053D919EE266A00E385DE /* Default-667h@2x.png */,
|
||||
6C5053DA19EE266A00E385DE /* Default-736h@3x.png */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
092C2001FE124604891D6E90 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
34566CB11BC1208700715E6B /* AssetsLibrary.framework */,
|
||||
34566CAF1BC1208200715E6B /* Photos.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
34566C9C1BC1202A00715E6B /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
34566CA31BC1202A00715E6B /* libAsyncDisplayKit.a */,
|
||||
34566CA51BC1202A00715E6B /* AsyncDisplayKitTests.xctest */,
|
||||
34566CA71BC1202A00715E6B /* AsyncDisplayKitTestHost.app */,
|
||||
34566CA91BC1202A00715E6B /* AsyncDisplayKit.framework */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
050E7C6D19D22E19004363C2 /* Sample */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 050E7C8D19D22E1A004363C2 /* Build configuration list for PBXNativeTarget "Sample" */;
|
||||
buildPhases = (
|
||||
050E7C6A19D22E19004363C2 /* Sources */,
|
||||
050E7C6B19D22E19004363C2 /* Frameworks */,
|
||||
050E7C6C19D22E19004363C2 /* Resources */,
|
||||
34566CAE1BC1204100715E6B /* Embed Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
34566CAD1BC1204100715E6B /* PBXTargetDependency */,
|
||||
);
|
||||
name = Sample;
|
||||
productName = Sample;
|
||||
productReference = 050E7C6E19D22E19004363C2 /* Sample.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
050E7C6619D22E19004363C2 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0700;
|
||||
LastUpgradeCheck = 0700;
|
||||
ORGANIZATIONNAME = Facebook;
|
||||
TargetAttributes = {
|
||||
050E7C6D19D22E19004363C2 = {
|
||||
CreatedOnToolsVersion = 6.0.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 050E7C6919D22E19004363C2 /* Build configuration list for PBXProject "Sample" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 050E7C6519D22E19004363C2;
|
||||
productRefGroup = 050E7C6F19D22E19004363C2 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectReferences = (
|
||||
{
|
||||
ProductGroup = 34566C9C1BC1202A00715E6B /* Products */;
|
||||
ProjectRef = 34566C9B1BC1202A00715E6B /* AsyncDisplayKit.xcodeproj */;
|
||||
},
|
||||
);
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
050E7C6D19D22E19004363C2 /* Sample */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXReferenceProxy section */
|
||||
34566CA31BC1202A00715E6B /* libAsyncDisplayKit.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libAsyncDisplayKit.a;
|
||||
remoteRef = 34566CA21BC1202A00715E6B /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
34566CA51BC1202A00715E6B /* AsyncDisplayKitTests.xctest */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = wrapper.cfbundle;
|
||||
path = AsyncDisplayKitTests.xctest;
|
||||
remoteRef = 34566CA41BC1202A00715E6B /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
34566CA71BC1202A00715E6B /* AsyncDisplayKitTestHost.app */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = wrapper.application;
|
||||
path = AsyncDisplayKitTestHost.app;
|
||||
remoteRef = 34566CA61BC1202A00715E6B /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
34566CA91BC1202A00715E6B /* AsyncDisplayKit.framework */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = wrapper.framework;
|
||||
path = AsyncDisplayKit.framework;
|
||||
remoteRef = 34566CA81BC1202A00715E6B /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
/* End PBXReferenceProxy section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
050E7C6C19D22E19004363C2 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
05DDD8DB19D2336300013C30 /* Default-568h@2x.png in Resources */,
|
||||
6C5053DB19EE266A00E385DE /* Default-667h@2x.png in Resources */,
|
||||
6C5053DC19EE266A00E385DE /* Default-736h@3x.png in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
050E7C6A19D22E19004363C2 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
050E7C7619D22E19004363C2 /* ViewController.swift in Sources */,
|
||||
050E7C7419D22E19004363C2 /* AppDelegate.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
34566CAD1BC1204100715E6B /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = "AsyncDisplayKit-iOS";
|
||||
targetProxy = 34566CAC1BC1204100715E6B /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
050E7C8B19D22E1A004363C2 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
050E7C8C19D22E1A004363C2 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
050E7C8E19D22E1A004363C2 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
INFOPLIST_FILE = Sample/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.AsyncDisplayKit.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
050E7C8F19D22E1A004363C2 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
INFOPLIST_FILE = Sample/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.AsyncDisplayKit.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
050E7C6919D22E19004363C2 /* Build configuration list for PBXProject "Sample" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
050E7C8B19D22E1A004363C2 /* Debug */,
|
||||
050E7C8C19D22E1A004363C2 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
050E7C8D19D22E1A004363C2 /* Build configuration list for PBXNativeTarget "Sample" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
050E7C8E19D22E1A004363C2 /* Debug */,
|
||||
050E7C8F19D22E1A004363C2 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 050E7C6619D22E19004363C2 /* Project object */;
|
||||
}
|
||||
7
smoke-tests/Framework/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
smoke-tests/Framework/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:Sample.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0700"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "050E7C6D19D22E19004363C2"
|
||||
BuildableName = "Sample.app"
|
||||
BlueprintName = "Sample"
|
||||
ReferencedContainer = "container:Sample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "050E7C6D19D22E19004363C2"
|
||||
BuildableName = "Sample.app"
|
||||
BlueprintName = "Sample"
|
||||
ReferencedContainer = "container:Sample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "050E7C6D19D22E19004363C2"
|
||||
BuildableName = "Sample.app"
|
||||
BlueprintName = "Sample"
|
||||
ReferencedContainer = "container:Sample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "050E7C6D19D22E19004363C2"
|
||||
BuildableName = "Sample.app"
|
||||
BlueprintName = "Sample"
|
||||
ReferencedContainer = "container:Sample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
28
smoke-tests/Framework/Sample/AppDelegate.swift
Normal file
28
smoke-tests/Framework/Sample/AppDelegate.swift
Normal file
@@ -0,0 +1,28 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import UIKit
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
|
||||
let window = UIWindow(frame: UIScreen.mainScreen().bounds)
|
||||
window.backgroundColor = UIColor.whiteColor()
|
||||
window.rootViewController = ViewController(nibName: nil, bundle: nil)
|
||||
window.makeKeyAndVisible()
|
||||
self.window = window
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
36
smoke-tests/Framework/Sample/Info.plist
Normal file
36
smoke-tests/Framework/Sample/Info.plist
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
67
smoke-tests/Framework/Sample/ViewController.swift
Normal file
67
smoke-tests/Framework/Sample/ViewController.swift
Normal file
@@ -0,0 +1,67 @@
|
||||
/* This file provided by Facebook is for non-commercial testing and evaluation
|
||||
* purposes only. Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import UIKit
|
||||
import AsyncDisplayKit
|
||||
|
||||
class ViewController: UIViewController, ASTableViewDataSource, ASTableViewDelegate {
|
||||
|
||||
var tableView: ASTableView
|
||||
|
||||
|
||||
// MARK: UIViewController.
|
||||
|
||||
override required init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
|
||||
self.tableView = ASTableView()
|
||||
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
|
||||
self.tableView.asyncDataSource = self
|
||||
self.tableView.asyncDelegate = self
|
||||
}
|
||||
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
fatalError("storyboards are incompatible with truth and beauty")
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.view.addSubview(self.tableView)
|
||||
}
|
||||
|
||||
override func viewWillLayoutSubviews() {
|
||||
self.tableView.frame = self.view.bounds
|
||||
}
|
||||
|
||||
override func prefersStatusBarHidden() -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
// MARK: ASTableView data source and delegate.
|
||||
|
||||
func tableView(tableView: ASTableView!, nodeForRowAtIndexPath indexPath: NSIndexPath!) -> ASCellNode! {
|
||||
let patter = NSString(format: "[%ld.%ld] says hello!", indexPath.section, indexPath.row)
|
||||
let node = ASTextCellNode()
|
||||
node.text = patter as String
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
|
||||
return 20
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user